refactor libcrypto initialisation

Don't call OpenSSL_add_all_algorithms() unless OpenSSL actually
supports it.

Move all libcrypto initialisation to a single function, and call that
from seed_rng() that is called early in each tool's main().

Prompted by patch from Rosen Penev
This commit is contained in:
Damien Miller 2018-11-23 10:40:06 +11:00
parent 5b60b6c020
commit 42c5ec4b97
16 changed files with 63 additions and 93 deletions

View File

@ -2671,8 +2671,8 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([if programs using OpenSSL functions will link]) AC_MSG_CHECKING([if programs using OpenSSL functions will link])
AC_LINK_IFELSE( AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]], [AC_LANG_PROGRAM([[ #include <openssl/err.h> ]],
[[ OpenSSL_add_all_algorithms(); ]])], [[ ERR_load_crypto_strings(); ]])],
[ [
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
], ],
@ -2682,8 +2682,8 @@ if test "x$openssl" = "xyes" ; then
LIBS="$LIBS -ldl" LIBS="$LIBS -ldl"
AC_MSG_CHECKING([if programs using OpenSSL need -ldl]) AC_MSG_CHECKING([if programs using OpenSSL need -ldl])
AC_LINK_IFELSE( AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]], [AC_LANG_PROGRAM([[ #include <openssl/err.h> ]],
[[ OpenSSL_add_all_algorithms(); ]])], [[ ERR_load_crypto_strings(); ]])],
[ [
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
], ],
@ -2698,15 +2698,16 @@ if test "x$openssl" = "xyes" ; then
AC_CHECK_FUNCS([ \ AC_CHECK_FUNCS([ \
BN_is_prime_ex \ BN_is_prime_ex \
DSA_generate_parameters_ex \ DSA_generate_parameters_ex \
EVP_DigestInit_ex \ EVP_CIPHER_CTX_ctrl \
EVP_DigestFinal_ex \ EVP_DigestFinal_ex \
EVP_MD_CTX_init \ EVP_DigestInit_ex \
EVP_MD_CTX_cleanup \ EVP_MD_CTX_cleanup \
EVP_MD_CTX_copy_ex \ EVP_MD_CTX_copy_ex \
EVP_MD_CTX_init \
HMAC_CTX_init \ HMAC_CTX_init \
OpenSSL_add_all_algorithms \
RSA_generate_key_ex \ RSA_generate_key_ex \
RSA_get_default_method \ RSA_get_default_method \
EVP_CIPHER_CTX_ctrl \
]) ])
# LibreSSL/OpenSSL 1.1x API # LibreSSL/OpenSSL 1.1x API
AC_CHECK_FUNCS([ \ AC_CHECK_FUNCS([ \

View File

@ -56,6 +56,8 @@
#include "sshbuf.h" #include "sshbuf.h"
#include "ssherr.h" #include "ssherr.h"
#define RANDOM_SEED_SIZE 48
/* /*
* Portable OpenSSH PRNG seeding: * Portable OpenSSH PRNG seeding:
* If OpenSSL has not "internally seeded" itself (e.g. pulled data from * If OpenSSL has not "internally seeded" itself (e.g. pulled data from
@ -64,8 +66,6 @@
*/ */
#ifndef OPENSSL_PRNG_ONLY #ifndef OPENSSL_PRNG_ONLY
#define RANDOM_SEED_SIZE 48
/* /*
* Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
* listening either on 'tcp_port', or via Unix domain socket at * * listening either on 'tcp_port', or via Unix domain socket at *
@ -216,9 +216,11 @@ rexec_recv_rng_seed(struct sshbuf *m)
void void
seed_rng(void) seed_rng(void)
{ {
#ifndef OPENSSL_PRNG_ONLY
unsigned char buf[RANDOM_SEED_SIZE]; unsigned char buf[RANDOM_SEED_SIZE];
#endif
/* Initialise libcrypto */
ssh_libcrypto_init();
if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER,
OpenSSL_version_num())) OpenSSL_version_num()))
fatal("OpenSSL version mismatch. Built against %lx, you " fatal("OpenSSL version mismatch. Built against %lx, you "
@ -226,27 +228,34 @@ seed_rng(void)
OpenSSL_version_num()); OpenSSL_version_num());
#ifndef OPENSSL_PRNG_ONLY #ifndef OPENSSL_PRNG_ONLY
if (RAND_status() == 1) { if (RAND_status() == 1)
debug3("RNG is ready, skipping seeding"); debug3("RNG is ready, skipping seeding");
return; else {
if (seed_from_prngd(buf, sizeof(buf)) == -1)
fatal("Could not obtain seed from PRNGd");
RAND_add(buf, sizeof(buf), sizeof(buf));
} }
if (seed_from_prngd(buf, sizeof(buf)) == -1)
fatal("Could not obtain seed from PRNGd");
RAND_add(buf, sizeof(buf), sizeof(buf));
memset(buf, '\0', sizeof(buf));
#endif /* OPENSSL_PRNG_ONLY */ #endif /* OPENSSL_PRNG_ONLY */
if (RAND_status() != 1) if (RAND_status() != 1)
fatal("PRNG is not seeded"); fatal("PRNG is not seeded");
/* Ensure arc4random() is primed */
arc4random_buf(buf, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
} }
#else /* WITH_OPENSSL */ #else /* WITH_OPENSSL */
/* Handled in arc4random() */ /* Acutal initialisation is handled in arc4random() */
void void
seed_rng(void) seed_rng(void)
{ {
unsigned char buf[RANDOM_SEED_SIZE];
/* Ensure arc4random() is primed */
arc4random_buf(buf, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
} }
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */

View File

@ -66,26 +66,31 @@ ssh_compatible_openssl(long headerver, long libver)
return 0; return 0;
} }
#ifdef USE_OPENSSL_ENGINE
void void
ssh_OpenSSL_add_all_algorithms(void) ssh_libcrypto_init(void)
{ {
#if defined(HAVE_OPENSSL_ADD_ALL_ALGORITHMS)
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
#elif defined(HAVE_OPENSSL_INIT_CRYPTO) && \
defined(OPENSSL_INIT_ADD_ALL_CIPHERS) && \
defined(OPENSSL_INIT_ADD_ALL_DIGESTS)
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |
OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
#endif
#ifdef USE_OPENSSL_ENGINE
/* Enable use of crypto hardware */ /* Enable use of crypto hardware */
ENGINE_load_builtin_engines(); ENGINE_load_builtin_engines();
ENGINE_register_all_complete(); ENGINE_register_all_complete();
#if defined(HAVE_OPENSSL_INIT_CRYPTO) && \ /* Load the libcrypto config file to pick up engines defined there */
defined(OPENSSL_INIT_ADD_ALL_CIPHERS) && \ # if defined(HAVE_OPENSSL_INIT_CRYPTO) && defined(OPENSSL_INIT_LOAD_CONFIG)
defined(OPENSSL_INIT_ADD_ALL_DIGESTS) && \
defined(OPENSSL_INIT_LOAD_CONFIG)
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |
OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL); OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL);
#else # else
OPENSSL_config(NULL); OPENSSL_config(NULL);
#endif # endif
#endif /* USE_OPENSSL_ENGINE */
} }
#endif
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */

View File

@ -31,6 +31,7 @@
#include <openssl/dh.h> #include <openssl/dh.h>
int ssh_compatible_openssl(long, long); int ssh_compatible_openssl(long, long);
void ssh_libcrypto_init(void);
#if (OPENSSL_VERSION_NUMBER < 0x1000100fL) #if (OPENSSL_VERSION_NUMBER < 0x1000100fL)
# error OpenSSL 1.0.1 or greater is required # error OpenSSL 1.0.1 or greater is required
@ -92,27 +93,6 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
# endif # endif
#endif #endif
/*
* We overload some of the OpenSSL crypto functions with ssh_* equivalents
* to automatically handle OpenSSL engine initialisation.
*
* In order for the compat library to call the real functions, it must
* define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and
* implement the ssh_* equivalents.
*/
#ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS
# ifdef USE_OPENSSL_ENGINE
# ifdef OpenSSL_add_all_algorithms
# undef OpenSSL_add_all_algorithms
# endif
# define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms()
# endif
void ssh_OpenSSL_add_all_algorithms(void);
#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */
/* LibreSSL/OpenSSL 1.1x API compat */ /* LibreSSL/OpenSSL 1.1x API compat */
#ifndef HAVE_DSA_GET0_PQG #ifndef HAVE_DSA_GET0_PQG
void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q,

View File

@ -7,8 +7,6 @@
#include "includes.h" #include "includes.h"
#include <openssl/evp.h>
#include "../test_helper/test_helper.h" #include "../test_helper/test_helper.h"
void sshkey_tests(void); void sshkey_tests(void);
@ -18,9 +16,6 @@ void sshkey_fuzz_tests(void);
void void
tests(void) tests(void)
{ {
OpenSSL_add_all_algorithms();
ERR_load_CRYPTO_strings();
sshkey_tests(); sshkey_tests();
sshkey_file_tests(); sshkey_file_tests();
sshkey_fuzz_tests(); sshkey_fuzz_tests();

View File

@ -35,11 +35,13 @@
#include <signal.h> #include <signal.h>
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/err.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
# include <vis.h> # include <vis.h>
#endif #endif
#include "entropy.h"
#include "test_helper.h" #include "test_helper.h"
#include "atomicio.h" #include "atomicio.h"
@ -123,6 +125,9 @@ main(int argc, char **argv)
{ {
int ch; int ch;
seed_rng();
ERR_load_CRYPTO_strings();
/* Handle systems without __progname */ /* Handle systems without __progname */
if (__progname == NULL) { if (__progname == NULL) {
__progname = strrchr(argv[0], '/'); __progname = strrchr(argv[0], '/');

2
scp.c
View File

@ -400,6 +400,8 @@ main(int argc, char **argv)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd(); sanitise_stdfd();
seed_rng();
msetlocale(); msetlocale();
/* Copy argv, because we modify it */ /* Copy argv, because we modify it */

View File

@ -43,6 +43,8 @@ main(int argc, char **argv)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd(); sanitise_stdfd();
seed_rng();
if ((user_pw = getpwuid(getuid())) == NULL) { if ((user_pw = getpwuid(getuid())) == NULL) {
fprintf(stderr, "No user found for uid %lu\n", fprintf(stderr, "No user found for uid %lu\n",
(u_long)getuid()); (u_long)getuid());

2
sftp.c
View File

@ -2367,6 +2367,8 @@ main(int argc, char **argv)
sanitise_stdfd(); sanitise_stdfd();
msetlocale(); msetlocale();
seed_rng();
__progname = ssh_get_progname(argv[0]); __progname = ssh_get_progname(argv[0]);
memset(&args, '\0', sizeof(args)); memset(&args, '\0', sizeof(args));
args.list = NULL; args.list = NULL;

View File

@ -544,10 +544,6 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]); __progname = ssh_get_progname(argv[0]);
seed_rng(); seed_rng();
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
#endif
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
/* First, get a connection to the authentication agent. */ /* First, get a connection to the authentication agent. */

View File

@ -1095,10 +1095,6 @@ main(int ac, char **av)
if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
fatal("%s: getrlimit: %s", __progname, strerror(errno)); fatal("%s: getrlimit: %s", __progname, strerror(errno));
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
#endif
__progname = ssh_get_progname(av[0]); __progname = ssh_get_progname(av[0]);
seed_rng(); seed_rng();

View File

@ -2459,13 +2459,10 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]); __progname = ssh_get_progname(argv[0]);
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
#endif
log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
seed_rng(); seed_rng();
log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
msetlocale(); msetlocale();
/* we need this for the home * directory. */ /* we need this for the home * directory. */

View File

@ -174,9 +174,6 @@ main(int argc, char **argv)
u_char *signature, *data, rver; u_char *signature, *data, rver;
char *host, *fp; char *host, *fp;
size_t slen, dlen; size_t slen, dlen;
#ifdef WITH_OPENSSL
u_int32_t rnd[256];
#endif
ssh_malloc_init(); /* must be called before any mallocs */ ssh_malloc_init(); /* must be called before any mallocs */
if (pledge("stdio rpath getpw dns id", NULL) != 0) if (pledge("stdio rpath getpw dns id", NULL) != 0)
@ -224,12 +221,6 @@ main(int argc, char **argv)
if (found == 0) if (found == 0)
fatal("could not open any host key"); fatal("could not open any host key");
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
arc4random_buf(rnd, sizeof(rnd));
RAND_seed(rnd, sizeof(rnd));
#endif
found = 0; found = 0;
for (i = 0; i < NUM_KEYTYPES; i++) { for (i = 0; i < NUM_KEYTYPES; i++) {
keys[i] = NULL; keys[i] = NULL;

9
ssh.c
View File

@ -610,6 +610,8 @@ main(int ac, char **av)
av = saved_av; av = saved_av;
#endif #endif
seed_rng();
/* /*
* Discard other fds that are hanging around. These can cause problem * Discard other fds that are hanging around. These can cause problem
* with backgrounded ssh processes started by ControlPersist. * with backgrounded ssh processes started by ControlPersist.
@ -1036,11 +1038,6 @@ main(int ac, char **av)
host_arg = xstrdup(host); host_arg = xstrdup(host);
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
#endif
/* Initialize the command to execute on remote host. */ /* Initialize the command to execute on remote host. */
if ((command = sshbuf_new()) == NULL) if ((command = sshbuf_new()) == NULL)
fatal("sshbuf_new failed"); fatal("sshbuf_new failed");
@ -1264,8 +1261,6 @@ main(int ac, char **av)
tty_flag = 0; tty_flag = 0;
} }
seed_rng();
if (options.user == NULL) if (options.user == NULL)
options.user = xstrdup(pw->pw_name); options.user = xstrdup(pw->pw_name);

View File

@ -81,9 +81,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
int r; int r;
if (!called) { if (!called) {
#ifdef WITH_OPENSSL seed_rng();
OpenSSL_add_all_algorithms();
#endif /* WITH_OPENSSL */
called = 1; called = 1;
} }

8
sshd.c
View File

@ -1510,6 +1510,8 @@ main(int ac, char **av)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd(); sanitise_stdfd();
seed_rng();
/* Initialize configuration options to their default values. */ /* Initialize configuration options to their default values. */
initialize_server_options(&options); initialize_server_options(&options);
@ -1631,10 +1633,6 @@ main(int ac, char **av)
else else
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
#endif
/* If requested, redirect the logs to the specified logfile. */ /* If requested, redirect the logs to the specified logfile. */
if (logfile != NULL) if (logfile != NULL)
log_redirect_stderr_to(logfile); log_redirect_stderr_to(logfile);
@ -1677,8 +1675,6 @@ main(int ac, char **av)
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
cfg, NULL); cfg, NULL);
seed_rng();
/* Fill in default values for those options not explicitly set. */ /* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options); fill_default_server_options(&options);