From a65784c9f9c5d00cf1a0e235090170abc8d07c73 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Tue, 23 Oct 2018 05:56:35 +0000 Subject: upstream: refer to OpenSSL not SSLeay; we're old, but we don't have to act it OpenBSD-Commit-ID: 9ca38d11f8ed19e61a55108d1e892d696cee08ec --- sshd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sshd.c') diff --git a/sshd.c b/sshd.c index ba26287ba..66e79a3d2 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.516 2018/09/21 12:23:17 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.517 2018/10/23 05:56:35 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -917,7 +917,7 @@ usage(void) fprintf(stderr, "%s, %s\n", SSH_RELEASE, #ifdef WITH_OPENSSL - SSLeay_version(SSLEAY_VERSION) + OpenSSL_version(OPENSSL_VERSION) #else "without OpenSSL" #endif @@ -1723,7 +1723,7 @@ main(int ac, char **av) debug("sshd version %s, %s", SSH_VERSION, #ifdef WITH_OPENSSL - SSLeay_version(SSLEAY_VERSION) + OpenSSL_version(OPENSSL_VERSION) #else "without OpenSSL" #endif -- cgit v1.2.3 From 2a35862e664afde774d4a72497d394fe7306ccb5 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 16 Nov 2018 03:26:01 +0000 Subject: upstream: use path_absolute() for pathname checks; from Manoj Ampalam OpenBSD-Commit-ID: 482ce71a5ea5c5f3bc4d00fd719481a6a584d925 --- auth.c | 6 +++--- misc.c | 9 ++++++++- misc.h | 3 ++- readconf.c | 4 ++-- servconf.c | 4 ++-- session.c | 4 ++-- sftp.c | 8 ++++---- sshd.c | 4 ++-- 8 files changed, 25 insertions(+), 17 deletions(-) (limited to 'sshd.c') diff --git a/auth.c b/auth.c index 3ca3762cc..18d0857ff 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.133 2018/09/12 01:19:12 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.134 2018/11/16 03:26:01 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -437,7 +437,7 @@ expand_authorized_keys(const char *filename, struct passwd *pw) * Ensure that filename starts anchored. If not, be backward * compatible and prepend the '%h/' */ - if (*file == '/') + if (path_absolute(file)) return (file); i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file); @@ -893,7 +893,7 @@ subprocess(const char *tag, struct passwd *pw, const char *command, * If executing an explicit binary, then verify the it exists * and appears safe-ish to execute */ - if (*av[0] != '/') { + if (!path_absolute(av[0])) { error("%s path is not absolute", tag); return 0; } diff --git a/misc.c b/misc.c index bdc06fdb3..dd74c8d45 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.133 2018/10/05 14:26:09 naddy Exp $ */ +/* $OpenBSD: misc.c,v 1.134 2018/11/16 03:26:01 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -2037,3 +2037,10 @@ format_absolute_time(uint64_t t, char *buf, size_t len) localtime_r(&tt, &tm); strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); } + +/* check if path is absolute */ +int +path_absolute(const char *path) +{ + return (*path == '/') ? 1 : 0; +} diff --git a/misc.h b/misc.h index 31b207a8d..bcae6a509 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.75 2018/10/03 06:38:35 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.76 2018/11/16 03:26:01 djm Exp $ */ /* * Author: Tatu Ylonen @@ -78,6 +78,7 @@ int valid_env_name(const char *); const char *atoi_err(const char *, int *); int parse_absolute_time(const char *, uint64_t *); void format_absolute_time(uint64_t, char *, size_t); +int path_absolute(const char *); void sock_set_v6only(int); diff --git a/readconf.c b/readconf.c index 433811521..7850f2f59 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.300 2018/10/05 14:26:09 naddy Exp $ */ +/* $OpenBSD: readconf.c,v 1.301 2018/11/16 03:26:01 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1521,7 +1521,7 @@ parse_keytypes: if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) fatal("%.200s line %d: bad include path %s.", filename, linenum, arg); - if (*arg != '/' && *arg != '~') { + if (!path_absolute(arg) && *arg != '~') { xasprintf(&arg2, "%s/%s", (flags & SSHCONF_USERCONF) ? "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); diff --git a/servconf.c b/servconf.c index 932d363bb..a8727c0fa 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.342 2018/09/20 23:40:16 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.343 2018/11/16 03:26:01 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -702,7 +702,7 @@ derelativise_path(const char *path) if (strcasecmp(path, "none") == 0) return xstrdup("none"); expanded = tilde_expand_filename(path, getuid()); - if (*expanded == '/') + if (path_absolute(expanded)) return expanded; if (getcwd(cwd, sizeof(cwd)) == NULL) fatal("%s: getcwd: %s", __func__, strerror(errno)); diff --git a/session.c b/session.c index 2d0958d11..a3f0b3562 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.307 2018/10/04 00:10:11 djm Exp $ */ +/* $OpenBSD: session.c,v 1.308 2018/11/16 03:26:01 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -1334,7 +1334,7 @@ safely_chroot(const char *path, uid_t uid) char component[PATH_MAX]; struct stat st; - if (*path != '/') + if (!path_absolute(path)) fatal("chroot path does not begin at root"); if (strlen(path) >= sizeof(component)) fatal("chroot path too long"); diff --git a/sftp.c b/sftp.c index e3091969c..ed95cf817 100644 --- a/sftp.c +++ b/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.187 2018/11/16 02:30:20 djm Exp $ */ +/* $OpenBSD: sftp.c,v 1.188 2018/11/16 03:26:01 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -389,7 +389,7 @@ make_absolute(char *p, const char *pwd) char *abs_str; /* Derelativise */ - if (p && p[0] != '/') { + if (p && !path_absolute(p)) { abs_str = path_append(pwd, p); free(p); return(abs_str); @@ -1623,7 +1623,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, /* Strip pwd off beginning of non-absolute paths */ tmp = NULL; - if (*path1 != '/') + if (!path_absolute(path1)) tmp = *pwd; path1 = make_absolute(path1, *pwd); @@ -1951,7 +1951,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, xasprintf(&tmp, "%s*", file); /* Check if the path is absolute. */ - isabs = tmp[0] == '/'; + isabs = path_absolute(tmp); memset(&g, 0, sizeof(g)); if (remote != LOCAL) { diff --git a/sshd.c b/sshd.c index 66e79a3d2..362736977 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.517 2018/10/23 05:56:35 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.518 2018/11/16 03:26:01 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1624,7 +1624,7 @@ main(int ac, char **av) } if (rexeced_flag || inetd_flag) rexec_flag = 0; - if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/'))) + if (!test_flag && rexec_flag && !path_absolute(av[0])) fatal("sshd re-exec requires execution with an absolute path"); if (rexeced_flag) closefrom(REEXEC_MIN_FREE_FD); -- cgit v1.2.3 From 928f1231f65f88cd4c73e6e0edd63d2cf6295d77 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 19 Nov 2018 04:12:32 +0000 Subject: upstream: silence (to log level debug2) failure messages when MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loading the default hostkeys. Hostkeys explicitly specified in the configuration or on the command-line are still reported as errors, and failure to load at least one host key remains a fatal error. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on patch from Dag-Erling Smørgrav via https://github.com/openssh/openssh-portable/pull/103 ok markus@ OpenBSD-Commit-ID: ffc2e35a75d1008effaf05a5e27425041c27b684 --- servconf.c | 40 ++++++++++++++++++++++++++++------------ servconf.h | 5 +++-- sshd.c | 13 ++++++++----- 3 files changed, 39 insertions(+), 19 deletions(-) (limited to 'sshd.c') diff --git a/servconf.c b/servconf.c index a8727c0fa..52d9be429 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.343 2018/11/16 03:26:01 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.344 2018/11/19 04:12:32 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -221,26 +221,40 @@ assemble_algorithms(ServerOptions *o) } static void -array_append(const char *file, const int line, const char *directive, - char ***array, u_int *lp, const char *s) +array_append2(const char *file, const int line, const char *directive, + char ***array, int **iarray, u_int *lp, const char *s, int i) { if (*lp >= INT_MAX) fatal("%s line %d: Too many %s entries", file, line, directive); + if (iarray != NULL) { + *iarray = xrecallocarray(*iarray, *lp, *lp + 1, + sizeof(**iarray)); + (*iarray)[*lp] = i; + } + *array = xrecallocarray(*array, *lp, *lp + 1, sizeof(**array)); (*array)[*lp] = xstrdup(s); (*lp)++; } +static void +array_append(const char *file, const int line, const char *directive, + char ***array, u_int *lp, const char *s) +{ + array_append2(file, line, directive, array, NULL, lp, s, 0); +} + void servconf_add_hostkey(const char *file, const int line, - ServerOptions *options, const char *path) + ServerOptions *options, const char *path, int userprovided) { char *apath = derelativise_path(path); - array_append(file, line, "HostKey", - &options->host_key_files, &options->num_host_key_files, apath); + array_append2(file, line, "HostKey", + &options->host_key_files, &options->host_key_file_userprovided, + &options->num_host_key_files, apath, userprovided); free(apath); } @@ -268,16 +282,16 @@ fill_default_server_options(ServerOptions *options) if (options->num_host_key_files == 0) { /* fill default hostkeys for protocols */ servconf_add_hostkey("[default]", 0, options, - _PATH_HOST_RSA_KEY_FILE); + _PATH_HOST_RSA_KEY_FILE, 0); #ifdef OPENSSL_HAS_ECC servconf_add_hostkey("[default]", 0, options, - _PATH_HOST_ECDSA_KEY_FILE); + _PATH_HOST_ECDSA_KEY_FILE, 0); #endif servconf_add_hostkey("[default]", 0, options, - _PATH_HOST_ED25519_KEY_FILE); + _PATH_HOST_ED25519_KEY_FILE, 0); #ifdef WITH_XMSS servconf_add_hostkey("[default]", 0, options, - _PATH_HOST_XMSS_KEY_FILE); + _PATH_HOST_XMSS_KEY_FILE, 0); #endif /* WITH_XMSS */ } /* No certificates by default */ @@ -1355,8 +1369,10 @@ process_server_config_line(ServerOptions *options, char *line, if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); - if (*activep) - servconf_add_hostkey(filename, linenum, options, arg); + if (*activep) { + servconf_add_hostkey(filename, linenum, + options, arg, 1); + } break; case sHostKeyAgent: diff --git a/servconf.h b/servconf.h index 0175e00e8..548ad5a0c 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.137 2018/09/20 03:28:06 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.138 2018/11/19 04:12:32 djm Exp $ */ /* * Author: Tatu Ylonen @@ -75,6 +75,7 @@ typedef struct { char *routing_domain; /* Bind session to routing domain */ char **host_key_files; /* Files containing host keys. */ + int *host_key_file_userprovided; /* Key was specified by user. */ u_int num_host_key_files; /* Number of files for host keys. */ char **host_cert_files; /* Files containing host certs. */ u_int num_host_cert_files; /* Number of files for host certs. */ @@ -273,7 +274,7 @@ void copy_set_server_options(ServerOptions *, ServerOptions *, int); void dump_config(ServerOptions *); char *derelativise_path(const char *); void servconf_add_hostkey(const char *, const int, - ServerOptions *, const char *path); + ServerOptions *, const char *path, int); void servconf_add_hostcert(const char *, const int, ServerOptions *, const char *path); diff --git a/sshd.c b/sshd.c index 362736977..afd959329 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.518 2018/11/16 03:26:01 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.519 2018/11/19 04:12:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1588,7 +1588,7 @@ main(int ac, char **av) break; case 'h': servconf_add_hostkey("[command-line]", 0, - &options, optarg); + &options, optarg, 1); break; case 't': test_flag = 1; @@ -1760,15 +1760,18 @@ main(int ac, char **av) } for (i = 0; i < options.num_host_key_files; i++) { + int ll = options.host_key_file_userprovided[i] ? + SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_DEBUG1; + if (options.host_key_files[i] == NULL) continue; if ((r = sshkey_load_private(options.host_key_files[i], "", &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) - error("Error loading host key \"%s\": %s", + do_log2(ll, "Unable to load host key \"%s\": %s", options.host_key_files[i], ssh_err(r)); if ((r = sshkey_load_public(options.host_key_files[i], &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) - error("Error loading host key \"%s\": %s", + do_log2(ll, "Unable to load host key \"%s\": %s", options.host_key_files[i], ssh_err(r)); if (pubkey == NULL && key != NULL) if ((r = sshkey_from_private(key, &pubkey)) != 0) @@ -1785,7 +1788,7 @@ main(int ac, char **av) keytype = key->type; accumulate_host_timing_secret(cfg, key); } else { - error("Could not load host key: %s", + do_log2(ll, "Unable to load host key: %s", options.host_key_files[i]); sensitive_data.host_keys[i] = NULL; sensitive_data.host_pubkeys[i] = NULL; -- cgit v1.2.3 From 42c5ec4b97b6a1bae70f323952d0646af16ce710 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 23 Nov 2018 10:40:06 +1100 Subject: 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 --- configure.ac | 15 +++++++------ entropy.c | 35 ++++++++++++++++++----------- openbsd-compat/openssl-compat.c | 23 +++++++++++-------- openbsd-compat/openssl-compat.h | 22 +----------------- regress/unittests/sshkey/tests.c | 5 ----- regress/unittests/test_helper/test_helper.c | 5 +++++ scp.c | 2 ++ sftp-server-main.c | 2 ++ sftp.c | 2 ++ ssh-add.c | 4 ---- ssh-agent.c | 4 ---- ssh-keygen.c | 7 ++---- ssh-keysign.c | 9 -------- ssh.c | 9 ++------ ssh_api.c | 4 +--- sshd.c | 8 ++----- 16 files changed, 63 insertions(+), 93 deletions(-) (limited to 'sshd.c') diff --git a/configure.ac b/configure.ac index 3f7fe2cd0..5a9b3ff11 100644 --- a/configure.ac +++ b/configure.ac @@ -2671,8 +2671,8 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([if programs using OpenSSL functions will link]) AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], - [[ OpenSSL_add_all_algorithms(); ]])], + [AC_LANG_PROGRAM([[ #include ]], + [[ ERR_load_crypto_strings(); ]])], [ AC_MSG_RESULT([yes]) ], @@ -2682,8 +2682,8 @@ if test "x$openssl" = "xyes" ; then LIBS="$LIBS -ldl" AC_MSG_CHECKING([if programs using OpenSSL need -ldl]) AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], - [[ OpenSSL_add_all_algorithms(); ]])], + [AC_LANG_PROGRAM([[ #include ]], + [[ ERR_load_crypto_strings(); ]])], [ AC_MSG_RESULT([yes]) ], @@ -2698,15 +2698,16 @@ if test "x$openssl" = "xyes" ; then AC_CHECK_FUNCS([ \ BN_is_prime_ex \ DSA_generate_parameters_ex \ - EVP_DigestInit_ex \ + EVP_CIPHER_CTX_ctrl \ EVP_DigestFinal_ex \ - EVP_MD_CTX_init \ + EVP_DigestInit_ex \ EVP_MD_CTX_cleanup \ EVP_MD_CTX_copy_ex \ + EVP_MD_CTX_init \ HMAC_CTX_init \ + OpenSSL_add_all_algorithms \ RSA_generate_key_ex \ RSA_get_default_method \ - EVP_CIPHER_CTX_ctrl \ ]) # LibreSSL/OpenSSL 1.1x API AC_CHECK_FUNCS([ \ diff --git a/entropy.c b/entropy.c index fc710ec23..97e836087 100644 --- a/entropy.c +++ b/entropy.c @@ -56,6 +56,8 @@ #include "sshbuf.h" #include "ssherr.h" +#define RANDOM_SEED_SIZE 48 + /* * Portable OpenSSH PRNG seeding: * If OpenSSL has not "internally seeded" itself (e.g. pulled data from @@ -64,8 +66,6 @@ */ #ifndef OPENSSL_PRNG_ONLY -#define RANDOM_SEED_SIZE 48 - /* * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon * listening either on 'tcp_port', or via Unix domain socket at * @@ -216,9 +216,11 @@ rexec_recv_rng_seed(struct sshbuf *m) void seed_rng(void) { -#ifndef OPENSSL_PRNG_ONLY unsigned char buf[RANDOM_SEED_SIZE]; -#endif + + /* Initialise libcrypto */ + ssh_libcrypto_init(); + if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, OpenSSL_version_num())) fatal("OpenSSL version mismatch. Built against %lx, you " @@ -226,27 +228,34 @@ seed_rng(void) OpenSSL_version_num()); #ifndef OPENSSL_PRNG_ONLY - if (RAND_status() == 1) { + if (RAND_status() == 1) 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 */ + if (RAND_status() != 1) fatal("PRNG is not seeded"); + + /* Ensure arc4random() is primed */ + arc4random_buf(buf, sizeof(buf)); + explicit_bzero(buf, sizeof(buf)); } #else /* WITH_OPENSSL */ -/* Handled in arc4random() */ +/* Acutal initialisation is handled in arc4random() */ 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 */ diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c index 5ade8f0ba..d8c00ebcb 100644 --- a/openbsd-compat/openssl-compat.c +++ b/openbsd-compat/openssl-compat.c @@ -66,26 +66,31 @@ ssh_compatible_openssl(long headerver, long libver) return 0; } -#ifdef USE_OPENSSL_ENGINE void -ssh_OpenSSL_add_all_algorithms(void) +ssh_libcrypto_init(void) { +#if defined(HAVE_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 */ ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); -#if defined(HAVE_OPENSSL_INIT_CRYPTO) && \ - defined(OPENSSL_INIT_ADD_ALL_CIPHERS) && \ - defined(OPENSSL_INIT_ADD_ALL_DIGESTS) && \ - defined(OPENSSL_INIT_LOAD_CONFIG) + /* Load the libcrypto config file to pick up engines defined there */ +# if defined(HAVE_OPENSSL_INIT_CRYPTO) && defined(OPENSSL_INIT_LOAD_CONFIG) OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL); -#else +# else OPENSSL_config(NULL); -#endif +# endif +#endif /* USE_OPENSSL_ENGINE */ } -#endif #endif /* WITH_OPENSSL */ diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h index b87ce59e7..917bc6f7c 100644 --- a/openbsd-compat/openssl-compat.h +++ b/openbsd-compat/openssl-compat.h @@ -31,6 +31,7 @@ #include int ssh_compatible_openssl(long, long); +void ssh_libcrypto_init(void); #if (OPENSSL_VERSION_NUMBER < 0x1000100fL) # 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 -/* - * 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 */ #ifndef HAVE_DSA_GET0_PQG void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, diff --git a/regress/unittests/sshkey/tests.c b/regress/unittests/sshkey/tests.c index 13f265cdb..78aa9223d 100644 --- a/regress/unittests/sshkey/tests.c +++ b/regress/unittests/sshkey/tests.c @@ -7,8 +7,6 @@ #include "includes.h" -#include - #include "../test_helper/test_helper.h" void sshkey_tests(void); @@ -18,9 +16,6 @@ void sshkey_fuzz_tests(void); void tests(void) { - OpenSSL_add_all_algorithms(); - ERR_load_CRYPTO_strings(); - sshkey_tests(); sshkey_file_tests(); sshkey_fuzz_tests(); diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c index cd08b5778..6b4f343a8 100644 --- a/regress/unittests/test_helper/test_helper.c +++ b/regress/unittests/test_helper/test_helper.c @@ -35,11 +35,13 @@ #include #include +#include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) # include #endif +#include "entropy.h" #include "test_helper.h" #include "atomicio.h" @@ -123,6 +125,9 @@ main(int argc, char **argv) { int ch; + seed_rng(); + ERR_load_CRYPTO_strings(); + /* Handle systems without __progname */ if (__progname == NULL) { __progname = strrchr(argv[0], '/'); diff --git a/scp.c b/scp.c index 4f3fdcd3d..eb17c3416 100644 --- a/scp.c +++ b/scp.c @@ -400,6 +400,8 @@ main(int argc, char **argv) /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); + seed_rng(); + msetlocale(); /* Copy argv, because we modify it */ diff --git a/sftp-server-main.c b/sftp-server-main.c index c6ccd623e..6230d897d 100644 --- a/sftp-server-main.c +++ b/sftp-server-main.c @@ -43,6 +43,8 @@ main(int argc, char **argv) /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); + seed_rng(); + if ((user_pw = getpwuid(getuid())) == NULL) { fprintf(stderr, "No user found for uid %lu\n", (u_long)getuid()); diff --git a/sftp.c b/sftp.c index ed95cf817..f886b330b 100644 --- a/sftp.c +++ b/sftp.c @@ -2367,6 +2367,8 @@ main(int argc, char **argv) sanitise_stdfd(); msetlocale(); + seed_rng(); + __progname = ssh_get_progname(argv[0]); memset(&args, '\0', sizeof(args)); args.list = NULL; diff --git a/ssh-add.c b/ssh-add.c index 627c02983..50165e7d6 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -544,10 +544,6 @@ main(int argc, char **argv) __progname = ssh_get_progname(argv[0]); seed_rng(); -#ifdef WITH_OPENSSL - OpenSSL_add_all_algorithms(); -#endif - setvbuf(stdout, NULL, _IOLBF, 0); /* First, get a connection to the authentication agent. */ diff --git a/ssh-agent.c b/ssh-agent.c index cb552462a..6baebc313 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1095,10 +1095,6 @@ main(int ac, char **av) if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) fatal("%s: getrlimit: %s", __progname, strerror(errno)); -#ifdef WITH_OPENSSL - OpenSSL_add_all_algorithms(); -#endif - __progname = ssh_get_progname(av[0]); seed_rng(); diff --git a/ssh-keygen.c b/ssh-keygen.c index 416d25be0..a67737350 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -2459,13 +2459,10 @@ main(int argc, char **argv) __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(); + log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + msetlocale(); /* we need this for the home * directory. */ diff --git a/ssh-keysign.c b/ssh-keysign.c index bcd1508c0..8f487b8c5 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -174,9 +174,6 @@ main(int argc, char **argv) u_char *signature, *data, rver; char *host, *fp; size_t slen, dlen; -#ifdef WITH_OPENSSL - u_int32_t rnd[256]; -#endif ssh_malloc_init(); /* must be called before any mallocs */ if (pledge("stdio rpath getpw dns id", NULL) != 0) @@ -224,12 +221,6 @@ main(int argc, char **argv) if (found == 0) 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; for (i = 0; i < NUM_KEYTYPES; i++) { keys[i] = NULL; diff --git a/ssh.c b/ssh.c index 1e471f5c4..1ac903d16 100644 --- a/ssh.c +++ b/ssh.c @@ -610,6 +610,8 @@ main(int ac, char **av) av = saved_av; #endif + seed_rng(); + /* * Discard other fds that are hanging around. These can cause problem * with backgrounded ssh processes started by ControlPersist. @@ -1036,11 +1038,6 @@ main(int ac, char **av) host_arg = xstrdup(host); -#ifdef WITH_OPENSSL - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); -#endif - /* Initialize the command to execute on remote host. */ if ((command = sshbuf_new()) == NULL) fatal("sshbuf_new failed"); @@ -1264,8 +1261,6 @@ main(int ac, char **av) tty_flag = 0; } - seed_rng(); - if (options.user == NULL) options.user = xstrdup(pw->pw_name); diff --git a/ssh_api.c b/ssh_api.c index e727c0d69..53bbc9b49 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -81,9 +81,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) int r; if (!called) { -#ifdef WITH_OPENSSL - OpenSSL_add_all_algorithms(); -#endif /* WITH_OPENSSL */ + seed_rng(); called = 1; } diff --git a/sshd.c b/sshd.c index afd959329..fb9d9b60f 100644 --- a/sshd.c +++ b/sshd.c @@ -1510,6 +1510,8 @@ main(int ac, char **av) /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); + seed_rng(); + /* Initialize configuration options to their default values. */ initialize_server_options(&options); @@ -1631,10 +1633,6 @@ main(int ac, char **av) else closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); -#ifdef WITH_OPENSSL - OpenSSL_add_all_algorithms(); -#endif - /* If requested, redirect the logs to the specified logfile. */ if (logfile != NULL) log_redirect_stderr_to(logfile); @@ -1677,8 +1675,6 @@ main(int ac, char **av) parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, cfg, NULL); - seed_rng(); - /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); -- cgit v1.2.3 From 0a843d9a0e805f14653a555f5c7a8ba99d62c12d Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 27 Dec 2018 03:25:24 +0000 Subject: upstream: move client/server SSH-* banners to buffers under ssh->kex and factor out the banner exchange. This eliminates some common code from the client and server. Also be more strict about handling \r characters - these should only be accepted immediately before \n (pointed out by Jann Horn). Inspired by a patch from Markus Schmidt. (lots of) feedback and ok markus@ OpenBSD-Commit-ID: 1cc7885487a6754f63641d7d3279b0941890275b --- .depend | 6 +- Makefile.in | 2 +- atomicio.h | 4 +- kex.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ kex.h | 20 ++-- kexc25519.c | 10 +- kexc25519c.c | 6 +- kexc25519s.c | 6 +- kexdh.c | 10 +- kexdhc.c | 6 +- kexdhs.c | 6 +- kexecdh.c | 10 +- kexecdhc.c | 6 +- kexecdhs.c | 6 +- kexgex.c | 10 +- kexgexc.c | 6 +- kexgexs.c | 6 +- misc.c | 77 ++++++++++++++- misc.h | 5 +- packet.c | 42 ++++----- ssh.c | 4 +- ssh.h | 6 +- ssh_api.c | 125 ++++++++++++++----------- sshconnect.c | 187 ++----------------------------------- sshconnect.h | 15 ++- sshconnect2.c | 49 +++++----- sshd.c | 118 +---------------------- 27 files changed, 548 insertions(+), 494 deletions(-) (limited to 'sshd.c') diff --git a/.depend b/.depend index f85557c9c..193130f5d 100644 --- a/.depend +++ b/.depend @@ -60,8 +60,8 @@ gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-comp hash.o: crypto_api.h includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest.h log.h ssherr.h hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h misc.h ssherr.h digest.h hmac.h -kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h log.h match.h misc.h monitor.h ssherr.h sshbuf.h -kex.o: digest.h +kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h ssh2.h atomicio.h version.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h log.h match.h misc.h +kex.o: monitor.h ssherr.h sshbuf.h digest.h kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h digest.h ssherr.h kexc25519c.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h digest.h ssherr.h kexc25519s.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h ssherr.h @@ -149,7 +149,7 @@ sshbuf-getput-crypto.o: includes.h config.h defines.h platform.h openbsd-compat/ sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h sshkey.h sshconnect.h log.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h -sshconnect.o: ssherr.h authfd.h +sshconnect.o: ssherr.h authfd.h kex.h mac.h sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h myproposal.h sshconnect2.o: sshconnect.h authfile.h dh.h authfd.h log.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h ssherr.h utf8.h sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h opacket.h log.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h diff --git a/Makefile.in b/Makefile.in index 126b2c742..6ffccb482 100644 --- a/Makefile.in +++ b/Makefile.in @@ -186,7 +186,7 @@ ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o +ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o compat.o $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o diff --git a/atomicio.h b/atomicio.h index 0d728ac86..8b3cc6e21 100644 --- a/atomicio.h +++ b/atomicio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: atomicio.h,v 1.11 2010/09/22 22:58:51 djm Exp $ */ +/* $OpenBSD: atomicio.h,v 1.12 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2006 Damien Miller. All rights reserved. @@ -29,6 +29,8 @@ #ifndef _ATOMICIO_H #define _ATOMICIO_H +struct iovec; + /* * Ensure all of data on socket comes through. f==read || f==vwrite */ diff --git a/kex.c b/kex.c index 3823a9544..30e1c261d 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.142 2018/12/07 03:39:40 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.143 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -25,19 +25,25 @@ #include "includes.h" - +#include +#include #include #include #include #include #include +#include +#include #ifdef WITH_OPENSSL #include #include #endif +#include "ssh.h" #include "ssh2.h" +#include "atomicio.h" +#include "version.h" #include "packet.h" #include "compat.h" #include "cipher.h" @@ -578,32 +584,20 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) return SSH_ERR_INTERNAL_ERROR; } -int -kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp) +struct kex * +kex_new(void) { struct kex *kex; - int r; - *kexp = NULL; - if ((kex = calloc(1, sizeof(*kex))) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((kex->peer = sshbuf_new()) == NULL || - (kex->my = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kex_prop2buf(kex->my, proposal)) != 0) - goto out; - kex->done = 0; - kex->flags = KEX_INITIAL; - kex_reset_dispatch(ssh); - ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); - r = 0; - *kexp = kex; - out: - if (r != 0) + if ((kex = calloc(1, sizeof(*kex))) == NULL || + (kex->peer = sshbuf_new()) == NULL || + (kex->my = sshbuf_new()) == NULL || + (kex->client_version = sshbuf_new()) == NULL || + (kex->server_version = sshbuf_new()) == NULL) { kex_free(kex); - return r; + return NULL; + } + return kex; } void @@ -642,6 +636,9 @@ kex_free(struct kex *kex) { u_int mode; + if (kex == NULL) + return; + #ifdef WITH_OPENSSL DH_free(kex->dh); #ifdef OPENSSL_HAS_ECC @@ -654,21 +651,34 @@ kex_free(struct kex *kex) } sshbuf_free(kex->peer); sshbuf_free(kex->my); + sshbuf_free(kex->client_version); + sshbuf_free(kex->server_version); free(kex->session_id); - free(kex->client_version_string); - free(kex->server_version_string); free(kex->failed_choice); free(kex->hostkey_alg); free(kex->name); free(kex); } +int +kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) +{ + int r; + + if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0) + return r; + ssh->kex->flags = KEX_INITIAL; + kex_reset_dispatch(ssh); + ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); + return 0; +} + int kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) { int r; - if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) + if ((r = kex_ready(ssh, proposal)) != 0) return r; if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ kex_free(ssh->kex); @@ -1043,3 +1053,233 @@ dump_digest(char *msg, u_char *digest, int len) sshbuf_dump_data(digest, len, stderr); } #endif + +/* + * Send a plaintext error message to the peer, suffixed by \r\n. + * Only used during banner exchange, and there only for the server. + */ +static void +send_error(struct ssh *ssh, char *msg) +{ + char *crnl = "\r\n"; + + if (!ssh->kex->server) + return; + + if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), + msg, strlen(msg)) != strlen(msg) || + atomicio(vwrite, ssh_packet_get_connection_out(ssh), + crnl, strlen(crnl)) != strlen(crnl)) + error("%s: write: %.100s", __func__, strerror(errno)); +} + +/* + * Sends our identification string and waits for the peer's. Will block for + * up to timeout_ms (or indefinitely if timeout_ms <= 0). + * Returns on 0 success or a ssherr.h code on failure. + */ +int +kex_exchange_identification(struct ssh *ssh, int timeout_ms, + const char *version_addendum) +{ + int remote_major, remote_minor, mismatch; + size_t len, i, n; + int r, expect_nl; + u_char c; + struct sshbuf *our_version = ssh->kex->server ? + ssh->kex->server_version : ssh->kex->client_version; + struct sshbuf *peer_version = ssh->kex->server ? + ssh->kex->client_version : ssh->kex->server_version; + char *our_version_string = NULL, *peer_version_string = NULL; + char *cp, *remote_version = NULL; + + /* Prepare and send our banner */ + sshbuf_reset(our_version); + if (version_addendum != NULL && *version_addendum == '\0') + version_addendum = NULL; + if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n", + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, + version_addendum == NULL ? "" : " ", + version_addendum == NULL ? "" : version_addendum)) != 0) { + error("%s: sshbuf_putf: %s", __func__, ssh_err(r)); + goto out; + } + + if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), + sshbuf_mutable_ptr(our_version), + sshbuf_len(our_version)) != sshbuf_len(our_version)) { + error("%s: write: %.100s", __func__, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */ + error("%s: sshbuf_consume_end: %s", __func__, ssh_err(r)); + goto out; + } + our_version_string = sshbuf_dup_string(our_version); + if (our_version_string == NULL) { + error("%s: sshbuf_dup_string failed", __func__); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + debug("Local version string %.100s", our_version_string); + + /* Read other side's version identification. */ + for (n = 0; ; n++) { + if (n >= SSH_MAX_PRE_BANNER_LINES) { + send_error(ssh, "No SSH identification string " + "received."); + error("%s: No SSH version received in first %u lines " + "from server", __func__, SSH_MAX_PRE_BANNER_LINES); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + sshbuf_reset(peer_version); + expect_nl = 0; + for (i = 0; ; i++) { + if (timeout_ms > 0) { + r = waitrfd(ssh_packet_get_connection_in(ssh), + &timeout_ms); + if (r == -1 && errno == ETIMEDOUT) { + send_error(ssh, "Timed out waiting " + "for SSH identification string."); + error("Connection timed out during " + "banner exchange"); + r = SSH_ERR_CONN_TIMEOUT; + goto out; + } else if (r == -1) { + error("%s: %s", + __func__, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + } + + len = atomicio(read, ssh_packet_get_connection_in(ssh), + &c, 1); + if (len != 1 && errno == EPIPE) { + error("%s: Connection closed by remote host", + __func__); + r = SSH_ERR_CONN_CLOSED; + goto out; + } else if (len != 1) { + error("%s: read: %.100s", + __func__, strerror(errno)); + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + if (c == '\r') { + expect_nl = 1; + continue; + } + if (c == '\n') + break; + if (c == '\0' || expect_nl) { + error("%s: banner line contains invalid " + "characters", __func__); + goto invalid; + } + if ((r = sshbuf_put_u8(peer_version, c)) != 0) { + error("%s: sshbuf_put: %s", + __func__, ssh_err(r)); + goto out; + } + if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) { + error("%s: banner line too long", __func__); + goto invalid; + } + } + /* Is this an actual protocol banner? */ + if (sshbuf_len(peer_version) > 4 && + memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0) + break; + /* If not, then just log the line and continue */ + if ((cp = sshbuf_dup_string(peer_version)) == NULL) { + error("%s: sshbuf_dup_string failed", __func__); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* Do not accept lines before the SSH ident from a client */ + if (ssh->kex->server) { + error("%s: client sent invalid protocol identifier " + "\"%.256s\"", __func__, cp); + free(cp); + goto invalid; + } + debug("%s: banner line %zu: %s", __func__, n, cp); + free(cp); + } + peer_version_string = sshbuf_dup_string(peer_version); + if (peer_version_string == NULL) + error("%s: sshbuf_dup_string failed", __func__); + /* XXX must be same size for sscanf */ + if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) { + error("%s: calloc failed", __func__); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + /* + * Check that the versions match. In future this might accept + * several versions and set appropriate flags to handle them. + */ + if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n", + &remote_major, &remote_minor, remote_version) != 3) { + error("Bad remote protocol version identification: '%.100s'", + peer_version_string); + invalid: + send_error(ssh, "Invalid SSH identification string."); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + debug("Remote protocol version %d.%d, remote software version %.100s", + remote_major, remote_minor, remote_version); + ssh->compat = compat_datafellows(remote_version); + + mismatch = 0; + switch (remote_major) { + case 2: + break; + case 1: + if (remote_minor != 99) + mismatch = 1; + break; + default: + mismatch = 1; + break; + } + if (mismatch) { + error("Protocol major versions differ: %d vs. %d", + PROTOCOL_MAJOR_2, remote_major); + send_error(ssh, "Protocol major versions differ."); + r = SSH_ERR_NO_PROTOCOL_VERSION; + goto out; + } + + if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) { + logit("probed from %s port %d with %s. Don't panic.", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + peer_version_string); + r = SSH_ERR_CONN_CLOSED; /* XXX */ + goto out; + } + if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) { + logit("scanned from %s port %d with %s. Don't panic.", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + peer_version_string); + r = SSH_ERR_CONN_CLOSED; /* XXX */ + goto out; + } + if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { + logit("Remote version \"%.100s\" uses unsafe RSA signature " + "scheme; disabling use of RSA keys", remote_version); + } + /* success */ + r = 0; + out: + free(our_version_string); + free(peer_version_string); + free(remote_version); + return r; +} + diff --git a/kex.h b/kex.h index 0f67f58db..9ba860954 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.92 2018/12/07 03:39:40 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.93 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -145,12 +145,12 @@ struct kex { int ext_info_c; struct sshbuf *my; struct sshbuf *peer; + struct sshbuf *client_version; + struct sshbuf *server_version; sig_atomic_t done; u_int flags; int hash_alg; int ec_nid; - char *client_version_string; - char *server_version_string; char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); @@ -173,7 +173,10 @@ char *kex_alg_list(char); char *kex_names_cat(const char *, const char *); int kex_assemble_names(char **, const char *, const char *); -int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **); +int kex_exchange_identification(struct ssh *, int, const char *); + +struct kex *kex_new(void); +int kex_ready(struct ssh *, char *[PROPOSAL_MAX]); int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); void kex_free_newkeys(struct newkeys *); void kex_free(struct kex *); @@ -199,22 +202,23 @@ int kexecdh_server(struct ssh *); int kexc25519_client(struct ssh *); int kexc25519_server(struct ssh *); -int kex_dh_hash(int, const char *, const char *, +int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); -int kexgex_hash(int, const char *, const char *, +int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, int, int, int, const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); -int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *, +int kex_ecdh_hash(int, const EC_GROUP *, + const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *); -int kex_c25519_hash(int, const char *, const char *, +int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, const u_char *, const u_char *, size_t, u_char *, size_t *); diff --git a/kexc25519.c b/kexc25519.c index 0897b8c51..712dd523d 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.10 2016/05/02 08:49:03 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.11 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -84,8 +84,8 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE], int kex_c25519_hash( int hash_alg, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -101,8 +101,8 @@ kex_c25519_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 || - (r = sshbuf_put_cstring(b, server_version_string)) < 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || diff --git a/kexc25519c.c b/kexc25519c.c index a8d92149c..75e7d8c57 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.9 2017/12/18 02:25:15 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.10 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -129,8 +129,8 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_c25519_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexc25519s.c b/kexc25519s.c index 0800a7a4b..81f816e56 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.11 2017/05/31 04:19:28 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.12 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -110,8 +110,8 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_c25519_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/kexdh.c b/kexdh.c index e6925b186..34c55ef9f 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.26 2016/05/02 10:26:04 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.27 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -46,8 +46,8 @@ int kex_dh_hash( int hash_alg, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -63,8 +63,8 @@ kex_dh_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || - (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || diff --git a/kexdhc.c b/kexdhc.c index 8b56377ad..b367832d5 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.22 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.24 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -178,8 +178,8 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_dh_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexdhs.c b/kexdhs.c index 337aab5be..adf70babd 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.27 2018/04/10 00:10:49 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -166,8 +166,8 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kex_dh_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/kexecdh.c b/kexecdh.c index 2a4fec6b1..4380427ea 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.7 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -50,8 +50,8 @@ int kex_ecdh_hash( int hash_alg, const EC_GROUP *ec_group, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -67,8 +67,8 @@ kex_ecdh_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || - (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || diff --git a/kexecdhc.c b/kexecdhc.c index ac146a362..af556dc58 100644 --- a/kexecdhc.c +++ b/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.13 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexecdhc.c,v 1.14 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -175,8 +175,8 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) if ((r = kex_ecdh_hash( kex->hash_alg, group, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexecdhs.c b/kexecdhs.c index af4f30309..c690feffe 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.17 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.18 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -145,8 +145,8 @@ input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) if ((r = kex_ecdh_hash( kex->hash_alg, group, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/kexgex.c b/kexgex.c index 3ca4bd370..a5d591b0a 100644 --- a/kexgex.c +++ b/kexgex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */ +/* $OpenBSD: kexgex.c,v 1.30 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -46,8 +46,8 @@ int kexgex_hash( int hash_alg, - const char *client_version_string, - const char *server_version_string, + const struct sshbuf *client_version, + const struct sshbuf *server_version, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, @@ -66,8 +66,8 @@ kexgex_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || - (r = sshbuf_put_cstring(b, server_version_string)) != 0 || + if ((r = sshbuf_put_stringb(b, client_version)) < 0 || + (r = sshbuf_put_stringb(b, server_version)) < 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || diff --git a/kexgexc.c b/kexgexc.c index 0d07f73c7..f2be35ab2 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.27 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -222,8 +222,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kexgex_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, diff --git a/kexgexs.c b/kexgexs.c index dc9c0bc60..cd0e758c4 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.35 2018/10/04 00:04:41 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.36 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -198,8 +198,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) hashlen = sizeof(hash); if ((r = kexgex_hash( kex->hash_alg, - kex->client_version_string, - kex->server_version_string, + kex->client_version, + kex->server_version, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, diff --git a/misc.c b/misc.c index 275e68141..bfd786ef8 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.135 2018/12/07 04:36:09 dtucker Exp $ */ +/* $OpenBSD: misc.c,v 1.136 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -38,6 +38,7 @@ #ifdef HAVE_LIBGEN_H # include #endif +#include #include #include #include @@ -234,6 +235,80 @@ set_rdomain(int fd, const char *name) #endif } +/* + * Wait up to *timeoutp milliseconds for fd to be readable. Updates + * *timeoutp with time remaining. + * Returns 0 if fd ready or -1 on timeout or error (see errno). + */ +int +waitrfd(int fd, int *timeoutp) +{ + struct pollfd pfd; + struct timeval t_start; + int oerrno, r; + + monotime_tv(&t_start); + pfd.fd = fd; + pfd.events = POLLIN; + for (; *timeoutp >= 0;) { + r = poll(&pfd, 1, *timeoutp); + oerrno = errno; + ms_subtract_diff(&t_start, timeoutp); + errno = oerrno; + if (r > 0) + return 0; + else if (r == -1 && errno != EAGAIN) + return -1; + else if (r == 0) + break; + } + /* timeout */ + errno = ETIMEDOUT; + return -1; +} + +/* + * Attempt a non-blocking connect(2) to the specified address, waiting up to + * *timeoutp milliseconds for the connection to complete. If the timeout is + * <=0, then wait indefinitely. + * + * Returns 0 on success or -1 on failure. + */ +int +timeout_connect(int sockfd, const struct sockaddr *serv_addr, + socklen_t addrlen, int *timeoutp) +{ + int optval = 0; + socklen_t optlen = sizeof(optval); + + /* No timeout: just do a blocking connect() */ + if (timeoutp == NULL || *timeoutp <= 0) + return connect(sockfd, serv_addr, addrlen); + + set_nonblock(sockfd); + if (connect(sockfd, serv_addr, addrlen) == 0) { + /* Succeeded already? */ + unset_nonblock(sockfd); + return 0; + } else if (errno != EINPROGRESS) + return -1; + + if (waitrfd(sockfd, timeoutp) == -1) + return -1; + + /* Completed or failed */ + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { + debug("getsockopt: %s", strerror(errno)); + return -1; + } + if (optval != 0) { + errno = optval; + return -1; + } + unset_nonblock(sockfd); + return 0; +} + /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" #define QUOTE "\"" diff --git a/misc.h b/misc.h index 2dd61dc32..47177d838 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.77 2018/12/07 04:36:09 dtucker Exp $ */ +/* $OpenBSD: misc.h,v 1.78 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen @@ -17,6 +17,7 @@ #include #include +#include /* Data structure for representing a forwarding request. */ struct Forward { @@ -51,6 +52,8 @@ void set_nodelay(int); int set_reuseaddr(int); char *get_rdomain(int); int set_rdomain(int, const char *); +int waitrfd(int, int *); +int timeout_connect(int, const struct sockaddr *, socklen_t, int *); int a2port(const char *); int a2tun(const char *, int *); char *put_host_port(const char *, u_short); diff --git a/packet.c b/packet.c index dcf35e6e6..e7e6d27a7 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.278 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -228,6 +229,7 @@ ssh_alloc_session_state(void) if ((ssh = calloc(1, sizeof(*ssh))) == NULL || (state = calloc(1, sizeof(*state))) == NULL || + (ssh->kex = kex_new()) == NULL || (state->input = sshbuf_new()) == NULL || (state->output = sshbuf_new()) == NULL || (state->outgoing_packet = sshbuf_new()) == NULL || @@ -250,6 +252,10 @@ ssh_alloc_session_state(void) ssh->state = state; return ssh; fail: + if (ssh) { + kex_free(ssh->kex); + free(ssh); + } if (state) { sshbuf_free(state->input); sshbuf_free(state->output); @@ -257,7 +263,6 @@ ssh_alloc_session_state(void) sshbuf_free(state->outgoing_packet); free(state); } - free(ssh); return NULL; } @@ -272,8 +277,7 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) int ssh_packet_is_rekeying(struct ssh *ssh) { - return ssh->state->rekeying || - (ssh->kex != NULL && ssh->kex->done == 0); + return ssh->state->rekeying || ssh->kex->done == 0; } /* @@ -932,7 +936,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) return 0; /* Haven't keyed yet or KEX in progress. */ - if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) + if (ssh_packet_is_rekeying(ssh)) return 0; /* Peer can't rekey */ @@ -2123,6 +2127,7 @@ void ssh_packet_set_server(struct ssh *ssh) { ssh->state->server_side = 1; + ssh->kex->server = 1; /* XXX unify? */ } void @@ -2175,9 +2180,9 @@ kex_to_blob(struct sshbuf *m, struct kex *kex) (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || (r = sshbuf_put_stringb(m, kex->my)) != 0 || (r = sshbuf_put_stringb(m, kex->peer)) != 0 || - (r = sshbuf_put_u32(m, kex->flags)) != 0 || - (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || - (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) + (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || + (r = sshbuf_put_stringb(m, kex->server_version)) != 0 || + (r = sshbuf_put_u32(m, kex->flags)) != 0) return r; return 0; } @@ -2327,12 +2332,8 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) struct kex *kex; int r; - if ((kex = calloc(1, sizeof(struct kex))) == NULL || - (kex->my = sshbuf_new()) == NULL || - (kex->peer = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } + if ((kex = kex_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || @@ -2341,23 +2342,20 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || (r = sshbuf_get_stringb(m, kex->my)) != 0 || (r = sshbuf_get_stringb(m, kex->peer)) != 0 || - (r = sshbuf_get_u32(m, &kex->flags)) != 0 || - (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || - (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) + (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || + (r = sshbuf_get_stringb(m, kex->server_version)) != 0 || + (r = sshbuf_get_u32(m, &kex->flags)) != 0) goto out; kex->server = 1; kex->done = 1; r = 0; out: if (r != 0 || kexp == NULL) { - if (kex != NULL) { - sshbuf_free(kex->my); - sshbuf_free(kex->peer); - free(kex); - } + kex_free(kex); if (kexp != NULL) *kexp = NULL; } else { + kex_free(*kexp); *kexp = kex; } return r; diff --git a/ssh.c b/ssh.c index c6cb7847d..16536a97a 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.496 2018/11/23 05:08:07 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.497 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1490,7 +1490,7 @@ main(int ac, char **av) signal(SIGCHLD, main_sigchld_handler); /* Log into the remote system. Never returns if the login fails. */ - ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, + ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr, options.port, pw, timeout_ms); if (packet_connection_is_on_socket()) { diff --git a/ssh.h b/ssh.h index 5abfd7a68..dda6f617e 100644 --- a/ssh.h +++ b/ssh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.h,v 1.88 2018/06/06 18:29:18 markus Exp $ */ +/* $OpenBSD: ssh.h,v 1.89 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen @@ -93,3 +93,7 @@ /* Listen backlog for sshd, ssh-agent and forwarding sockets */ #define SSH_LISTEN_BACKLOG 128 + +/* Limits for banner exchange */ +#define SSH_MAX_BANNER_LEN 8192 +#define SSH_MAX_PRE_BANNER_LINES 1024 diff --git a/ssh_api.c b/ssh_api.c index 53bbc9b49..ab209c4ca 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.9 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -34,8 +34,8 @@ #include int _ssh_exchange_banner(struct ssh *); -int _ssh_send_banner(struct ssh *, char **); -int _ssh_read_banner(struct ssh *, char **); +int _ssh_send_banner(struct ssh *, struct sshbuf *); +int _ssh_read_banner(struct ssh *, struct sshbuf *); int _ssh_order_hostkeyalgs(struct ssh *); int _ssh_verify_host_key(struct sshkey *, struct ssh *); struct sshkey *_ssh_host_public_key(int, int, struct ssh *); @@ -92,7 +92,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) /* Initialize key exchange */ proposal = kex_params ? kex_params->proposal : myproposal; - if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) { + if ((r = kex_ready(ssh, proposal)) != 0) { ssh_free(ssh); return r; } @@ -236,8 +236,8 @@ ssh_packet_next(struct ssh *ssh, u_char *typep) * enough data. */ *typep = SSH_MSG_NONE; - if (ssh->kex->client_version_string == NULL || - ssh->kex->server_version_string == NULL) + if (sshbuf_len(ssh->kex->client_version) == 0 || + sshbuf_len(ssh->kex->server_version) == 0) return _ssh_exchange_banner(ssh); /* * If we enough data and a dispatch function then @@ -312,39 +312,46 @@ ssh_input_space(struct ssh *ssh, size_t len) /* Read other side's version identification. */ int -_ssh_read_banner(struct ssh *ssh, char **bannerp) +_ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) { - struct sshbuf *input; - const char *s; - char buf[256], remote_version[256]; /* must be same size! */ + struct sshbuf *input = ssh_packet_get_input(ssh); const char *mismatch = "Protocol mismatch.\r\n"; - int r, remote_major, remote_minor; - size_t i, n, j, len; + const u_char *s = sshbuf_ptr(input); + u_char c; + char *cp, *remote_version; + int r, remote_major, remote_minor, expect_nl; + size_t n, j; - *bannerp = NULL; - input = ssh_packet_get_input(ssh); - len = sshbuf_len(input); - s = (const char *)sshbuf_ptr(input); for (j = n = 0;;) { - for (i = 0; i < sizeof(buf) - 1; i++) { - if (j >= len) - return (0); - buf[i] = s[j++]; - if (buf[i] == '\r') { - buf[i] = '\n'; - buf[i + 1] = 0; - continue; /**XXX wait for \n */ + sshbuf_reset(banner); + expect_nl = 0; + for (;;) { + if (j >= sshbuf_len(input)) + return 0; /* insufficient data in input buf */ + c = s[j++]; + if (c == '\r') { + expect_nl = 1; + continue; } - if (buf[i] == '\n') { - buf[i + 1] = 0; + if (c == '\n') break; - } + if (expect_nl) + goto bad; + if ((r = sshbuf_put_u8(banner, c)) != 0) + return r; + if (sshbuf_len(banner) > SSH_MAX_BANNER_LEN) + goto bad; } - buf[sizeof(buf) - 1] = 0; - if (strncmp(buf, "SSH-", 4) == 0) + if (sshbuf_len(banner) >= 4 && + memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0) break; - debug("ssh_exchange_identification: %s", buf); - if (ssh->kex->server || ++n > 65536) { + if ((cp = sshbuf_dup_string(banner)) == NULL) + return SSH_ERR_ALLOC_FAIL; + debug("%s: %s", __func__, cp); + free(cp); + /* Accept lines before banner only on client */ + if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) { + bad: if ((r = sshbuf_put(ssh_packet_get_output(ssh), mismatch, strlen(mismatch))) != 0) return r; @@ -354,11 +361,17 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp) if ((r = sshbuf_consume(input, j)) != 0) return r; + if ((cp = sshbuf_dup_string(banner)) == NULL) + return SSH_ERR_ALLOC_FAIL; + /* XXX remote version must be the same size as banner for sscanf */ + if ((remote_version = calloc(1, sshbuf_len(banner))) == NULL) + return SSH_ERR_ALLOC_FAIL; + /* * Check that the versions match. In future this might accept * several versions and set appropriate flags to handle them. */ - if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", + if (sscanf(cp, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) != 3) return SSH_ERR_INVALID_FORMAT; debug("Remote protocol version %d.%d, remote software version %.100s", @@ -371,27 +384,29 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp) } if (remote_major != 2) return SSH_ERR_PROTOCOL_MISMATCH; - chop(buf); - debug("Remote version string %.100s", buf); - if ((*bannerp = strdup(buf)) == NULL) - return SSH_ERR_ALLOC_FAIL; + debug("Remote version string %.100s", cp); + free(cp); return 0; } /* Send our own protocol version identification. */ int -_ssh_send_banner(struct ssh *ssh, char **bannerp) +_ssh_send_banner(struct ssh *ssh, struct sshbuf *banner) { - char buf[256]; + char *cp; int r; - snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION); - if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0) + if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0) + return r; + if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0) + return r; + /* Remove trailing \r\n */ + if ((r = sshbuf_consume_end(banner, 2)) != 0) return r; - chop(buf); - debug("Local version string %.100s", buf); - if ((*bannerp = strdup(buf)) == NULL) + if ((cp = sshbuf_dup_string(banner)) == NULL) return SSH_ERR_ALLOC_FAIL; + debug("Local version string %.100s", cp); + free(cp); return 0; } @@ -408,25 +423,25 @@ _ssh_exchange_banner(struct ssh *ssh) r = 0; if (kex->server) { - if (kex->server_version_string == NULL) - r = _ssh_send_banner(ssh, &kex->server_version_string); + if (sshbuf_len(ssh->kex->server_version) == 0) + r = _ssh_send_banner(ssh, ssh->kex->server_version); if (r == 0 && - kex->server_version_string != NULL && - kex->client_version_string == NULL) - r = _ssh_read_banner(ssh, &kex->client_version_string); + sshbuf_len(ssh->kex->server_version) != 0 && + sshbuf_len(ssh->kex->client_version) == 0) + r = _ssh_read_banner(ssh, ssh->kex->client_version); } else { - if (kex->server_version_string == NULL) - r = _ssh_read_banner(ssh, &kex->server_version_string); + if (sshbuf_len(ssh->kex->server_version) == 0) + r = _ssh_read_banner(ssh, ssh->kex->server_version); if (r == 0 && - kex->server_version_string != NULL && - kex->client_version_string == NULL) - r = _ssh_send_banner(ssh, &kex->client_version_string); + sshbuf_len(ssh->kex->server_version) != 0 && + sshbuf_len(ssh->kex->client_version) == 0) + r = _ssh_send_banner(ssh, ssh->kex->client_version); } if (r != 0) return r; /* start initial kex as soon as we have exchanged the banners */ - if (kex->server_version_string != NULL && - kex->client_version_string != NULL) { + if (sshbuf_len(ssh->kex->server_version) != 0 && + sshbuf_len(ssh->kex->client_version) != 0) { if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 || (r = kex_send_kexinit(ssh)) != 0) return r; diff --git a/sshconnect.c b/sshconnect.c index 4862da5ed..884e33628 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.308 2018/11/18 22:43:29 dtucker Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.309 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -68,9 +68,8 @@ #include "authfile.h" #include "ssherr.h" #include "authfd.h" +#include "kex.h" -char *client_version_string = NULL; -char *server_version_string = NULL; struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; @@ -444,73 +443,6 @@ fail: return sock; } -/* - * Wait up to *timeoutp milliseconds for fd to be readable. Updates - * *timeoutp with time remaining. - * Returns 0 if fd ready or -1 on timeout or error (see errno). - */ -static int -waitrfd(int fd, int *timeoutp) -{ - struct pollfd pfd; - struct timeval t_start; - int oerrno, r; - - monotime_tv(&t_start); - pfd.fd = fd; - pfd.events = POLLIN; - for (; *timeoutp >= 0;) { - r = poll(&pfd, 1, *timeoutp); - oerrno = errno; - ms_subtract_diff(&t_start, timeoutp); - errno = oerrno; - if (r > 0) - return 0; - else if (r == -1 && errno != EAGAIN) - return -1; - else if (r == 0) - break; - } - /* timeout */ - errno = ETIMEDOUT; - return -1; -} - -static int -timeout_connect(int sockfd, const struct sockaddr *serv_addr, - socklen_t addrlen, int *timeoutp) -{ - int optval = 0; - socklen_t optlen = sizeof(optval); - - /* No timeout: just do a blocking connect() */ - if (*timeoutp <= 0) - return connect(sockfd, serv_addr, addrlen); - - set_nonblock(sockfd); - if (connect(sockfd, serv_addr, addrlen) == 0) { - /* Succeeded already? */ - unset_nonblock(sockfd); - return 0; - } else if (errno != EINPROGRESS) - return -1; - - if (waitrfd(sockfd, timeoutp) == -1) - return -1; - - /* Completed or failed */ - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { - debug("getsockopt: %s", strerror(errno)); - return -1; - } - if (optval != 0) { - errno = optval; - return -1; - } - unset_nonblock(sockfd); - return 0; -} - /* * Opens a TCP/IP connection to the remote server on the given host. * The address of the remote host will be returned in hostaddr. @@ -629,110 +561,6 @@ ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs, return ssh_proxy_connect(ssh, host, port, options.proxy_command); } -static void -send_client_banner(int connection_out, int minor1) -{ - /* Send our own protocol version identification. */ - xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); - if (atomicio(vwrite, connection_out, client_version_string, - strlen(client_version_string)) != strlen(client_version_string)) - fatal("write: %.100s", strerror(errno)); - chop(client_version_string); - debug("Local version string %.100s", client_version_string); -} - -/* - * Waits for the server identification string, and sends our own - * identification string. - */ -void -ssh_exchange_identification(int timeout_ms) -{ - char buf[256], remote_version[256]; /* must be same size! */ - int remote_major, remote_minor, mismatch; - int connection_in = packet_get_connection_in(); - int connection_out = packet_get_connection_out(); - u_int i, n; - size_t len; - int rc; - - send_client_banner(connection_out, 0); - - /* Read other side's version identification. */ - for (n = 0;;) { - for (i = 0; i < sizeof(buf) - 1; i++) { - if (timeout_ms > 0) { - rc = waitrfd(connection_in, &timeout_ms); - if (rc == -1 && errno == ETIMEDOUT) { - fatal("Connection timed out during " - "banner exchange"); - } else if (rc == -1) { - fatal("%s: %s", - __func__, strerror(errno)); - } - } - - len = atomicio(read, connection_in, &buf[i], 1); - if (len != 1 && errno == EPIPE) - fatal("ssh_exchange_identification: " - "Connection closed by remote host"); - else if (len != 1) - fatal("ssh_exchange_identification: " - "read: %.100s", strerror(errno)); - if (buf[i] == '\r') { - buf[i] = '\n'; - buf[i + 1] = 0; - continue; /**XXX wait for \n */ - } - if (buf[i] == '\n') { - buf[i + 1] = 0; - break; - } - if (++n > 65536) - fatal("ssh_exchange_identification: " - "No banner received"); - } - buf[sizeof(buf) - 1] = 0; - if (strncmp(buf, "SSH-", 4) == 0) - break; - debug("ssh_exchange_identification: %s", buf); - } - server_version_string = xstrdup(buf); - - /* - * Check that the versions match. In future this might accept - * several versions and set appropriate flags to handle them. - */ - if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) != 3) - fatal("Bad remote protocol version identification: '%.100s'", buf); - debug("Remote protocol version %d.%d, remote software version %.100s", - remote_major, remote_minor, remote_version); - - active_state->compat = compat_datafellows(remote_version); - mismatch = 0; - - switch (remote_major) { - case 2: - break; - case 1: - if (remote_minor != 99) - mismatch = 1; - break; - default: - mismatch = 1; - break; - } - if (mismatch) - fatal("Protocol major versions differ: %d vs. %d", - PROTOCOL_MAJOR_2, remote_major); - if ((datafellows & SSH_BUG_RSASIGMD5) != 0) - logit("Server version \"%.100s\" uses unsafe RSA signature " - "scheme; disabling use of RSA keys", remote_version); - chop(server_version_string); -} - /* defaults to 'no' */ static int confirm(const char *prompt) @@ -1426,7 +1254,7 @@ out: * This function does not require super-user privileges. */ void -ssh_login(Sensitive *sensitive, const char *orighost, +ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms) { char *host; @@ -1440,16 +1268,17 @@ ssh_login(Sensitive *sensitive, const char *orighost, lowercase(host); /* Exchange protocol version identification strings with the server. */ - ssh_exchange_identification(timeout_ms); + if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0) + cleanup_exit(255); /* error already logged */ /* Put the connection into non-blocking mode. */ - packet_set_nonblocking(); + ssh_packet_set_nonblocking(ssh); /* key exchange */ /* authenticate user */ debug("Authenticating to %s:%d as '%s'", host, port, server_user); - ssh_kex2(host, hostaddr, port); - ssh_userauth2(local_user, server_user, host, sensitive); + ssh_kex2(ssh, host, hostaddr, port); + ssh_userauth2(ssh, local_user, server_user, host, sensitive); free(local_user); } diff --git a/sshconnect.h b/sshconnect.h index 890d85733..44a5071c7 100644 --- a/sshconnect.h +++ b/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.35 2018/07/19 10:28:47 dtucker Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.36 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -37,21 +37,18 @@ int ssh_connect(struct ssh *, const char *, struct addrinfo *, struct sockaddr_storage *, u_short, int, int, int *, int); void ssh_kill_proxy_command(void); -void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, - struct passwd *, int); - -void ssh_exchange_identification(int); +void ssh_login(struct ssh *, Sensitive *, const char *, + struct sockaddr *, u_short, struct passwd *, int); int verify_host_key(char *, struct sockaddr *, struct sshkey *); void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, char **, char **); -void ssh_kex(char *, struct sockaddr *); -void ssh_kex2(char *, struct sockaddr *, u_short); +void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short); -void ssh_userauth1(const char *, const char *, char *, Sensitive *); -void ssh_userauth2(const char *, const char *, char *, Sensitive *); +void ssh_userauth2(struct ssh *ssh, const char *, const char *, + char *, Sensitive *); void ssh_put_password(char *); int ssh_local_cmd(const char *); diff --git a/sshconnect2.c b/sshconnect2.c index adb4e4cbd..19caebabc 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.290 2018/11/28 06:00:38 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.291 2018/12/27 03:25:25 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -155,11 +155,10 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) } void -ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) +ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) { char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; char *s, *all_key; - struct kex *kex; int r; xxx_host = host; @@ -199,36 +198,33 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) options.rekey_interval); /* start key exchange */ - if ((r = kex_setup(active_state, myproposal)) != 0) + if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); - kex = active_state->kex; #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif - kex->kex[KEX_C25519_SHA256] = kexc25519_client; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; - kex->verify_host_key=&verify_host_key_callback; + ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->verify_host_key=&verify_host_key_callback; - ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); /* remove ext-info from the KEX proposals for rekeying */ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(options.kex_algorithms); - if ((r = kex_prop2buf(kex->my, myproposal)) != 0) + if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) fatal("kex_prop2buf: %s", ssh_err(r)); - session_id2 = kex->session_id; - session_id2_len = kex->session_id_len; + session_id2 = ssh->kex->session_id; + session_id2_len = ssh->kex->session_id_len; #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ @@ -365,10 +361,9 @@ Authmethod authmethods[] = { }; void -ssh_userauth2(const char *local_user, const char *server_user, char *host, - Sensitive *sensitive) +ssh_userauth2(struct ssh *ssh, const char *local_user, + const char *server_user, char *host, Sensitive *sensitive) { - struct ssh *ssh = active_state; Authctxt authctxt; int r; @@ -392,8 +387,10 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, authctxt.info_req_seen = 0; authctxt.agent_fd = -1; pubkey_prepare(&authctxt); - if (authctxt.method == NULL) - fatal("ssh_userauth2: internal error: cannot send userauth none request"); + if (authctxt.method == NULL) { + fatal("%s: internal error: cannot send userauth none request", + __func__); + } if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 || diff --git a/sshd.c b/sshd.c index fb9d9b60f..3461383a0 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.519 2018/11/19 04:12:32 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.520 2018/12/27 03:25:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -180,13 +180,6 @@ char **rexec_argv; int listen_socks[MAX_LISTEN_SOCKS]; int num_listen_socks = 0; -/* - * the client's version string, passed by sshd2 in compat mode. if != NULL, - * sshd will skip the version-number exchange - */ -char *client_version_string = NULL; -char *server_version_string = NULL; - /* Daemon's agent connection */ int auth_sock = -1; int have_agent = 0; @@ -363,108 +356,6 @@ grace_alarm_handler(int sig) ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); } -static void -sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) -{ - u_int i; - int remote_major, remote_minor; - char *s; - char buf[256]; /* Must not be larger than remote_version. */ - char remote_version[256]; /* Must be at least as big as buf. */ - - xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n", - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, - *options.version_addendum == '\0' ? "" : " ", - options.version_addendum); - - /* Send our protocol version identification. */ - if (atomicio(vwrite, sock_out, server_version_string, - strlen(server_version_string)) - != strlen(server_version_string)) { - logit("Could not write ident string to %s port %d", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); - cleanup_exit(255); - } - - /* Read other sides version identification. */ - memset(buf, 0, sizeof(buf)); - for (i = 0; i < sizeof(buf) - 1; i++) { - if (atomicio(read, sock_in, &buf[i], 1) != 1) { - logit("Did not receive identification string " - "from %s port %d", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); - cleanup_exit(255); - } - if (buf[i] == '\r') { - buf[i] = 0; - /* Kludge for F-Secure Macintosh < 1.0.2 */ - if (i == 12 && - strncmp(buf, "SSH-1.5-W1.0", 12) == 0) - break; - continue; - } - if (buf[i] == '\n') { - buf[i] = 0; - break; - } - } - buf[sizeof(buf) - 1] = 0; - client_version_string = xstrdup(buf); - - /* - * Check that the versions match. In future this might accept - * several versions and set appropriate flags to handle them. - */ - if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", - &remote_major, &remote_minor, remote_version) != 3) { - s = "Protocol mismatch.\n"; - (void) atomicio(vwrite, sock_out, s, strlen(s)); - logit("Bad protocol version identification '%.100s' " - "from %s port %d", client_version_string, - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); - close(sock_in); - close(sock_out); - cleanup_exit(255); - } - debug("Client protocol version %d.%d; client software version %.100s", - remote_major, remote_minor, remote_version); - - ssh->compat = compat_datafellows(remote_version); - - if ((ssh->compat & SSH_BUG_PROBE) != 0) { - logit("probed from %s port %d with %s. Don't panic.", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - client_version_string); - cleanup_exit(255); - } - if ((ssh->compat & SSH_BUG_SCANNER) != 0) { - logit("scanned from %s port %d with %s. Don't panic.", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - client_version_string); - cleanup_exit(255); - } - if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) { - logit("Client version \"%.100s\" uses unsafe RSA signature " - "scheme; disabling use of RSA keys", remote_version); - } - - chop(server_version_string); - debug("Local version string %.200s", server_version_string); - - if (remote_major != 2 && - !(remote_major == 1 && remote_minor == 99)) { - s = "Protocol major versions differ.\n"; - (void) atomicio(vwrite, sock_out, s, strlen(s)); - close(sock_in); - close(sock_out); - logit("Protocol major versions differ for %s port %d: " - "%.200s vs. %.200s", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - server_version_string, client_version_string); - cleanup_exit(255); - } -} - /* Destroy the host and server keys. They will no longer be needed. */ void destroy_sensitive_data(void) @@ -2115,7 +2006,9 @@ main(int ac, char **av) if (!debug_flag) alarm(options.login_grace_time); - sshd_exchange_identification(ssh, sock_in, sock_out); + if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0) + cleanup_exit(255); /* error already logged */ + packet_set_nonblocking(); /* allocate authentication context */ @@ -2303,9 +2196,6 @@ do_ssh2_kex(void) # endif #endif kex->kex[KEX_C25519_SHA256] = kexc25519_server; - kex->server = 1; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; -- cgit v1.2.3 From dbb4dec6d5d671b5e9d67ef02162a610ad052068 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 17 Jan 2019 01:50:24 +0000 Subject: upstream: many of the global variables in this file can be made static; patch from Markus Schmidt OpenBSD-Commit-ID: f3db619f67beb53257b21bac0e92b4fb7d5d5737 --- sshd.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'sshd.c') diff --git a/sshd.c b/sshd.c index 3461383a0..1d25c88f3 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.520 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.521 2019/01/17 01:50:24 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -151,38 +151,38 @@ int debug_flag = 0; * configuration, optionally using connection information provided by the * "-C" flag. */ -int test_flag = 0; +static int test_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ -int inetd_flag = 0; +static int inetd_flag = 0; /* Flag indicating that sshd should not detach and become a daemon. */ -int no_daemon_flag = 0; +static int no_daemon_flag = 0; /* debug goes to stderr unless inetd_flag is set */ -int log_stderr = 0; +static int log_stderr = 0; /* Saved arguments to main(). */ -char **saved_argv; -int saved_argc; +static char **saved_argv; +static int saved_argc; /* re-exec */ -int rexeced_flag = 0; -int rexec_flag = 1; -int rexec_argc = 0; -char **rexec_argv; +static int rexeced_flag = 0; +static int rexec_flag = 1; +static int rexec_argc = 0; +static char **rexec_argv; /* * The sockets that the server is listening; this is used in the SIGHUP * signal handler. */ #define MAX_LISTEN_SOCKS 16 -int listen_socks[MAX_LISTEN_SOCKS]; -int num_listen_socks = 0; +static int listen_socks[MAX_LISTEN_SOCKS]; +static int num_listen_socks = 0; /* Daemon's agent connection */ int auth_sock = -1; -int have_agent = 0; +static int have_agent = 0; /* * Any really sensitive data in the application is contained in this @@ -214,8 +214,8 @@ u_int session_id2_len = 0; u_int utmp_len = HOST_NAME_MAX+1; /* options.max_startup sized array of fd ints */ -int *startup_pipes = NULL; -int startup_pipe; /* in child */ +static int *startup_pipes = NULL; +static int startup_pipe; /* in child */ /* variables used for privilege separation */ int use_privsep = -1; -- cgit v1.2.3 From 0fa174ebe129f3d0aeaf4e2d1dd8de745870d0ff Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:31:32 +0000 Subject: upstream: begin landing remaining refactoring of packet parsing API, started almost exactly six years ago. This change stops including the old packet_* API by default and makes each file that requires the old API include it explicitly. We will commit file-by-file refactoring to remove the old API in consistent steps. with & ok markus@ OpenBSD-Commit-ID: 93c98a6b38f6911fd1ae025a1ec57807fb4d4ef4 --- auth.c | 5 ++++- auth2-hostbased.c | 4 +++- auth2.c | 5 ++++- channels.c | 5 ++++- clientloop.c | 5 ++++- monitor.c | 5 ++++- monitor_wrap.c | 5 ++++- mux.c | 5 ++++- opacket.c | 3 ++- packet.h | 6 +----- servconf.c | 5 ++++- serverloop.c | 5 ++++- session.c | 5 ++++- ssh.c | 5 ++++- sshconnect.c | 5 ++++- sshconnect2.c | 5 ++++- sshd.c | 5 ++++- 17 files changed, 62 insertions(+), 21 deletions(-) (limited to 'sshd.c') diff --git a/auth.c b/auth.c index 7d48d07a8..94f43a6c2 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.135 2019/01/17 04:20:53 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.136 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -77,6 +77,9 @@ #include "compat.h" #include "channels.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import */ extern ServerOptions options; extern int use_privsep; diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 764ceff74..e28a48fb3 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.38 2018/09/20 03:28:06 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.39 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -51,6 +51,8 @@ #include "ssherr.h" #include "match.h" +extern struct ssh *active_state; /* XXX */ + /* import */ extern ServerOptions options; extern u_char *session_id2; diff --git a/auth2.c b/auth2.c index 4415c11ec..3df2acf78 100644 --- a/auth2.c +++ b/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.151 2019/01/17 04:20:53 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.152 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -61,6 +61,9 @@ #include "ssherr.h" #include "digest.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import */ extern ServerOptions options; extern u_char *session_id2; diff --git a/channels.c b/channels.c index 6d2e1c6a6..dcda44b07 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.387 2018/12/07 02:31:20 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.388 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -84,6 +84,9 @@ #include "pathnames.h" #include "match.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* -- agent forwarding */ #define NUM_SOCKS 10 diff --git a/clientloop.c b/clientloop.c index 8d312cdaa..d29ec00bc 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.318 2018/09/21 12:46:22 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.319 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -112,6 +112,9 @@ #include "ssherr.h" #include "hostfile.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import options */ extern Options options; diff --git a/monitor.c b/monitor.c index 09d3a27fd..e15a5225d 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.188 2018/11/16 02:43:56 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.189 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -96,6 +96,9 @@ #include "match.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + #ifdef GSSAPI static Gssctxt *gsscontext = NULL; #endif diff --git a/monitor_wrap.c b/monitor_wrap.c index 732fb3476..6ceaa3716 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.107 2018/07/20 03:46:34 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.108 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -76,6 +76,9 @@ #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* Imports */ extern struct monitor *pmonitor; extern struct sshbuf *loginmsg; diff --git a/mux.c b/mux.c index 8e4b60827..abc1e05ab 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.77 2018/09/26 07:32:44 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.78 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -68,6 +68,9 @@ #include "clientloop.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* from ssh.c */ extern int tty_flag; extern Options options; diff --git a/opacket.c b/opacket.c index e637d7a71..56a76939e 100644 --- a/opacket.c +++ b/opacket.c @@ -2,11 +2,12 @@ /* Written by Markus Friedl. Placed in the public domain. */ #include "includes.h" - +/* $OpenBSD: opacket.c,v 1.8 2019/01/19 21:31:32 djm Exp $ */ #include #include "ssherr.h" #include "packet.h" +#include "opacket.h" /* XXX */ #include "log.h" struct ssh *active_state, *backup_state; diff --git a/packet.h b/packet.h index 170203cab..c58b52d39 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.86 2018/07/09 21:20:26 markus Exp $ */ +/* $OpenBSD: packet.h,v 1.87 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen @@ -204,10 +204,6 @@ int sshpkt_get_end(struct ssh *ssh); void sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l); const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); -/* OLD API */ -extern struct ssh *active_state; -#include "opacket.h" - #if !defined(WITH_OPENSSL) # undef BIGNUM # undef EC_KEY diff --git a/servconf.c b/servconf.c index 52d9be429..0ec095bd0 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.344 2018/11/19 04:12:32 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.345 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -65,6 +65,9 @@ #include "myproposal.h" #include "digest.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + static void add_listen_addr(ServerOptions *, const char *, const char *, int); static void add_one_listen_addr(ServerOptions *, const char *, diff --git a/serverloop.c b/serverloop.c index 7be83e2d3..e0c26bbbc 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.209 2018/07/27 05:13:02 dtucker Exp $ */ +/* $OpenBSD: serverloop.c,v 1.210 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -78,6 +78,9 @@ #include "serverloop.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + extern ServerOptions options; /* XXX */ diff --git a/session.c b/session.c index 0452f507a..f0dabe111 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.309 2019/01/17 04:45:09 djm Exp $ */ +/* $OpenBSD: session.c,v 1.310 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -105,6 +105,9 @@ #include #endif +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + #define IS_INTERNAL_SFTP(c) \ (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \ (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \ diff --git a/ssh.c b/ssh.c index 16536a97a..a206a5fca 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.497 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.498 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -113,6 +113,9 @@ #include "ssh-pkcs11.h" #endif +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX move here */ + extern char *__progname; /* Saves a copy of argv for setproctitle emulation */ diff --git a/sshconnect.c b/sshconnect.c index 884e33628..346f979d1 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.309 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.310 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -70,6 +70,9 @@ #include "authfd.h" #include "kex.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; diff --git a/sshconnect2.c b/sshconnect2.c index 0e8f323d6..73ffe77a9 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.292 2019/01/04 03:27:50 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.293 2019/01/19 21:31:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -77,6 +77,9 @@ #include "ssh-gss.h" #endif +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX */ + /* import */ extern char *client_version_string; extern char *server_version_string; diff --git a/sshd.c b/sshd.c index 1d25c88f3..ad8c152a5 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.521 2019/01/17 01:50:24 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.522 2019/01/19 21:31:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -123,6 +123,9 @@ #include "version.h" #include "ssherr.h" +#include "opacket.h" /* XXX */ +extern struct ssh *active_state; /* XXX move decl to this file */ + /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) -- cgit v1.2.3 From 172a592a53ebe8649c4ac0d7946e6c08eb151af6 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:37:48 +0000 Subject: upstream: convert servconf.c to new packet API with & ok markus@ OpenBSD-Commit-ID: 126553aecca302c9e02fd77e333b9cb217e623b4 --- auth.c | 5 +++-- servconf.c | 10 +++------- servconf.h | 4 ++-- sshd.c | 6 +++--- 4 files changed, 11 insertions(+), 14 deletions(-) (limited to 'sshd.c') diff --git a/auth.c b/auth.c index 94f43a6c2..d82b40683 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.136 2019/01/19 21:31:32 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.137 2019/01/19 21:37:48 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -572,8 +572,9 @@ getpwnamallow(const char *user) #endif #endif struct passwd *pw; - struct connection_info *ci = get_connection_info(1, options.use_dns); + struct connection_info *ci; + ci = get_connection_info(ssh, 1, options.use_dns); ci->user = user; parse_server_match_config(&options, ci); log_change_level(options.log_level); diff --git a/servconf.c b/servconf.c index 0ec095bd0..86c631bb0 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.345 2019/01/19 21:31:32 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.346 2019/01/19 21:37:48 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -65,9 +65,6 @@ #include "myproposal.h" #include "digest.h" -#include "opacket.h" /* XXX */ -extern struct ssh *active_state; /* XXX */ - static void add_listen_addr(ServerOptions *, const char *, const char *, int); static void add_one_listen_addr(ServerOptions *, const char *, @@ -926,12 +923,11 @@ process_permitopen(struct ssh *ssh, ServerOptions *options) } struct connection_info * -get_connection_info(int populate, int use_dns) +get_connection_info(struct ssh *ssh, int populate, int use_dns) { - struct ssh *ssh = active_state; /* XXX */ static struct connection_info ci; - if (!populate) + if (ssh == NULL || !populate) return &ci; ci.host = auth_get_canonical_hostname(ssh, use_dns); ci.address = ssh_remote_ipaddr(ssh); diff --git a/servconf.h b/servconf.h index 548ad5a0c..54e0a8d8d 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.138 2018/11/19 04:12:32 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.139 2019/01/19 21:37:48 djm Exp $ */ /* * Author: Tatu Ylonen @@ -258,7 +258,7 @@ struct connection_info { M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \ } while (0) -struct connection_info *get_connection_info(int, int); +struct connection_info *get_connection_info(struct ssh *, int, int); void initialize_server_options(ServerOptions *); void fill_default_server_options(ServerOptions *); int process_server_config_line(ServerOptions *, char *, const char *, int, diff --git a/sshd.c b/sshd.c index ad8c152a5..64f27a7bb 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.522 2019/01/19 21:31:32 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.523 2019/01/19 21:37:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1493,7 +1493,7 @@ main(int ac, char **av) test_flag = 2; break; case 'C': - connection_info = get_connection_info(0, 0); + connection_info = get_connection_info(ssh, 0, 0); if (parse_server_match_testspec(connection_info, optarg) == -1) exit(1); @@ -1776,7 +1776,7 @@ main(int ac, char **av) * use a blank one that will cause no predicate to match. */ if (connection_info == NULL) - connection_info = get_connection_info(0, 0); + connection_info = get_connection_info(ssh, 0, 0); parse_server_match_config(&options, connection_info); dump_config(&options); } -- cgit v1.2.3 From 5ebce136a6105f084db8f0d7ee41981d42daec40 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 20 Jan 2019 09:44:53 +1100 Subject: upstream: convert auth2.c to new packet API OpenBSD-Commit-ID: ed831bb95ad228c6791bc18b60ce7a2edef2c999 --- auth.h | 6 ++-- auth2.c | 106 ++++++++++++++++++++++++++++++++++++---------------------------- sshd.c | 5 +-- 3 files changed, 64 insertions(+), 53 deletions(-) (limited to 'sshd.c') diff --git a/auth.h b/auth.h index 977562f0a..68104e50b 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.96 2018/04/10 00:10:49 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.97 2019/01/19 21:38:24 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -166,15 +166,13 @@ int auth_shadow_pwexpired(Authctxt *); #include "audit.h" void remove_kbdint_device(const char *); -void do_authentication2(Authctxt *); +void do_authentication2(struct ssh *); void auth_log(Authctxt *, int, int, const char *, const char *); void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn)); void userauth_finish(struct ssh *, int, const char *, const char *); int auth_root_allowed(struct ssh *, const char *); -void userauth_send_banner(const char *); - char *auth2_read_banner(void); int auth2_methods_valid(const char *, int); int auth2_update_methods_lists(Authctxt *, const char *, const char *); diff --git a/auth2.c b/auth2.c index 3df2acf78..2ea71210c 100644 --- a/auth2.c +++ b/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.152 2019/01/19 21:31:32 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.153 2019/01/19 21:38:24 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -61,9 +61,6 @@ #include "ssherr.h" #include "digest.h" -#include "opacket.h" /* XXX */ -extern struct ssh *active_state; /* XXX */ - /* import */ extern ServerOptions options; extern u_char *session_id2; @@ -141,18 +138,21 @@ auth2_read_banner(void) return (banner); } -void -userauth_send_banner(const char *msg) +static void +userauth_send_banner(struct ssh *ssh, const char *msg) { - packet_start(SSH2_MSG_USERAUTH_BANNER); - packet_put_cstring(msg); - packet_put_cstring(""); /* language, unused */ - packet_send(); + int r; + + if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_BANNER)) != 0 || + (r = sshpkt_put_cstring(ssh, msg)) != 0 || + (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */ + (r = sshpkt_send(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); debug("%s: sent", __func__); } static void -userauth_banner(void) +userauth_banner(struct ssh *ssh) { char *banner = NULL; @@ -161,7 +161,7 @@ userauth_banner(void) if ((banner = PRIVSEP(auth2_read_banner())) == NULL) goto done; - userauth_send_banner(banner); + userauth_send_banner(ssh, banner); done: free(banner); @@ -171,10 +171,10 @@ done: * loop until authctxt->success == TRUE */ void -do_authentication2(Authctxt *authctxt) +do_authentication2(struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ - ssh->authctxt = authctxt; /* XXX move to caller */ + Authctxt *authctxt = ssh->authctxt; + ssh_dispatch_init(ssh, &dispatch_protocol_error); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request); ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success); @@ -186,10 +186,12 @@ static int input_service_request(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; - u_int len; - int acceptit = 0; - char *service = packet_get_cstring(&len); - packet_check_eom(); + char *service = NULL; + int r, acceptit = 0; + + if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; if (authctxt == NULL) fatal("input_service_request: no authctxt"); @@ -198,20 +200,24 @@ input_service_request(int type, u_int32_t seq, struct ssh *ssh) if (!authctxt->success) { acceptit = 1; /* now we can handle user-auth requests */ - ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, + &input_userauth_request); } } /* XXX all other service requests are denied */ if (acceptit) { - packet_start(SSH2_MSG_SERVICE_ACCEPT); - packet_put_cstring(service); - packet_send(); - packet_write_wait(); + if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 || + (r = sshpkt_put_cstring(ssh, service)) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + goto out; } else { debug("bad service request %s", service); - packet_disconnect("bad service request %s", service); + ssh_packet_disconnect(ssh, "bad service request %s", service); } + r = 0; + out: free(service); return 0; } @@ -259,16 +265,17 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; - char *user, *service, *method, *style = NULL; - int authenticated = 0; + char *user = NULL, *service = NULL, *method = NULL, *style = NULL; + int r, authenticated = 0; double tstart = monotime_double(); if (authctxt == NULL) fatal("input_userauth_request: no authctxt"); - user = packet_get_cstring(NULL); - service = packet_get_cstring(NULL); - method = packet_get_cstring(NULL); + if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 || + (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || + (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0) + goto out; debug("userauth-request for user %s service %s method %s", user, service, method); debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); @@ -302,13 +309,14 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) authctxt->style = style ? xstrdup(style) : NULL; if (use_privsep) mm_inform_authserv(service, style); - userauth_banner(); + userauth_banner(ssh); if (auth2_setup_methods_lists(authctxt) != 0) - packet_disconnect("no authentication methods enabled"); + ssh_packet_disconnect(ssh, + "no authentication methods enabled"); } else if (strcmp(user, authctxt->user) != 0 || strcmp(service, authctxt->service) != 0) { - packet_disconnect("Change of username or service not allowed: " - "(%s,%s) -> (%s,%s)", + ssh_packet_disconnect(ssh, "Change of username or service " + "not allowed: (%s,%s) -> (%s,%s)", authctxt->user, authctxt->service, user, service); } /* reset state */ @@ -334,11 +342,12 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) ensure_minimum_time_since(tstart, user_specific_delay(authctxt->user)); userauth_finish(ssh, authenticated, method, NULL); - + r = 0; + out: free(service); free(user); free(method); - return 0; + return r; } void @@ -347,7 +356,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, { Authctxt *authctxt = ssh->authctxt; char *methods; - int partial = 0; + int r, partial = 0; if (!authctxt->valid && authenticated) fatal("INTERNAL ERROR: authenticated invalid user %s", @@ -391,7 +400,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); - userauth_send_banner(sshbuf_ptr(loginmsg)); + userauth_send_banner(ssh, sshbuf_ptr(loginmsg)); packet_write_wait(); } fatal("Access denied for user %s by PAM account " @@ -402,10 +411,12 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, if (authenticated == 1) { /* turn off userauth */ - ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); - packet_start(SSH2_MSG_USERAUTH_SUCCESS); - packet_send(); - packet_write_wait(); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, + &dispatch_protocol_ignore); + if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); /* now we can break out */ authctxt->success = 1; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); @@ -423,11 +434,12 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, methods = authmethods_get(authctxt); debug3("%s: failure partial=%d next methods=\"%s\"", __func__, partial, methods); - packet_start(SSH2_MSG_USERAUTH_FAILURE); - packet_put_cstring(methods); - packet_put_char(partial); - packet_send(); - packet_write_wait(); + if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 || + (r = sshpkt_put_cstring(ssh, methods)) != 0 || + (r = sshpkt_put_u8(ssh, partial)) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); free(methods); } } diff --git a/sshd.c b/sshd.c index 64f27a7bb..c2cd5b068 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.523 2019/01/19 21:37:48 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.524 2019/01/19 21:38:24 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2044,7 +2044,8 @@ main(int ac, char **av) /* perform the key exchange */ /* authenticate user and start session */ do_ssh2_kex(); - do_authentication2(authctxt); + ssh->authctxt = authctxt; + do_authentication2(ssh); /* * If we use privilege separation, the unprivileged child transfers -- cgit v1.2.3 From 6350e0316981489d4205952d6904d6fedba5bfe0 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:42:30 +0000 Subject: upstream: convert sshd.c to new packet API with & ok markus@ OpenBSD-Commit-ID: ea569d3eaf9b5cf1bad52779fbfa5fa0b28af891 --- sshd.c | 69 +++++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 30 deletions(-) (limited to 'sshd.c') diff --git a/sshd.c b/sshd.c index c2cd5b068..9dbb09c6d 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.524 2019/01/19 21:38:24 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.525 2019/01/19 21:42:30 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -123,7 +123,6 @@ #include "version.h" #include "ssherr.h" -#include "opacket.h" /* XXX */ extern struct ssh *active_state; /* XXX move decl to this file */ /* Re-exec fds */ @@ -244,7 +243,7 @@ struct passwd *privsep_pw = NULL; /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); void demote_sensitive_data(void); -static void do_ssh2_kex(void); +static void do_ssh2_kex(struct ssh *); /* * Close all listening sockets @@ -458,8 +457,9 @@ privsep_preauth_child(void) } static int -privsep_preauth(Authctxt *authctxt) +privsep_preauth(struct ssh *ssh) { + Authctxt *authctxt = (Authctxt *)ssh->authctxt; int status, r; pid_t pid; struct ssh_sandbox *box = NULL; @@ -467,7 +467,7 @@ privsep_preauth(Authctxt *authctxt) /* Set up unprivileged child process to deal with network data */ pmonitor = monitor_init(); /* Store a pointer to the kex for later rekeying */ - pmonitor->m_pkex = &active_state->kex; + pmonitor->m_pkex = &ssh->kex; if (use_privsep == PRIVSEP_ON) box = ssh_sandbox_init(pmonitor); @@ -527,7 +527,7 @@ privsep_preauth(Authctxt *authctxt) } static void -privsep_postauth(Authctxt *authctxt) +privsep_postauth(struct ssh *ssh, Authctxt *authctxt) { #ifdef DISABLE_FD_PASSING if (1) { @@ -576,7 +576,7 @@ privsep_postauth(Authctxt *authctxt) * Tell the packet layer that authentication was successful, since * this information is not part of the key state. */ - packet_set_authenticated(); + ssh_packet_set_authenticated(ssh); } static void @@ -759,21 +759,29 @@ notify_hostkeys(struct ssh *ssh) sshkey_ssh_name(key), fp); free(fp); if (nkeys == 0) { - packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("hostkeys-00@openssh.com"); - packet_put_char(0); /* want-reply */ + /* + * Start building the request when we find the + * first usable key. + */ + if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, "hostkeys-00@openssh.com")) != 0 || + (r = sshpkt_put_u8(ssh, 0)) != 0) /* want reply */ + sshpkt_fatal(ssh, r, "%s: start request", __func__); } + /* Append the key to the request */ sshbuf_reset(buf); if ((r = sshkey_putb(key, buf)) != 0) fatal("%s: couldn't put hostkey %d: %s", __func__, i, ssh_err(r)); - packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf)); + if ((r = sshpkt_put_stringb(ssh, buf)) != 0) + sshpkt_fatal(ssh, r, "%s: append key", __func__); nkeys++; } debug3("%s: sent %u hostkeys", __func__, nkeys); if (nkeys == 0) fatal("%s: no hostkeys", __func__); - packet_send(); + if ((r = sshpkt_send(ssh)) != 0) + sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } @@ -1951,9 +1959,10 @@ main(int ac, char **av) * Register our connection. This turns encryption off because we do * not have a key. */ - packet_set_connection(sock_in, sock_out); - packet_set_server(); - ssh = active_state; /* XXX */ + if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) + fatal("Unable to create connection"); + ssh_packet_set_server(ssh); + active_state = ssh; /* XXX needed elsewhere */ check_ip_options(ssh); @@ -1963,7 +1972,7 @@ main(int ac, char **av) process_permitopen(ssh, &options); /* Set SO_KEEPALIVE if requested. */ - if (options.tcp_keep_alive && packet_connection_is_on_socket() && + if (options.tcp_keep_alive && ssh_packet_connection_is_on_socket(ssh) && setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); @@ -2012,10 +2021,11 @@ main(int ac, char **av) if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0) cleanup_exit(255); /* error already logged */ - packet_set_nonblocking(); + ssh_packet_set_nonblocking(ssh); /* allocate authentication context */ authctxt = xcalloc(1, sizeof(*authctxt)); + ssh->authctxt = authctxt; authctxt->loginmsg = loginmsg; @@ -2032,7 +2042,7 @@ main(int ac, char **av) auth_debug_reset(); if (use_privsep) { - if (privsep_preauth(authctxt) == 1) + if (privsep_preauth(ssh) == 1) goto authenticated; } else if (have_agent) { if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { @@ -2043,8 +2053,7 @@ main(int ac, char **av) /* perform the key exchange */ /* authenticate user and start session */ - do_ssh2_kex(); - ssh->authctxt = authctxt; + do_ssh2_kex(ssh); do_authentication2(ssh); /* @@ -2053,7 +2062,7 @@ main(int ac, char **av) */ if (use_privsep) { mm_send_keystate(pmonitor); - packet_clear_keys(); + ssh_packet_clear_keys(ssh); exit(0); } @@ -2093,11 +2102,11 @@ main(int ac, char **av) * file descriptor passing. */ if (use_privsep) { - privsep_postauth(authctxt); + privsep_postauth(ssh, authctxt); /* the monitor process [priv] will not return */ } - packet_set_timeout(options.client_alive_interval, + ssh_packet_set_timeout(ssh, options.client_alive_interval, options.client_alive_count_max); /* Try to send all our hostkeys to the client */ @@ -2107,7 +2116,7 @@ main(int ac, char **av) do_authenticated(ssh, authctxt); /* The connection has been terminated. */ - packet_get_bytes(&ibytes, &obytes); + ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); @@ -2122,7 +2131,7 @@ main(int ac, char **av) PRIVSEP(audit_event(SSH_CONNECTION_CLOSE)); #endif - packet_close(); + ssh_packet_close(ssh); if (use_privsep) mm_terminate(); @@ -2156,7 +2165,7 @@ sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, /* SSH2 key exchange */ static void -do_ssh2_kex(void) +do_ssh2_kex(struct ssh *ssh) { char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; struct kex *kex; @@ -2177,16 +2186,16 @@ do_ssh2_kex(void) } if (options.rekey_limit || options.rekey_interval) - packet_set_rekey_limits(options.rekey_limit, + ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( list_hostkey_types()); /* start key exchange */ - if ((r = kex_setup(active_state, myproposal)) != 0) + if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); - kex = active_state->kex; + kex = ssh->kex; #ifdef WITH_OPENSSL kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; @@ -2205,7 +2214,7 @@ do_ssh2_kex(void) kex->host_key_index=&get_hostkey_index; kex->sign = sshd_hostkey_sign; - ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); session_id2 = kex->session_id; session_id2_len = kex->session_id_len; -- cgit v1.2.3 From ec00f918b8ad90295044266c433340a8adc93452 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:43:07 +0000 Subject: upstream: convert monitor.c to new packet API with & ok markus@ OpenBSD-Commit-ID: 61ecd154bd9804461a0cf5f495a29d919e0014d5 --- monitor.c | 169 +++++++++++++++++++++++++++------------------------------ monitor.h | 12 ++-- monitor_wrap.c | 3 +- monitor_wrap.h | 4 +- sshd.c | 11 ++-- 5 files changed, 94 insertions(+), 105 deletions(-) (limited to 'sshd.c') diff --git a/monitor.c b/monitor.c index 39bf7705c..387b50026 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.190 2019/01/19 21:41:18 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.191 2019/01/19 21:43:07 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -96,9 +96,6 @@ #include "match.h" #include "ssherr.h" -#include "opacket.h" /* XXX */ -extern struct ssh *active_state; /* XXX */ - #ifdef GSSAPI static Gssctxt *gsscontext = NULL; #endif @@ -115,48 +112,48 @@ static struct sshbuf *child_state; /* Functions on the monitor that answer unprivileged requests */ -int mm_answer_moduli(int, struct sshbuf *); -int mm_answer_sign(int, struct sshbuf *); -int mm_answer_pwnamallow(int, struct sshbuf *); -int mm_answer_auth2_read_banner(int, struct sshbuf *); -int mm_answer_authserv(int, struct sshbuf *); -int mm_answer_authpassword(int, struct sshbuf *); -int mm_answer_bsdauthquery(int, struct sshbuf *); -int mm_answer_bsdauthrespond(int, struct sshbuf *); -int mm_answer_keyallowed(int, struct sshbuf *); -int mm_answer_keyverify(int, struct sshbuf *); -int mm_answer_pty(int, struct sshbuf *); -int mm_answer_pty_cleanup(int, struct sshbuf *); -int mm_answer_term(int, struct sshbuf *); -int mm_answer_rsa_keyallowed(int, struct sshbuf *); -int mm_answer_rsa_challenge(int, struct sshbuf *); -int mm_answer_rsa_response(int, struct sshbuf *); -int mm_answer_sesskey(int, struct sshbuf *); -int mm_answer_sessid(int, struct sshbuf *); +int mm_answer_moduli(struct ssh *, int, struct sshbuf *); +int mm_answer_sign(struct ssh *, int, struct sshbuf *); +int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); +int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); +int mm_answer_authserv(struct ssh *, int, struct sshbuf *); +int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); +int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); +int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); +int mm_answer_skeyquery(struct ssh *, int, struct sshbuf *); +int mm_answer_skeyrespond(struct ssh *, int, struct sshbuf *); +int mm_answer_keyallowed(struct ssh *, int, struct sshbuf *); +int mm_answer_keyverify(struct ssh *, int, struct sshbuf *); +int mm_answer_pty(struct ssh *, int, struct sshbuf *); +int mm_answer_pty_cleanup(struct ssh *, int, struct sshbuf *); +int mm_answer_term(struct ssh *, int, struct sshbuf *); +int mm_answer_rsa_keyallowed(struct ssh *, int, struct sshbuf *); +int mm_answer_rsa_challenge(struct ssh *, int, struct sshbuf *); +int mm_answer_rsa_response(struct ssh *, int, struct sshbuf *); +int mm_answer_sesskey(struct ssh *, int, struct sshbuf *); +int mm_answer_sessid(struct ssh *, int, struct sshbuf *); #ifdef USE_PAM -int mm_answer_pam_start(int, struct sshbuf *); -int mm_answer_pam_account(int, struct sshbuf *); -int mm_answer_pam_init_ctx(int, struct sshbuf *); -int mm_answer_pam_query(int, struct sshbuf *); -int mm_answer_pam_respond(int, struct sshbuf *); -int mm_answer_pam_free_ctx(int, struct sshbuf *); +int mm_answer_pam_start(struct ssh *, int, struct sshbuf *); +int mm_answer_pam_account(struct ssh *, int, struct sshbuf *); +int mm_answer_pam_init_ctx(struct ssh *, int, struct sshbuf *); +int mm_answer_pam_query(struct ssh *, int, struct sshbuf *); +int mm_answer_pam_respond(struct ssh *, int, struct sshbuf *); +int mm_answer_pam_free_ctx(struct ssh *, int, struct sshbuf *); #endif #ifdef GSSAPI -int mm_answer_gss_setup_ctx(int, struct sshbuf *); -int mm_answer_gss_accept_ctx(int, struct sshbuf *); -int mm_answer_gss_userok(int, struct sshbuf *); -int mm_answer_gss_checkmic(int, struct sshbuf *); +int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); +int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); +int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); +int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); #endif #ifdef SSH_AUDIT_EVENTS -int mm_answer_audit_event(int, struct sshbuf *); -int mm_answer_audit_command(int, struct sshbuf *); +int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); +int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); #endif -static int monitor_read_log(struct monitor *); - static Authctxt *authctxt; /* local state for key verify */ @@ -175,7 +172,7 @@ static pid_t monitor_child_pid; struct mon_table { enum monitor_reqtype type; int flags; - int (*f)(int, struct sshbuf *); + int (*f)(struct ssh *, int, struct sshbuf *); }; #define MON_ISAUTH 0x0004 /* Required for Authentication */ @@ -187,6 +184,10 @@ struct mon_table { #define MON_PERMIT 0x1000 /* Request is permitted */ +static int monitor_read(struct ssh *, struct monitor *, struct mon_table *, + struct mon_table **); +static int monitor_read_log(struct monitor *); + struct mon_table mon_dispatch_proto20[] = { #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, @@ -268,9 +269,8 @@ monitor_permit_authentications(int permit) } void -monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) +monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) { - struct ssh *ssh = active_state; /* XXX */ struct mon_table *ent; int authenticated = 0, partial = 0; @@ -282,7 +282,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) close(pmonitor->m_log_sendfd); pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; - authctxt = _authctxt; + authctxt = (Authctxt *)ssh->authctxt; memset(authctxt, 0, sizeof(*authctxt)); ssh->authctxt = authctxt; @@ -300,7 +300,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) auth_submethod = NULL; auth2_authctxt_reset_info(authctxt); - authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); + authenticated = (monitor_read(ssh, pmonitor, + mon_dispatch, &ent) == 1); /* Special handling for multiple required authentications */ if (options.num_auth_methods != 0) { @@ -332,7 +333,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_PAM_ACCOUNT, m); authenticated = mm_answer_pam_account( - pmonitor->m_sendfd, m); + ssh, pmonitor->m_sendfd, m); sshbuf_free(m); } #endif @@ -385,7 +386,7 @@ monitor_child_handler(int sig) } void -monitor_child_postauth(struct monitor *pmonitor) +monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) { close(pmonitor->m_recvfd); pmonitor->m_recvfd = -1; @@ -411,7 +412,7 @@ monitor_child_postauth(struct monitor *pmonitor) } for (;;) - monitor_read(pmonitor, mon_dispatch, NULL); + monitor_read(ssh, pmonitor, mon_dispatch, NULL); } static int @@ -466,8 +467,8 @@ monitor_read_log(struct monitor *pmonitor) return 0; } -int -monitor_read(struct monitor *pmonitor, struct mon_table *ent, +static int +monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent, struct mon_table **pent) { struct sshbuf *m; @@ -517,7 +518,7 @@ monitor_read(struct monitor *pmonitor, struct mon_table *ent, if (!(ent->flags & MON_PERMIT)) fatal("%s: unpermitted request %d", __func__, type); - ret = (*ent->f)(pmonitor->m_sendfd, m); + ret = (*ent->f)(ssh, pmonitor->m_sendfd, m); sshbuf_free(m); /* The child may use this request only once, disable it */ @@ -568,7 +569,7 @@ monitor_reset_key_state(void) #ifdef WITH_OPENSSL int -mm_answer_moduli(int sock, struct sshbuf *m) +mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m) { DH *dh; const BIGNUM *dh_p, *dh_g; @@ -610,9 +611,8 @@ mm_answer_moduli(int sock, struct sshbuf *m) #endif int -mm_answer_sign(int sock, struct sshbuf *m) +mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) { - struct ssh *ssh = active_state; /* XXX */ extern int auth_sock; /* XXX move to state struct? */ struct sshkey *key; struct sshbuf *sigbuf = NULL; @@ -713,9 +713,8 @@ mm_answer_sign(int sock, struct sshbuf *m) /* Retrieves the password entry and also checks if the user is permitted */ int -mm_answer_pwnamallow(int sock, struct sshbuf *m) +mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) { - struct ssh *ssh = active_state; /* XXX */ char *username; struct passwd *pwent; int r, allowed = 0; @@ -813,7 +812,7 @@ mm_answer_pwnamallow(int sock, struct sshbuf *m) return (0); } -int mm_answer_auth2_read_banner(int sock, struct sshbuf *m) +int mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m) { char *banner; int r; @@ -829,7 +828,7 @@ int mm_answer_auth2_read_banner(int sock, struct sshbuf *m) } int -mm_answer_authserv(int sock, struct sshbuf *m) +mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m) { int r; @@ -879,9 +878,8 @@ key_base_type_match(const char *method, const struct sshkey *key, } int -mm_answer_authpassword(int sock, struct sshbuf *m) +mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { - struct ssh *ssh = active_state; /* XXX */ static int call_count; char *passwd; int r, authenticated; @@ -920,7 +918,7 @@ mm_answer_authpassword(int sock, struct sshbuf *m) #ifdef BSD_AUTH int -mm_answer_bsdauthquery(int sock, struct sshbuf *m) +mm_answer_bsdauthquery(struct ssh *ssh, int sock, struct sshbuf *m) { char *name, *infotxt; u_int numprompts, *echo_on, success; @@ -954,7 +952,7 @@ mm_answer_bsdauthquery(int sock, struct sshbuf *m) } int -mm_answer_bsdauthrespond(int sock, struct sshbuf *m) +mm_answer_bsdauthrespond(struct ssh *ssh, int sock, struct sshbuf *m) { char *response; int r, authok; @@ -988,7 +986,7 @@ mm_answer_bsdauthrespond(int sock, struct sshbuf *m) #ifdef USE_PAM int -mm_answer_pam_start(int sock, struct sshbuf *m) +mm_answer_pam_start(struct ssh *ssh, int sock, struct sshbuf *m) { if (!options.use_pam) fatal("UsePAM not set, but ended up in %s anyway", __func__); @@ -1003,7 +1001,7 @@ mm_answer_pam_start(int sock, struct sshbuf *m) } int -mm_answer_pam_account(int sock, struct sshbuf *m) +mm_answer_pam_account(struct ssh *ssh, int sock, struct sshbuf *m) { u_int ret; int r; @@ -1026,7 +1024,7 @@ static void *sshpam_ctxt, *sshpam_authok; extern KbdintDevice sshpam_device; int -mm_answer_pam_init_ctx(int sock, struct sshbuf *m) +mm_answer_pam_init_ctx(struct ssh *ssh, int sock, struct sshbuf *m) { u_int ok = 0; int r; @@ -1051,7 +1049,7 @@ mm_answer_pam_init_ctx(int sock, struct sshbuf *m) } int -mm_answer_pam_query(int sock, struct sshbuf *m) +mm_answer_pam_query(struct ssh *ssh, int sock, struct sshbuf *m) { char *name = NULL, *info = NULL, **prompts = NULL; u_int i, num = 0, *echo_on = 0; @@ -1092,7 +1090,7 @@ mm_answer_pam_query(int sock, struct sshbuf *m) } int -mm_answer_pam_respond(int sock, struct sshbuf *m) +mm_answer_pam_respond(struct ssh *ssh, int sock, struct sshbuf *m) { char **resp; u_int i, num; @@ -1130,7 +1128,7 @@ mm_answer_pam_respond(int sock, struct sshbuf *m) } int -mm_answer_pam_free_ctx(int sock, struct sshbuf *m) +mm_answer_pam_free_ctx(struct ssh *ssh, int sock, struct sshbuf *m) { int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; @@ -1150,9 +1148,8 @@ mm_answer_pam_free_ctx(int sock, struct sshbuf *m) #endif int -mm_answer_keyallowed(int sock, struct sshbuf *m) +mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) { - struct ssh *ssh = active_state; /* XXX */ struct sshkey *key = NULL; char *cuser, *chost; u_int pubkey_auth_attempt; @@ -1387,9 +1384,8 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, } int -mm_answer_keyverify(int sock, struct sshbuf *m) +mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) { - struct ssh *ssh = active_state; /* XXX */ struct sshkey *key; u_char *signature, *data, *blob; char *sigalg; @@ -1434,7 +1430,7 @@ mm_answer_keyverify(int sock, struct sshbuf *m) fatal("%s: bad signature data blob", __func__); ret = sshkey_verify(key, signature, signaturelen, data, datalen, - sigalg, active_state->compat); + sigalg, ssh->compat); debug3("%s: %s %p signature %s", __func__, auth_method, key, (ret == 0) ? "verified" : "unverified"); auth2_record_key(authctxt, ret == 0, key); @@ -1461,9 +1457,8 @@ mm_answer_keyverify(int sock, struct sshbuf *m) } static void -mm_record_login(Session *s, struct passwd *pw) +mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw) { - struct ssh *ssh = active_state; /* XXX */ socklen_t fromlen; struct sockaddr_storage from; @@ -1473,8 +1468,8 @@ mm_record_login(Session *s, struct passwd *pw) */ memset(&from, 0, sizeof(from)); fromlen = sizeof(from); - if (packet_connection_is_on_socket()) { - if (getpeername(packet_get_connection_in(), + if (ssh_packet_connection_is_on_socket(ssh)) { + if (getpeername(ssh_packet_get_connection_in(ssh), (struct sockaddr *)&from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); cleanup_exit(255); @@ -1498,7 +1493,7 @@ mm_session_close(Session *s) } int -mm_answer_pty(int sock, struct sshbuf *m) +mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) { extern struct monitor *pmonitor; Session *s; @@ -1526,7 +1521,7 @@ mm_answer_pty(int sock, struct sshbuf *m) if (dup2(s->ttyfd, 0) == -1) fatal("%s: dup2", __func__); - mm_record_login(s, authctxt->pw); + mm_record_login(ssh, s, authctxt->pw); /* Now we can close the file descriptor again */ close(0); @@ -1568,7 +1563,7 @@ mm_answer_pty(int sock, struct sshbuf *m) } int -mm_answer_pty_cleanup(int sock, struct sshbuf *m) +mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m) { Session *s; char *tty; @@ -1586,9 +1581,8 @@ mm_answer_pty_cleanup(int sock, struct sshbuf *m) } int -mm_answer_term(int sock, struct sshbuf *req) +mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) { - struct ssh *ssh = active_state; /* XXX */ extern struct monitor *pmonitor; int res, status; @@ -1615,7 +1609,7 @@ mm_answer_term(int sock, struct sshbuf *req) #ifdef SSH_AUDIT_EVENTS /* Report that an audit event occurred */ int -mm_answer_audit_event(int socket, struct sshbuf *m) +mm_answer_audit_event(struct ssh *ssh, int socket, struct sshbuf *m) { u_int n; ssh_audit_event_t event; @@ -1644,7 +1638,7 @@ mm_answer_audit_event(int socket, struct sshbuf *m) } int -mm_answer_audit_command(int socket, struct sshbuf *m) +mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) { char *cmd; int r; @@ -1660,10 +1654,8 @@ mm_answer_audit_command(int socket, struct sshbuf *m) #endif /* SSH_AUDIT_EVENTS */ void -monitor_clear_keystate(struct monitor *pmonitor) +monitor_clear_keystate(struct ssh *ssh, struct monitor *pmonitor) { - struct ssh *ssh = active_state; /* XXX */ - ssh_clear_newkeys(ssh, MODE_IN); ssh_clear_newkeys(ssh, MODE_OUT); sshbuf_free(child_state); @@ -1671,9 +1663,8 @@ monitor_clear_keystate(struct monitor *pmonitor) } void -monitor_apply_keystate(struct monitor *pmonitor) +monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) { - struct ssh *ssh = active_state; /* XXX */ struct kex *kex; int r; @@ -1780,7 +1771,7 @@ monitor_reinit(struct monitor *mon) #ifdef GSSAPI int -mm_answer_gss_setup_ctx(int sock, struct sshbuf *m) +mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) { gss_OID_desc goid; OM_uint32 major; @@ -1813,7 +1804,7 @@ mm_answer_gss_setup_ctx(int sock, struct sshbuf *m) } int -mm_answer_gss_accept_ctx(int sock, struct sshbuf *m) +mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) { gss_buffer_desc in; gss_buffer_desc out = GSS_C_EMPTY_BUFFER; @@ -1847,7 +1838,7 @@ mm_answer_gss_accept_ctx(int sock, struct sshbuf *m) } int -mm_answer_gss_checkmic(int sock, struct sshbuf *m) +mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) { gss_buffer_desc gssbuf, mic; OM_uint32 ret; @@ -1878,7 +1869,7 @@ mm_answer_gss_checkmic(int sock, struct sshbuf *m) } int -mm_answer_gss_userok(int sock, struct sshbuf *m) +mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) { int r, authenticated; const char *displayname; diff --git a/monitor.h b/monitor.h index 16047299f..a4b68fbe2 100644 --- a/monitor.h +++ b/monitor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.21 2018/07/09 21:53:45 markus Exp $ */ +/* $OpenBSD: monitor.h,v 1.22 2019/01/19 21:43:07 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -65,6 +65,8 @@ enum monitor_reqtype { }; +struct ssh; + struct monitor { int m_recvfd; int m_sendfd; @@ -78,11 +80,11 @@ struct monitor *monitor_init(void); void monitor_reinit(struct monitor *); struct Authctxt; -void monitor_child_preauth(struct Authctxt *, struct monitor *); -void monitor_child_postauth(struct monitor *); +void monitor_child_preauth(struct ssh *, struct monitor *); +void monitor_child_postauth(struct ssh *, struct monitor *); -struct mon_table; -int monitor_read(struct monitor*, struct mon_table *, struct mon_table **); +void monitor_clear_keystate(struct ssh *, struct monitor *); +void monitor_apply_keystate(struct ssh *, struct monitor *); /* Prototypes for request sending and receiving */ void mm_request_send(int, enum monitor_reqtype, struct sshbuf *); diff --git a/monitor_wrap.c b/monitor_wrap.c index 5db8a0a9c..4bdfd518e 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.109 2019/01/19 21:41:18 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.110 2019/01/19 21:43:07 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -76,7 +76,6 @@ #include "ssherr.h" -#include "opacket.h" /* XXX */ extern struct ssh *active_state; /* XXX */ /* Imports */ diff --git a/monitor_wrap.h b/monitor_wrap.h index 19c58e486..8277cbf45 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.39 2019/01/19 21:41:18 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.40 2019/01/19 21:43:07 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -89,8 +89,6 @@ void mm_session_pty_cleanup2(struct Session *); struct newkeys *mm_newkeys_from_blob(u_char *, int); int mm_newkeys_to_blob(int, u_char **, u_int *); -void monitor_clear_keystate(struct monitor *); -void monitor_apply_keystate(struct monitor *); void mm_get_keystate(struct monitor *); void mm_send_keystate(struct monitor*); diff --git a/sshd.c b/sshd.c index 9dbb09c6d..0c93f7f31 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.525 2019/01/19 21:42:30 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.526 2019/01/19 21:43:07 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -459,7 +459,6 @@ privsep_preauth_child(void) static int privsep_preauth(struct ssh *ssh) { - Authctxt *authctxt = (Authctxt *)ssh->authctxt; int status, r; pid_t pid; struct ssh_sandbox *box = NULL; @@ -488,7 +487,7 @@ privsep_preauth(struct ssh *ssh) } if (box != NULL) ssh_sandbox_parent_preauth(box, pid); - monitor_child_preauth(authctxt, pmonitor); + monitor_child_preauth(ssh, pmonitor); /* Wait for the child's exit status */ while (waitpid(pid, &status, 0) < 0) { @@ -548,8 +547,8 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) else if (pmonitor->m_pid != 0) { verbose("User child is on pid %ld", (long)pmonitor->m_pid); sshbuf_reset(loginmsg); - monitor_clear_keystate(pmonitor); - monitor_child_postauth(pmonitor); + monitor_clear_keystate(ssh, pmonitor); + monitor_child_postauth(ssh, pmonitor); /* NEVERREACHED */ exit(0); @@ -570,7 +569,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) skip: /* It is safe now to apply the key state */ - monitor_apply_keystate(pmonitor); + monitor_apply_keystate(ssh, pmonitor); /* * Tell the packet layer that authentication was successful, since -- cgit v1.2.3 From 04c091fc199f17dacf8921df0a06634b454e2722 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sat, 19 Jan 2019 21:43:56 +0000 Subject: upstream: remove last references to active_state with & ok markus@ OpenBSD-Commit-ID: 78619a50ea7e4ca2f3b54d4658b3227277490ba2 --- auth.h | 10 ++++----- auth2-hostbased.c | 12 +++++------ kex.h | 6 +++--- kexc25519s.c | 6 +++--- kexdhs.c | 6 +++--- kexecdhs.c | 6 +++--- kexgexs.c | 6 +++--- monitor.c | 8 +++---- monitor.h | 3 ++- monitor_wrap.c | 15 ++++++------- monitor_wrap.h | 11 +++++----- serverloop.c | 6 +++--- ssh.c | 5 +---- ssh_api.c | 15 ++++++------- sshd.c | 63 +++++++++++++++++++++++++++++++------------------------ 15 files changed, 90 insertions(+), 88 deletions(-) (limited to 'sshd.c') diff --git a/auth.h b/auth.h index 71c372e97..bf393e755 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.98 2019/01/19 21:41:18 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.99 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -132,8 +132,8 @@ auth_rhosts2(struct passwd *, const char *, const char *, const char *); int auth_password(struct ssh *, const char *); -int hostbased_key_allowed(struct passwd *, const char *, char *, - struct sshkey *); +int hostbased_key_allowed(struct ssh *, struct passwd *, + const char *, char *, struct sshkey *); int user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int, struct sshauthopt **); int auth2_key_already_used(Authctxt *, const struct sshkey *); @@ -208,8 +208,8 @@ struct sshkey *get_hostkey_public_by_index(int, struct ssh *); struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *); struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *); int get_hostkey_index(struct sshkey *, int, struct ssh *); -int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **, - size_t *, const u_char *, size_t, const char *, u_int); +int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); /* Key / cert options linkage to auth layer */ const struct sshauthopt *auth_options(struct ssh *); diff --git a/auth2-hostbased.c b/auth2-hostbased.c index e28a48fb3..0c40fad4e 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.39 2019/01/19 21:31:32 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.40 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -51,8 +51,6 @@ #include "ssherr.h" #include "match.h" -extern struct ssh *active_state; /* XXX */ - /* import */ extern ServerOptions options; extern u_char *session_id2; @@ -149,7 +147,8 @@ userauth_hostbased(struct ssh *ssh) /* test for allowed key and correct signature */ authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && + if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, + chost, key)) && PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0) authenticated = 1; @@ -169,10 +168,9 @@ done: /* return 1 if given hostkey is allowed */ int -hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, - struct sshkey *key) +hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, + const char *cuser, char *chost, struct sshkey *key) { - struct ssh *ssh = active_state; /* XXX */ const char *resolvedname, *ipaddr, *lookup, *reason; HostStatus host_status; int len; diff --git a/kex.h b/kex.h index 9ba860954..085e60b52 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.93 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.94 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -156,8 +156,8 @@ struct kex { struct sshkey *(*load_host_public_key)(int, int, struct ssh *); struct sshkey *(*load_host_private_key)(int, int, struct ssh *); int (*host_key_index)(struct sshkey *, int, struct ssh *); - int (*sign)(struct sshkey *, struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int); + int (*sign)(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); int (*kex[KEX_MAX])(struct ssh *); /* kex specific state */ DH *dh; /* DH */ diff --git a/kexc25519s.c b/kexc25519s.c index 81f816e56..9ff74d912 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.12 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.13 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -133,8 +133,8 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ diff --git a/kexdhs.c b/kexdhs.c index adf70babd..c8be1b2f7 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.30 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -189,8 +189,8 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; /* destroy_sensitive_data(); */ diff --git a/kexecdhs.c b/kexecdhs.c index c690feffe..45ac3f794 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.18 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.19 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -168,8 +168,8 @@ input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; /* destroy_sensitive_data(); */ diff --git a/kexgexs.c b/kexgexs.c index cd0e758c4..3b2ad37e4 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.36 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.37 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -223,8 +223,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, &signature, - &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) goto out; /* destroy_sensitive_data(); */ diff --git a/monitor.c b/monitor.c index 387b50026..1dcf930d4 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.191 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.192 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -360,7 +360,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) ssh->authctxt = NULL; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); - mm_get_keystate(pmonitor); + mm_get_keystate(ssh, pmonitor); /* Drain any buffered messages from the child */ while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) @@ -1195,7 +1195,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) if (!key_base_type_match(auth_method, key, options.hostbased_key_types)) break; - allowed = hostbased_key_allowed(authctxt->pw, + allowed = hostbased_key_allowed(ssh, authctxt->pw, cuser, chost, key); auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", @@ -1699,7 +1699,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) /* This function requries careful sanity checking */ void -mm_get_keystate(struct monitor *pmonitor) +mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { debug3("%s: Waiting for new keys", __func__); diff --git a/monitor.h b/monitor.h index a4b68fbe2..683e5e071 100644 --- a/monitor.h +++ b/monitor.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.22 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor.h,v 1.23 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -90,5 +90,6 @@ void monitor_apply_keystate(struct ssh *, struct monitor *); void mm_request_send(int, enum monitor_reqtype, struct sshbuf *); void mm_request_receive(int, struct sshbuf *); void mm_request_receive_expect(int, enum monitor_reqtype, struct sshbuf *); +void mm_get_keystate(struct ssh *, struct monitor *); #endif /* _MONITOR_H_ */ diff --git a/monitor_wrap.c b/monitor_wrap.c index 4bdfd518e..5a0964b69 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.110 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.111 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -76,8 +76,6 @@ #include "ssherr.h" -extern struct ssh *active_state; /* XXX */ - /* Imports */ extern struct monitor *pmonitor; extern struct sshbuf *loginmsg; @@ -220,12 +218,12 @@ mm_choose_dh(int min, int nbits, int max) #endif int -mm_sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp, +mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *hostkey_alg, u_int compat) { struct kex *kex = *pmonitor->m_pkex; struct sshbuf *m; - u_int ndx = kex->host_key_index(key, 0, active_state); + u_int ndx = kex->host_key_index(key, 0, ssh); int r; debug3("%s entering", __func__); @@ -439,8 +437,8 @@ mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, } int -mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host, - struct sshkey *key) +mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, + const char *user, const char *host, struct sshkey *key) { return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL)); } @@ -533,9 +531,8 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, } void -mm_send_keystate(struct monitor *monitor) +mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { - struct ssh *ssh = active_state; /* XXX */ struct sshbuf *m; int r; diff --git a/monitor_wrap.h b/monitor_wrap.h index 8277cbf45..2b7052202 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.40 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.41 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -42,8 +42,8 @@ struct sshauthopt; void mm_log_handler(LogLevel, const char *, void *); int mm_is_monitor(void); DH *mm_choose_dh(int, int, int); -int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t, - const char *, u_int compat); +int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, + const u_char *, size_t, const char *, u_int compat); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(struct ssh *, const char *); char *mm_auth2_read_banner(void); @@ -52,7 +52,7 @@ int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *, int, struct sshauthopt **); int mm_user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int, struct sshauthopt **); -int mm_hostbased_key_allowed(struct passwd *, const char *, +int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, const char *, struct sshkey *); int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, const u_char *, size_t, const char *, u_int); @@ -89,8 +89,7 @@ void mm_session_pty_cleanup2(struct Session *); struct newkeys *mm_newkeys_from_blob(u_char *, int); int mm_newkeys_to_blob(int, u_char **, u_int *); -void mm_get_keystate(struct monitor *); -void mm_send_keystate(struct monitor*); +void mm_send_keystate(struct ssh *, struct monitor*); /* bsdauth */ int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); diff --git a/serverloop.c b/serverloop.c index c60758e88..afb32fd34 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.211 2019/01/19 21:40:48 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.212 2019/01/19 21:43:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -782,9 +782,9 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) (r = sshbuf_put_string(sigbuf, ssh->kex->session_id, ssh->kex->session_id_len)) != 0 || (r = sshkey_puts(key, sigbuf)) != 0 || - (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen, + (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), - use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0 || + use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error("%s: couldn't prepare signature: %s", __func__, ssh_err(r)); diff --git a/ssh.c b/ssh.c index 160bf6b54..91e7c3511 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.499 2019/01/19 21:36:06 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.500 2019/01/19 21:43:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -113,8 +113,6 @@ #include "ssh-pkcs11.h" #endif -extern struct ssh *active_state; /* XXX remove after sshconnect2.c updated */ - extern char *__progname; /* Saves a copy of argv for setproctitle emulation */ @@ -652,7 +650,6 @@ main(int ac, char **av) */ if ((ssh = ssh_alloc_session_state()) == NULL) fatal("Couldn't allocate session state"); - active_state = ssh; /* XXX */ channel_init_channels(ssh); /* Parse command-line arguments. */ diff --git a/ssh_api.c b/ssh_api.c index ab209c4ca..182c0d7e4 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.9 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.10 2019/01/19 21:43:56 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -40,8 +40,8 @@ int _ssh_order_hostkeyalgs(struct ssh *); int _ssh_verify_host_key(struct sshkey *, struct ssh *); struct sshkey *_ssh_host_public_key(int, int, struct ssh *); struct sshkey *_ssh_host_private_key(int, int, struct ssh *); -int _ssh_host_key_sign(struct sshkey *, struct sshkey *, - u_char **, size_t *, const u_char *, size_t, const char *, u_int); +int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); /* * stubs for the server side implementation of kex. @@ -547,9 +547,10 @@ _ssh_order_hostkeyalgs(struct ssh *ssh) } int -_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey, - u_char **signature, size_t *slen, const u_char *data, size_t dlen, - const char *alg, u_int compat) +_ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey, + struct sshkey *pubkey, u_char **signature, size_t *slen, + const u_char *data, size_t dlen, const char *alg) { - return sshkey_sign(privkey, signature, slen, data, dlen, alg, compat); + return sshkey_sign(privkey, signature, slen, data, dlen, + alg, ssh->compat); } diff --git a/sshd.c b/sshd.c index 0c93f7f31..58d17e546 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.526 2019/01/19 21:43:07 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.527 2019/01/19 21:43:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -123,8 +123,6 @@ #include "version.h" #include "ssherr.h" -extern struct ssh *active_state; /* XXX move decl to this file */ - /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) @@ -225,8 +223,9 @@ struct monitor *pmonitor = NULL; int privsep_is_preauth = 1; static int privsep_chroot = 1; -/* global authentication context */ +/* global connection state and authentication contexts */ Authctxt *the_authctxt = NULL; +struct ssh *the_active_state; /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ struct sshauthopt *auth_opts = NULL; @@ -353,9 +352,11 @@ grace_alarm_handler(int sig) kill(0, SIGTERM); } + /* XXX pre-format ipaddr/port so we don't need to access active_state */ /* Log error and exit. */ sigdie("Timeout before authentication for %s port %d", - ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); + ssh_remote_ipaddr(the_active_state), + ssh_remote_port(the_active_state)); } /* Destroy the host and server keys. They will no longer be needed. */ @@ -742,7 +743,7 @@ notify_hostkeys(struct ssh *ssh) char *fp; /* Some clients cannot cope with the hostkeys message, skip those. */ - if (datafellows & SSH_BUG_HOSTKEYS) + if (ssh->compat & SSH_BUG_HOSTKEYS) return; if ((buf = sshbuf_new()) == NULL) @@ -1960,8 +1961,8 @@ main(int ac, char **av) */ if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) fatal("Unable to create connection"); + the_active_state = ssh; ssh_packet_set_server(ssh); - active_state = ssh; /* XXX needed elsewhere */ check_ip_options(ssh); @@ -2060,7 +2061,7 @@ main(int ac, char **av) * the current keystate and exits */ if (use_privsep) { - mm_send_keystate(pmonitor); + mm_send_keystate(ssh, pmonitor); ssh_packet_clear_keys(ssh); exit(0); } @@ -2139,25 +2140,35 @@ main(int ac, char **av) } int -sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, - u_char **signature, size_t *slenp, const u_char *data, size_t dlen, - const char *alg, u_int flag) +sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, + struct sshkey *pubkey, u_char **signature, size_t *slenp, + const u_char *data, size_t dlen, const char *alg) { int r; - if (privkey) { - if (PRIVSEP(sshkey_sign(privkey, signature, slenp, data, dlen, - alg, datafellows)) < 0) - fatal("%s: key_sign failed", __func__); - } else if (use_privsep) { - if (mm_sshkey_sign(pubkey, signature, slenp, data, dlen, - alg, datafellows) < 0) - fatal("%s: pubkey_sign failed", __func__); + if (use_privsep) { + if (privkey) { + if (mm_sshkey_sign(ssh, privkey, signature, slenp, + data, dlen, alg, ssh->compat) < 0) + fatal("%s: privkey sign failed", __func__); + } else { + if (mm_sshkey_sign(ssh, pubkey, signature, slenp, + data, dlen, alg, ssh->compat) < 0) + fatal("%s: pubkey sign failed", __func__); + } } else { - if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slenp, - data, dlen, alg, datafellows)) != 0) - fatal("%s: ssh_agent_sign failed: %s", - __func__, ssh_err(r)); + if (privkey) { + if (sshkey_sign(privkey, signature, slenp, data, dlen, + alg, ssh->compat) < 0) + fatal("%s: privkey sign failed", __func__); + } else { + if ((r = ssh_agent_sign(auth_sock, pubkey, + signature, slenp, data, dlen, alg, + ssh->compat)) != 0) { + fatal("%s: agent sign failed: %s", + __func__, ssh_err(r)); + } + } } return 0; } @@ -2232,10 +2243,8 @@ do_ssh2_kex(struct ssh *ssh) void cleanup_exit(int i) { - struct ssh *ssh = active_state; /* XXX */ - - if (the_authctxt) { - do_cleanup(ssh, the_authctxt); + if (the_active_state != NULL && the_authctxt != NULL) { + do_cleanup(the_active_state, the_authctxt); if (use_privsep && privsep_is_preauth && pmonitor != NULL && pmonitor->m_pid > 1) { debug("Killing privsep child %d", pmonitor->m_pid); -- cgit v1.2.3 From 9b655dc9c9a353f0a527f0c6c43a5e35653c9503 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 20 Jan 2019 14:55:27 +1100 Subject: last bits of old packet API / active_state global --- audit-bsm.c | 2 +- audit-linux.c | 4 +--- audit.c | 2 +- audit.h | 4 +++- auth.c | 4 ++-- auth2.c | 6 +++--- monitor.c | 2 +- monitor_wrap.c | 2 +- monitor_wrap.h | 2 +- regress/misc/kexfuzz/kexfuzz.c | 2 -- regress/unittests/kex/test_kex.c | 2 -- session.c | 32 -------------------------------- ssh-keyscan.c | 2 -- ssh-keysign.c | 2 -- sshd.c | 8 ++++---- 15 files changed, 18 insertions(+), 58 deletions(-) (limited to 'sshd.c') diff --git a/audit-bsm.c b/audit-bsm.c index 1409f69ae..0ba16c72c 100644 --- a/audit-bsm.c +++ b/audit-bsm.c @@ -391,7 +391,7 @@ audit_session_close(struct logininfo *li) } void -audit_event(ssh_audit_event_t event) +audit_event(struct ssh *ssh, ssh_audit_event_t event) { char textbuf[BSM_TEXTBUFSZ]; static int logged_in = 0; diff --git a/audit-linux.c b/audit-linux.c index 136ed76bb..3fcbe5c53 100644 --- a/audit-linux.c +++ b/audit-linux.c @@ -97,10 +97,8 @@ audit_session_close(struct logininfo *li) } void -audit_event(ssh_audit_event_t event) +audit_event(struct ssh *ssh, ssh_audit_event_t event) { - struct ssh *ssh = active_state; /* XXX */ - switch(event) { case SSH_AUTH_SUCCESS: case SSH_CONNECTION_CLOSE: diff --git a/audit.c b/audit.c index 33a04376d..dd2f03558 100644 --- a/audit.c +++ b/audit.c @@ -131,7 +131,7 @@ audit_connection_from(const char *host, int port) * events and what they mean). */ void -audit_event(ssh_audit_event_t event) +audit_event(struct ssh *ssh, ssh_audit_event_t event) { debug("audit event euid %d user %s event %d (%s)", geteuid(), audit_username(), event, audit_event_lookup(event)); diff --git a/audit.h b/audit.h index 0b593666d..38cb5ad31 100644 --- a/audit.h +++ b/audit.h @@ -27,6 +27,8 @@ #include "loginrec.h" +struct ssh; + enum ssh_audit_event_type { SSH_LOGIN_EXCEED_MAXTRIES, SSH_LOGIN_ROOT_DENIED, @@ -46,7 +48,7 @@ enum ssh_audit_event_type { typedef enum ssh_audit_event_type ssh_audit_event_t; void audit_connection_from(const char *, int); -void audit_event(ssh_audit_event_t); +void audit_event(struct ssh *, ssh_audit_event_t); void audit_session_open(struct logininfo *); void audit_session_close(struct logininfo *); void audit_run_command(const char *); diff --git a/auth.c b/auth.c index a4c1dece5..62c58e72f 100644 --- a/auth.c +++ b/auth.c @@ -367,7 +367,7 @@ auth_log(struct ssh *ssh, int authenticated, int partial, #endif #ifdef SSH_AUDIT_EVENTS if (authenticated == 0 && !authctxt->postponed) - audit_event(audit_classify_auth(method)); + audit_event(ssh, audit_classify_auth(method)); #endif } @@ -605,7 +605,7 @@ getpwnamallow(struct ssh *ssh, const char *user) auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); #endif #ifdef SSH_AUDIT_EVENTS - audit_event(SSH_INVALID_USER); + audit_event(ssh, SSH_INVALID_USER); #endif /* SSH_AUDIT_EVENTS */ return (NULL); } diff --git a/auth2.c b/auth2.c index a80b3f872..e43350c36 100644 --- a/auth2.c +++ b/auth2.c @@ -294,7 +294,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) /* Invalid user, fake password information */ authctxt->pw = fakepw(); #ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_INVALID_USER)); + PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); #endif } #ifdef USE_PAM @@ -369,7 +369,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, !auth_root_allowed(ssh, method)) { authenticated = 0; #ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); + PRIVSEP(audit_event(ssh, SSH_LOGIN_ROOT_DENIED)); #endif } @@ -430,7 +430,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); + PRIVSEP(audit_event(ssh, SSH_LOGIN_EXCEED_MAXTRIES)); #endif auth_maxtries_exceeded(ssh); } diff --git a/monitor.c b/monitor.c index 5fa30b2a8..a9546dad2 100644 --- a/monitor.c +++ b/monitor.c @@ -1628,7 +1628,7 @@ mm_answer_audit_event(struct ssh *ssh, int socket, struct sshbuf *m) case SSH_LOGIN_ROOT_DENIED: case SSH_CONNECTION_CLOSE: case SSH_INVALID_USER: - audit_event(event); + audit_event(ssh, event); break; default: fatal("Audit event type %d not permitted", event); diff --git a/monitor_wrap.c b/monitor_wrap.c index f52b9c88c..9e3c7cd17 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -867,7 +867,7 @@ mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) #ifdef SSH_AUDIT_EVENTS void -mm_audit_event(ssh_audit_event_t event) +mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) { struct sshbuf *m; int r; diff --git a/monitor_wrap.h b/monitor_wrap.h index c7e0c91dd..fdebb3aa4 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -76,7 +76,7 @@ void mm_sshpam_free_ctx(void *); #ifdef SSH_AUDIT_EVENTS #include "audit.h" -void mm_audit_event(ssh_audit_event_t); +void mm_audit_event(struct ssh *, ssh_audit_event_t); void mm_audit_run_command(const char *); #endif diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c index 3e2c48160..61cae042f 100644 --- a/regress/misc/kexfuzz/kexfuzz.c +++ b/regress/misc/kexfuzz/kexfuzz.c @@ -29,8 +29,6 @@ #include "authfile.h" #include "log.h" -struct ssh *active_state = NULL; /* XXX - needed for linking */ - void kex_tests(void); static int do_debug = 0; diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c index 90f1ebf45..112bc5499 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c @@ -24,8 +24,6 @@ #include "packet.h" #include "myproposal.h" -struct ssh *active_state = NULL; /* XXX - needed for linking */ - void kex_tests(void); static int do_debug = 0; diff --git a/session.c b/session.c index b5a382473..4862e5d63 100644 --- a/session.c +++ b/session.c @@ -123,9 +123,6 @@ int do_exec_no_pty(struct ssh *, Session *, const char *); int do_exec(struct ssh *, Session *, const char *); void do_login(struct ssh *, Session *, const char *); void do_child(struct ssh *, Session *, const char *); -#ifdef LOGIN_NEEDS_UTMPX -static void do_pre_login(Session *s); -#endif void do_motd(void); int check_quietlogin(Session *, const char *); @@ -656,35 +653,6 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) return 0; } -#ifdef LOGIN_NEEDS_UTMPX -static void -do_pre_login(Session *s) -{ - struct ssh *ssh = active_state; /* XXX */ - socklen_t fromlen; - struct sockaddr_storage from; - pid_t pid = getpid(); - - /* - * Get IP address of client. If the connection is not a socket, let - * the address be 0.0.0.0. - */ - memset(&from, 0, sizeof(from)); - fromlen = sizeof(from); - if (packet_connection_is_on_socket()) { - if (getpeername(packet_get_connection_in(), - (struct sockaddr *)&from, &fromlen) < 0) { - debug("getpeername: %.100s", strerror(errno)); - cleanup_exit(255); - } - } - - record_utmp_only(pid, s->tty, s->pw->pw_name, - session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns), - (struct sockaddr *)&from, fromlen); -} -#endif - /* * This is called to fork and execute a command. If another command is * to be forced, execute that instead. diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 38b1c548b..88449f672 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -83,8 +83,6 @@ fd_set *read_wait; size_t read_wait_nfdset; int ncon; -struct ssh *active_state = NULL; /* XXX needed for linking */ - /* * Keep a connection structure for each file descriptor. The state * associated with file descriptor n is held in fdcon[n]. diff --git a/ssh-keysign.c b/ssh-keysign.c index 7ea5ad0e9..601f6ca72 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -59,8 +59,6 @@ #include "sshkey.h" #include "ssherr.h" -struct ssh *active_state = NULL; /* XXX needed for linking */ - extern char *__progname; static int diff --git a/sshd.c b/sshd.c index 58d17e546..f6927672e 100644 --- a/sshd.c +++ b/sshd.c @@ -2080,7 +2080,7 @@ main(int ac, char **av) } #ifdef SSH_AUDIT_EVENTS - audit_event(SSH_AUTH_SUCCESS); + audit_event(ssh, SSH_AUTH_SUCCESS); #endif #ifdef GSSAPI @@ -2128,7 +2128,7 @@ main(int ac, char **av) #endif /* USE_PAM */ #ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_CONNECTION_CLOSE)); + PRIVSEP(audit_event(ssh, SSH_CONNECTION_CLOSE)); #endif ssh_packet_close(ssh); @@ -2256,8 +2256,8 @@ cleanup_exit(int i) } #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ - if (!use_privsep || mm_is_monitor()) - audit_event(SSH_CONNECTION_ABANDON); + if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) + audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif _exit(i); } -- cgit v1.2.3 From dfd591618cdf2c96727ac0eb65f89cf54af0d97e Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:20:12 +0000 Subject: upstream: Add support for a PQC KEX/KEM: sntrup4591761x25519-sha512@tinyssh.org using the Streamlined NTRU Prime 4591^761 implementation from SUPERCOP coupled with X25519 as a stop-loss. Not enabled by default. introduce KEM API; a simplified framework for DH-ish KEX methods. from markus@ feedback & ok djm@ OpenBSD-Commit-ID: d687f76cffd3561dd73eb302d17a1c3bf321d1a7 --- Makefile.in | 2 + crypto_api.h | 18 +- kex.c | 7 +- kex.h | 25 +- kexc25519.c | 47 +- kexc25519c.c | 10 +- kexc25519s.c | 8 +- kexkemc.c | 128 ++++++ kexkems.c | 116 +++++ kexsntrup4591761x25519.c | 213 +++++++++ monitor.c | 3 +- sntrup4591761.c | 1068 ++++++++++++++++++++++++++++++++++++++++++++++ sntrup4591761.sh | 47 ++ ssh-keyscan.c | 3 +- ssh_api.c | 4 +- sshconnect2.c | 3 +- sshd.c | 3 +- 17 files changed, 1665 insertions(+), 40 deletions(-) create mode 100644 kexkemc.c create mode 100644 kexkems.c create mode 100644 kexsntrup4591761x25519.c create mode 100644 sntrup4591761.c create mode 100644 sntrup4591761.sh (limited to 'sshd.c') diff --git a/Makefile.in b/Makefile.in index 7b5de6039..2b22e9f47 100644 --- a/Makefile.in +++ b/Makefile.in @@ -100,8 +100,10 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ + sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect2.o mux.o diff --git a/crypto_api.h b/crypto_api.h index 7f45bbd69..eb05251ff 100644 --- a/crypto_api.h +++ b/crypto_api.h @@ -1,4 +1,4 @@ -/* $OpenBSD: crypto_api.h,v 1.4 2017/12/14 21:07:39 naddy Exp $ */ +/* $OpenBSD: crypto_api.h,v 1.5 2019/01/21 10:20:12 djm Exp $ */ /* * Assembled from generated headers and source files by Markus Friedl. @@ -15,10 +15,15 @@ #endif #include +typedef int8_t crypto_int8; +typedef uint8_t crypto_uint8; +typedef int16_t crypto_int16; +typedef uint16_t crypto_uint16; typedef int32_t crypto_int32; typedef uint32_t crypto_uint32; #define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len)) +#define small_random32() arc4random() #define crypto_hash_sha512_BYTES 64U @@ -37,4 +42,15 @@ int crypto_sign_ed25519_open(unsigned char *, unsigned long long *, const unsigned char *, unsigned long long, const unsigned char *); int crypto_sign_ed25519_keypair(unsigned char *, unsigned char *); +#define crypto_kem_sntrup4591761_PUBLICKEYBYTES 1218 +#define crypto_kem_sntrup4591761_SECRETKEYBYTES 1600 +#define crypto_kem_sntrup4591761_CIPHERTEXTBYTES 1047 +#define crypto_kem_sntrup4591761_BYTES 32 + +int crypto_kem_sntrup4591761_enc(unsigned char *cstr, unsigned char *k, + const unsigned char *pk); +int crypto_kem_sntrup4591761_dec(unsigned char *k, + const unsigned char *cstr, const unsigned char *sk); +int crypto_kem_sntrup4591761_keypair(unsigned char *pk, unsigned char *sk); + #endif /* crypto_api_h */ diff --git a/kex.c b/kex.c index d8c71bb3e..0dba2cefa 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.146 2019/01/21 10:07:22 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.147 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -108,6 +108,8 @@ static const struct kexalg kexalgs[] = { #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, + { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0, + SSH_DIGEST_SHA512 }, #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, -1, -1, -1}, }; @@ -653,6 +655,7 @@ kex_free(struct kex *kex) sshbuf_free(kex->my); sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); + sshbuf_free(kex->kem_client_pub); free(kex->session_id); free(kex->failed_choice); free(kex->hostkey_alg); @@ -1089,7 +1092,7 @@ kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void -dump_digest(char *msg, u_char *digest, int len) +dump_digest(const char *msg, const u_char *digest, int len) { fprintf(stderr, "%s\n", msg); sshbuf_dump_data(digest, len, stderr); diff --git a/kex.h b/kex.h index e404d0365..258a64712 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.98 2019/01/21 10:07:22 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.99 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -27,6 +27,7 @@ #define KEX_H #include "mac.h" +#include "crypto_api.h" #ifdef WITH_LEAKMALLOC #include "leakmalloc.h" @@ -62,6 +63,7 @@ #define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" #define KEX_CURVE25519_SHA256 "curve25519-sha256" #define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org" +#define KEX_SNTRUP4591761X25519_SHA512 "sntrup4591761x25519-sha512@tinyssh.org" #define COMP_NONE 0 /* pre-auth compression (COMP_ZLIB) is only supported in the client */ @@ -100,6 +102,7 @@ enum kex_exchange { KEX_DH_GEX_SHA256, KEX_ECDH_SHA2, KEX_C25519_SHA256, + KEX_KEM_SNTRUP4591761X25519_SHA512, KEX_MAX }; @@ -164,8 +167,10 @@ struct kex { u_int min, max, nbits; /* GEX */ EC_KEY *ec_client_key; /* ECDH */ const EC_GROUP *ec_group; /* ECDH */ - u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 */ + u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ + u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */ + struct sshbuf *kem_client_pub; /* KEM */ }; int kex_names_valid(const char *); @@ -203,6 +208,14 @@ int kexecdh_client(struct ssh *); int kexecdh_server(struct ssh *); int kexc25519_client(struct ssh *); int kexc25519_server(struct ssh *); +int kex_kem_client(struct ssh *); +int kex_kem_server(struct ssh *); + +int kex_kem_sntrup4591761x25519_keypair(struct kex *); +int kex_kem_sntrup4591761x25519_enc(struct kex *, const u_char *, size_t, + struct sshbuf **, struct sshbuf **); +int kex_kem_sntrup4591761x25519_dec(struct kex *, const u_char *, size_t, + struct sshbuf **); int kex_dh_keygen(struct kex *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); @@ -224,7 +237,7 @@ int kex_ecdh_hash(int, const EC_GROUP *, int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, - const u_char *, size_t, const u_char *, const u_char *, + const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, u_char *, size_t *); void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) @@ -234,9 +247,13 @@ int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) -void dump_digest(char *, u_char *, int); +void dump_digest(const char *, const u_char *, int); #endif #if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC) diff --git a/kexc25519.c b/kexc25519.c index acddcab37..3911baf14 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.12 2019/01/21 09:49:37 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -60,8 +60,8 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) } int -kexc25519_shared_key(const u_char key[CURVE25519_SIZE], - const u_char pub[CURVE25519_SIZE], struct sshbuf *out) +kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw) { u_char shared_key[CURVE25519_SIZE]; u_char zero[CURVE25519_SIZE]; @@ -77,12 +77,21 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE], #ifdef DEBUG_KEXECDH dump_digest("shared secret", shared_key, CURVE25519_SIZE); #endif - sshbuf_reset(out); - r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); + if (raw) + r = sshbuf_put(out, shared_key, CURVE25519_SIZE); + else + r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); explicit_bzero(shared_key, CURVE25519_SIZE); return r; } +int +kexc25519_shared_key(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out) +{ + return kexc25519_shared_key_ext(key, pub, out, 0); +} + int kex_c25519_hash( int hash_alg, @@ -91,8 +100,8 @@ kex_c25519_hash( const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, - const u_char client_dh_pub[CURVE25519_SIZE], - const u_char server_dh_pub[CURVE25519_SIZE], + const u_char *client_pub, size_t client_pub_len, + const u_char *server_pub, size_t server_pub_len, const u_char *shared_secret, size_t secretlen, u_char *hash, size_t *hashlen) { @@ -103,19 +112,19 @@ kex_c25519_hash( return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) < 0 || - (r = sshbuf_put_stringb(b, server_version)) < 0 || + if ((r = sshbuf_put_stringb(b, client_version)) != 0 || + (r = sshbuf_put_stringb(b, server_version)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) < 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) < 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) < 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) < 0 || - (r = sshbuf_put_string(b, client_dh_pub, CURVE25519_SIZE)) < 0 || - (r = sshbuf_put_string(b, server_dh_pub, CURVE25519_SIZE)) < 0 || - (r = sshbuf_put(b, shared_secret, secretlen)) < 0) { + (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || + (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || + (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || + (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || + (r = sshbuf_put_string(b, client_pub, client_pub_len)) != 0 || + (r = sshbuf_put_string(b, server_pub, server_pub_len)) != 0 || + (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { sshbuf_free(b); return r; } diff --git a/kexc25519c.c b/kexc25519c.c index 1c7f79000..cc6e54cc7 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.12 2019/01/21 10:07:22 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -109,7 +109,7 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) goto out; } if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey, - shared_secret)) < 0) + shared_secret)) != 0) goto out; /* calc and verify H */ @@ -121,10 +121,10 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), server_host_key_blob, sbloblen, - kex->c25519_client_pubkey, - server_pubkey, + kex->c25519_client_pubkey, sizeof(kex->c25519_client_pubkey), + server_pubkey, pklen, sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) < 0) + hash, &hashlen)) != 0) goto out; if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, diff --git a/kexc25519s.c b/kexc25519s.c index d7cc70fee..ace4d5c79 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.15 2019/01/21 10:05:09 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.16 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -104,10 +104,10 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, - client_pubkey, - server_pubkey, + client_pubkey, pklen, + server_pubkey, sizeof(server_pubkey), sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) < 0) + hash, &hashlen)) != 0) goto out; /* sign H */ diff --git a/kexkemc.c b/kexkemc.c new file mode 100644 index 000000000..47f15c30c --- /dev/null +++ b/kexkemc.c @@ -0,0 +1,128 @@ +/* $OpenBSD: kexkemc.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* + * Copyright (c) 2019 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include "sshkey.h" +#include "kex.h" +#include "log.h" +#include "packet.h" +#include "ssh2.h" +#include "sshbuf.h" +#include "digest.h" +#include "ssherr.h" + +static int +input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh); + +int +kex_kem_client(struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + int r; + + if ((r = kex_kem_sntrup4591761x25519_keypair(kex)) != 0) + return r; + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || + (r = sshpkt_put_stringb(ssh, kex->kem_client_pub)) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; + debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_kem_reply); + return 0; +} + +static int +input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + struct sshkey *server_host_key = NULL; + struct sshbuf *shared_secret = NULL; + u_char *server_pubkey = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, pklen, sbloblen, hashlen; + int r; + + /* hostkey */ + if ((r = sshpkt_get_string(ssh, &server_host_key_blob, + &sbloblen)) != 0 || + (r = sshkey_from_blob(server_host_key_blob, sbloblen, + &server_host_key)) != 0) + goto out; + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) + goto out; + + /* Q_S, server public key */ + /* signed H */ + if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 || + (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + + /* compute shared secret */ + if ((r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, + &shared_secret)) != 0) + goto out; + + /* calc and verify H */ + hashlen = sizeof(hash); + if ((r = kex_c25519_hash( + kex->hash_alg, + kex->client_version, + kex->server_version, + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + server_host_key_blob, sbloblen, + sshbuf_ptr(kex->kem_client_pub), sshbuf_len(kex->kem_client_pub), + server_pubkey, pklen, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, &hashlen)) != 0) + goto out; + + if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, + kex->hostkey_alg, ssh->compat)) != 0) + goto out; + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); +out: + explicit_bzero(hash, sizeof(hash)); + explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); + explicit_bzero(kex->sntrup4591761_client_key, + sizeof(kex->sntrup4591761_client_key)); + free(server_host_key_blob); + free(server_pubkey); + free(signature); + sshkey_free(server_host_key); + sshbuf_free(shared_secret); + sshbuf_free(kex->kem_client_pub); + kex->kem_client_pub = NULL; + return r; +} diff --git a/kexkems.c b/kexkems.c new file mode 100644 index 000000000..43cf82018 --- /dev/null +++ b/kexkems.c @@ -0,0 +1,116 @@ +/* $OpenBSD: kexkems.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* + * Copyright (c) 2019 Markus Friedl. All rights reserved. + * + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "sshkey.h" +#include "digest.h" +#include "kex.h" +#include "log.h" +#include "packet.h" +#include "ssh2.h" +#include "sshbuf.h" +#include "ssherr.h" + +static int input_kex_kem_init(int, u_int32_t, struct ssh *); + +int +kex_kem_server(struct ssh *ssh) +{ + debug("expecting SSH2_MSG_KEX_ECDH_INIT"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_kem_init); + return 0; +} + +static int +input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) +{ + struct kex *kex = ssh->kex; + struct sshkey *server_host_private, *server_host_public; + struct sshbuf *shared_secret = NULL; + struct sshbuf *server_pubkey = NULL; + u_char *server_host_key_blob = NULL, *signature = NULL; + u_char *client_pubkey = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t slen, pklen, sbloblen, hashlen; + int r; + + if ((r = kex_load_hostkey(ssh, &server_host_private, + &server_host_public)) != 0) + goto out; + + if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + goto out; + + /* compute shared secret */ + if ((r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, + &server_pubkey, &shared_secret)) != 0) + goto out; + + /* calc H */ + if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, + &sbloblen)) != 0) + goto out; + hashlen = sizeof(hash); + if ((r = kex_c25519_hash( + kex->hash_alg, + kex->client_version, + kex->server_version, + sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), + sshbuf_ptr(kex->my), sshbuf_len(kex->my), + server_host_key_blob, sbloblen, + client_pubkey, pklen, + sshbuf_ptr(server_pubkey), sshbuf_len(server_pubkey), + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, &hashlen)) != 0) + goto out; + + /* sign H */ + if ((r = kex->sign(ssh, server_host_private, server_host_public, + &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0) + goto out; + + /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || + (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || + (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || + (r = sshpkt_put_string(ssh, signature, slen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + goto out; + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); +out: + explicit_bzero(hash, sizeof(hash)); + free(server_host_key_blob); + free(signature); + free(client_pubkey); + sshbuf_free(shared_secret); + sshbuf_free(server_pubkey); + return r; +} diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c new file mode 100644 index 000000000..ffe05f420 --- /dev/null +++ b/kexsntrup4591761x25519.c @@ -0,0 +1,213 @@ +/* $OpenBSD: kexsntrup4591761x25519.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* + * Copyright (c) 2019 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include "sshkey.h" +#include "kex.h" +#include "sshbuf.h" +#include "digest.h" +#include "ssherr.h" + +int +kex_kem_sntrup4591761x25519_keypair(struct kex *kex) +{ + struct sshbuf *buf = NULL; + u_char *cp = NULL; + size_t need; + int r; + + if ((buf = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; + if ((r = sshbuf_reserve(buf, need, &cp)) != 0) + goto out; + crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key); +#ifdef DEBUG_KEXECDH + dump_digest("client public key sntrup4591761:", cp, + crypto_kem_sntrup4591761_PUBLICKEYBYTES); +#endif + cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES; + kexc25519_keygen(kex->c25519_client_key, cp); +#ifdef DEBUG_KEXECDH + dump_digest("client public key c25519:", cp, CURVE25519_SIZE); +#endif + kex->kem_client_pub = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} + +int +kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + struct sshbuf *server_blob = NULL; + struct sshbuf *buf = NULL; + u_char *kem_key, *ciphertext, *server_pub; + u_char server_key[CURVE25519_SIZE]; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t need; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + /* pkblob contains both KEM and ECDH client pubkeys */ + need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; + if (pklen != need) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +#ifdef DEBUG_KEXECDH + dump_digest("client public key sntrup4591761:", pkblob, + crypto_kem_sntrup4591761_PUBLICKEYBYTES); + dump_digest("client public key 25519:", + pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, CURVE25519_SIZE); +#endif + /* allocate buffer for concatenation of KEM key and ECDH shared key */ + /* the buffer will be hashed and the result is the shared secret */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES, + &kem_key)) != 0) + goto out; + /* allocate space for encrypted KEM key and ECDH pub key */ + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; + if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0) + goto out; + /* generate and encrypt KEM key with client key */ + crypto_kem_sntrup4591761_enc(ciphertext, kem_key, pkblob); + /* generate ECDH key pair, store server pubkey after ciphertext */ + server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; + kexc25519_keygen(server_key, server_pub); + /* append ECDH shared key */ + if ((r = kexc25519_shared_key_ext(server_key, + pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, buf, 1)) < 0) + goto out; + if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); + dump_digest("server cipher text:", ciphertext, + crypto_kem_sntrup4591761_CIPHERTEXTBYTES); + dump_digest("server kem key:", kem_key, sizeof(kem_key)); + dump_digest("concatenation of KEM key and ECDH shared key:", + sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + /* string-encoded hash is resulting shared secret */ + sshbuf_reset(buf); + if ((r = sshbuf_put_string(buf, hash, + ssh_digest_bytes(kex->hash_alg))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + *server_blobp = server_blob; + *shared_secretp = buf; + server_blob = NULL; + buf = NULL; + out: + explicit_bzero(hash, sizeof(hash)); + explicit_bzero(server_key, sizeof(server_key)); + sshbuf_free(server_blob); + sshbuf_free(buf); + return r; +} + +int +kex_kem_sntrup4591761x25519_dec(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **shared_secretp) +{ + struct sshbuf *buf = NULL; + u_char *kem_key = NULL; + const u_char *ciphertext, *server_pub; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t need; + int r, decoded; + + *shared_secretp = NULL; + + need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; + if (pklen != need) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } + ciphertext = pkblob; + server_pub = pkblob + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; +#ifdef DEBUG_KEXECDH + dump_digest("server cipher text:", ciphertext, + crypto_kem_sntrup4591761_CIPHERTEXTBYTES); + dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE); +#endif + /* hash concatenation of KEM key and ECDH shared key */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES, + &kem_key)) != 0) + goto out; + decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext, + kex->sntrup4591761_client_key); + if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub, + buf, 1)) < 0) + goto out; + if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("client kem key:", kem_key, sizeof(kem_key)); + dump_digest("concatenation of KEM key and ECDH shared key:", + sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + sshbuf_reset(buf); + if ((r = sshbuf_put_string(buf, hash, + ssh_digest_bytes(kex->hash_alg))) != 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + if (decoded != 0) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } + *shared_secretp = buf; + buf = NULL; + out: + explicit_bzero(hash, sizeof(hash)); + sshbuf_free(buf); + return r; +} diff --git a/monitor.c b/monitor.c index a9546dad2..b10fdebf2 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.192 2019/01/19 21:43:56 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.193 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1689,6 +1689,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) # endif #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; diff --git a/sntrup4591761.c b/sntrup4591761.c new file mode 100644 index 000000000..d3ff549ae --- /dev/null +++ b/sntrup4591761.c @@ -0,0 +1,1068 @@ +#include +#include "crypto_api.h" + +/* from supercop-20181216/crypto_sort/int32/portable3/int32_minmax.inc */ +#define int32_MINMAX(a,b) \ +do { \ + int32 ab = b ^ a; \ + int32 c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +/* from supercop-20181216/crypto_sort/int32/portable3/sort.c */ +#define int32 crypto_int32 + + +static void crypto_sort_int32(void *array,long long n) +{ + long long top,p,q,r,i; + int32 *x = array; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32 a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/small.h */ +#ifndef small_h +#define small_h + + +typedef crypto_int8 small; + +static void small_encode(unsigned char *,const small *); + +static void small_decode(small *,const unsigned char *); + + +static void small_random(small *); + +static void small_random_weightw(small *); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/mod3.h */ +#ifndef mod3_h +#define mod3_h + + +/* -1 if x is nonzero, 0 otherwise */ +static inline int mod3_nonzero_mask(small x) +{ + return -x*x; +} + +/* input between -100000 and 100000 */ +/* output between -1 and 1 */ +static inline small mod3_freeze(crypto_int32 a) +{ + a -= 3 * ((10923 * a) >> 15); + a -= 3 * ((89478485 * a + 134217728) >> 28); + return a; +} + +static inline small mod3_minusproduct(small a,small b,small c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return mod3_freeze(A - B * C); +} + +static inline small mod3_plusproduct(small a,small b,small c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return mod3_freeze(A + B * C); +} + +static inline small mod3_product(small a,small b) +{ + return a * b; +} + +static inline small mod3_sum(small a,small b) +{ + crypto_int32 A = a; + crypto_int32 B = b; + return mod3_freeze(A + B); +} + +static inline small mod3_reciprocal(small a1) +{ + return a1; +} + +static inline small mod3_quotient(small num,small den) +{ + return mod3_product(num,mod3_reciprocal(den)); +} + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/modq.h */ +#ifndef modq_h +#define modq_h + + +typedef crypto_int16 modq; + +/* -1 if x is nonzero, 0 otherwise */ +static inline int modq_nonzero_mask(modq x) +{ + crypto_int32 r = (crypto_uint16) x; + r = -r; + r >>= 30; + return r; +} + +/* input between -9000000 and 9000000 */ +/* output between -2295 and 2295 */ +static inline modq modq_freeze(crypto_int32 a) +{ + a -= 4591 * ((228 * a) >> 20); + a -= 4591 * ((58470 * a + 134217728) >> 28); + return a; +} + +static inline modq modq_minusproduct(modq a,modq b,modq c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return modq_freeze(A - B * C); +} + +static inline modq modq_plusproduct(modq a,modq b,modq c) +{ + crypto_int32 A = a; + crypto_int32 B = b; + crypto_int32 C = c; + return modq_freeze(A + B * C); +} + +static inline modq modq_product(modq a,modq b) +{ + crypto_int32 A = a; + crypto_int32 B = b; + return modq_freeze(A * B); +} + +static inline modq modq_square(modq a) +{ + crypto_int32 A = a; + return modq_freeze(A * A); +} + +static inline modq modq_sum(modq a,modq b) +{ + crypto_int32 A = a; + crypto_int32 B = b; + return modq_freeze(A + B); +} + +static inline modq modq_reciprocal(modq a1) +{ + modq a2 = modq_square(a1); + modq a3 = modq_product(a2,a1); + modq a4 = modq_square(a2); + modq a8 = modq_square(a4); + modq a16 = modq_square(a8); + modq a32 = modq_square(a16); + modq a35 = modq_product(a32,a3); + modq a70 = modq_square(a35); + modq a140 = modq_square(a70); + modq a143 = modq_product(a140,a3); + modq a286 = modq_square(a143); + modq a572 = modq_square(a286); + modq a1144 = modq_square(a572); + modq a1147 = modq_product(a1144,a3); + modq a2294 = modq_square(a1147); + modq a4588 = modq_square(a2294); + modq a4589 = modq_product(a4588,a1); + return a4589; +} + +static inline modq modq_quotient(modq num,modq den) +{ + return modq_product(num,modq_reciprocal(den)); +} + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/params.h */ +#ifndef params_h +#define params_h + +#define q 4591 +/* XXX: also built into modq in various ways */ + +#define qshift 2295 +#define p 761 +#define w 286 + +#define rq_encode_len 1218 +#define small_encode_len 191 + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/r3.h */ +#ifndef r3_h +#define r3_h + + +static void r3_mult(small *,const small *,const small *); + +extern int r3_recip(small *,const small *); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq.h */ +#ifndef rq_h +#define rq_h + + +static void rq_encode(unsigned char *,const modq *); + +static void rq_decode(modq *,const unsigned char *); + +static void rq_encoderounded(unsigned char *,const modq *); + +static void rq_decoderounded(modq *,const unsigned char *); + +static void rq_round3(modq *,const modq *); + +static void rq_mult(modq *,const modq *,const small *); + +int rq_recip3(modq *,const small *); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/swap.h */ +#ifndef swap_h +#define swap_h + +static void swap(void *,void *,int,int); + +#endif + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/dec.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + +#ifdef KAT +#endif + + +int crypto_kem_sntrup4591761_dec( + unsigned char *k, + const unsigned char *cstr, + const unsigned char *sk +) +{ + small f[p]; + modq h[p]; + small grecip[p]; + modq c[p]; + modq t[p]; + small t3[p]; + small r[p]; + modq hr[p]; + unsigned char rstr[small_encode_len]; + unsigned char hash[64]; + int i; + int result = 0; + int weight; + + small_decode(f,sk); + small_decode(grecip,sk + small_encode_len); + rq_decode(h,sk + 2 * small_encode_len); + + rq_decoderounded(c,cstr + 32); + + rq_mult(t,c,f); + for (i = 0;i < p;++i) t3[i] = mod3_freeze(modq_freeze(3*t[i])); + + r3_mult(r,t3,grecip); + +#ifdef KAT + { + int j; + printf("decrypt r:"); + for (j = 0;j < p;++j) + if (r[j] == 1) printf(" +%d",j); + else if (r[j] == -1) printf(" -%d",j); + printf("\n"); + } +#endif + + weight = 0; + for (i = 0;i < p;++i) weight += (1 & r[i]); + weight -= w; + result |= modq_nonzero_mask(weight); /* XXX: puts limit on p */ + + rq_mult(hr,h,r); + rq_round3(hr,hr); + for (i = 0;i < p;++i) result |= modq_nonzero_mask(hr[i] - c[i]); + + small_encode(rstr,r); + crypto_hash_sha512(hash,rstr,sizeof rstr); + result |= crypto_verify_32(hash,cstr); + + for (i = 0;i < 32;++i) k[i] = (hash[32 + i] & ~result); + return result; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/enc.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + +#ifdef KAT +#endif + + +int crypto_kem_sntrup4591761_enc( + unsigned char *cstr, + unsigned char *k, + const unsigned char *pk +) +{ + small r[p]; + modq h[p]; + modq c[p]; + unsigned char rstr[small_encode_len]; + unsigned char hash[64]; + + small_random_weightw(r); + +#ifdef KAT + { + int i; + printf("encrypt r:"); + for (i = 0;i < p;++i) + if (r[i] == 1) printf(" +%d",i); + else if (r[i] == -1) printf(" -%d",i); + printf("\n"); + } +#endif + + small_encode(rstr,r); + crypto_hash_sha512(hash,rstr,sizeof rstr); + + rq_decode(h,pk); + rq_mult(c,h,r); + rq_round3(c,c); + + memcpy(k,hash + 32,32); + memcpy(cstr,hash,32); + rq_encoderounded(cstr + 32,c); + + return 0; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/keypair.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +#if crypto_kem_sntrup4591761_PUBLICKEYBYTES != rq_encode_len +#error "crypto_kem_sntrup4591761_PUBLICKEYBYTES must match rq_encode_len" +#endif +#if crypto_kem_sntrup4591761_SECRETKEYBYTES != rq_encode_len + 2 * small_encode_len +#error "crypto_kem_sntrup4591761_SECRETKEYBYTES must match rq_encode_len + 2 * small_encode_len" +#endif + +int crypto_kem_sntrup4591761_keypair(unsigned char *pk,unsigned char *sk) +{ + small g[p]; + small grecip[p]; + small f[p]; + modq f3recip[p]; + modq h[p]; + + do + small_random(g); + while (r3_recip(grecip,g) != 0); + + small_random_weightw(f); + rq_recip3(f3recip,f); + + rq_mult(h,f3recip,g); + + rq_encode(pk,h); + small_encode(sk,f); + small_encode(sk + small_encode_len,grecip); + memcpy(sk + 2 * small_encode_len,pk,rq_encode_len); + + return 0; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/r3_mult.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void r3_mult(small *h,const small *f,const small *g) +{ + small fg[p + p - 1]; + small result; + int i, j; + + for (i = 0;i < p;++i) { + result = 0; + for (j = 0;j <= i;++j) + result = mod3_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + for (i = p;i < p + p - 1;++i) { + result = 0; + for (j = i - p + 1;j < p;++j) + result = mod3_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + + for (i = p + p - 2;i >= p;--i) { + fg[i - p] = mod3_sum(fg[i - p],fg[i]); + fg[i - p + 1] = mod3_sum(fg[i - p + 1],fg[i]); + } + + for (i = 0;i < p;++i) + h[i] = fg[i]; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/r3_recip.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +/* caller must ensure that x-y does not overflow */ +static int smaller_mask_r3_recip(int x,int y) +{ + return (x - y) >> 31; +} + +static void vectormod3_product(small *z,int len,const small *x,const small c) +{ + int i; + for (i = 0;i < len;++i) z[i] = mod3_product(x[i],c); +} + +static void vectormod3_minusproduct(small *z,int len,const small *x,const small *y,const small c) +{ + int i; + for (i = 0;i < len;++i) z[i] = mod3_minusproduct(x[i],y[i],c); +} + +static void vectormod3_shift(small *z,int len) +{ + int i; + for (i = len - 1;i > 0;--i) z[i] = z[i - 1]; + z[0] = 0; +} + +/* +r = s^(-1) mod m, returning 0, if s is invertible mod m +or returning -1 if s is not invertible mod m +r,s are polys of degree

= loops) break; + + c = mod3_quotient(g[p],f[p]); + + vectormod3_minusproduct(g,p + 1,g,f,c); + vectormod3_shift(g,p + 1); + +#ifdef SIMPLER + vectormod3_minusproduct(v,loops + 1,v,u,c); + vectormod3_shift(v,loops + 1); +#else + if (loop < p) { + vectormod3_minusproduct(v,loop + 1,v,u,c); + vectormod3_shift(v,loop + 2); + } else { + vectormod3_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c); + vectormod3_shift(v + loop - p,p + 2); + } +#endif + + e -= 1; + + ++loop; + + swapmask = smaller_mask_r3_recip(e,d) & mod3_nonzero_mask(g[p]); + swap(&e,&d,sizeof e,swapmask); + swap(f,g,(p + 1) * sizeof(small),swapmask); + +#ifdef SIMPLER + swap(u,v,(loops + 1) * sizeof(small),swapmask); +#else + if (loop < p) { + swap(u,v,(loop + 1) * sizeof(small),swapmask); + } else { + swap(u + loop - p,v + loop - p,(p + 1) * sizeof(small),swapmask); + } +#endif + } + + c = mod3_reciprocal(f[p]); + vectormod3_product(r,p,u + p,c); + return smaller_mask_r3_recip(0,d); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/randomsmall.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void small_random(small *g) +{ + int i; + + for (i = 0;i < p;++i) { + crypto_uint32 r = small_random32(); + g[i] = (small) (((1073741823 & r) * 3) >> 30) - 1; + } +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/randomweightw.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void small_random_weightw(small *f) +{ + crypto_int32 r[p]; + int i; + + for (i = 0;i < p;++i) r[i] = small_random32(); + for (i = 0;i < w;++i) r[i] &= -2; + for (i = w;i < p;++i) r[i] = (r[i] & -3) | 1; + crypto_sort_int32(r,p); + for (i = 0;i < p;++i) f[i] = ((small) (r[i] & 3)) - 1; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_encode(unsigned char *c,const modq *f) +{ + crypto_int32 f0, f1, f2, f3, f4; + int i; + + for (i = 0;i < p/5;++i) { + f0 = *f++ + qshift; + f1 = *f++ + qshift; + f2 = *f++ + qshift; + f3 = *f++ + qshift; + f4 = *f++ + qshift; + /* now want f0 + 6144*f1 + ... as a 64-bit integer */ + f1 *= 3; + f2 *= 9; + f3 *= 27; + f4 *= 81; + /* now want f0 + f1<<11 + f2<<22 + f3<<33 + f4<<44 */ + f0 += f1 << 11; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + f0 += f2 << 6; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + f0 += f3 << 1; + *c++ = f0; f0 >>= 8; + f0 += f4 << 4; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; + } + /* XXX: using p mod 5 = 1 */ + f0 = *f++ + qshift; + *c++ = f0; f0 >>= 8; + *c++ = f0; +} + +static void rq_decode(modq *f,const unsigned char *c) +{ + crypto_uint32 c0, c1, c2, c3, c4, c5, c6, c7; + crypto_uint32 f0, f1, f2, f3, f4; + int i; + + for (i = 0;i < p/5;++i) { + c0 = *c++; + c1 = *c++; + c2 = *c++; + c3 = *c++; + c4 = *c++; + c5 = *c++; + c6 = *c++; + c7 = *c++; + + /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 + f4*6144^4 */ + /* = c0 + c1*256 + ... + c6*256^6 + c7*256^7 */ + /* with each f between 0 and 4590 */ + + c6 += c7 << 8; + /* c6 <= 23241 = floor(4591*6144^4/2^48) */ + /* f4 = (16/81)c6 + (1/1296)(c5+[0,1]) - [0,0.75] */ + /* claim: 2^19 f4 < x < 2^19(f4+1) */ + /* where x = 103564 c6 + 405(c5+1) */ + /* proof: x - 2^19 f4 = (76/81)c6 + (37/81)c5 + 405 - (32768/81)[0,1] + 2^19[0,0.75] */ + /* at least 405 - 32768/81 > 0 */ + /* at most (76/81)23241 + (37/81)255 + 405 + 2^19 0.75 < 2^19 */ + f4 = (103564*c6 + 405*(c5+1)) >> 19; + + c5 += c6 << 8; + c5 -= (f4 * 81) << 4; + c4 += c5 << 8; + + /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 */ + /* = c0 + c1*256 + c2*256^2 + c3*256^3 + c4*256^4 */ + /* c4 <= 247914 = floor(4591*6144^3/2^32) */ + /* f3 = (1/54)(c4+[0,1]) - [0,0.75] */ + /* claim: 2^19 f3 < x < 2^19(f3+1) */ + /* where x = 9709(c4+2) */ + /* proof: x - 2^19 f3 = 19418 - (1/27)c4 - (262144/27)[0,1] + 2^19[0,0.75] */ + /* at least 19418 - 247914/27 - 262144/27 > 0 */ + /* at most 19418 + 2^19 0.75 < 2^19 */ + f3 = (9709*(c4+2)) >> 19; + + c4 -= (f3 * 27) << 1; + c3 += c4 << 8; + /* f0 + f1*6144 + f2*6144^2 */ + /* = c0 + c1*256 + c2*256^2 + c3*256^3 */ + /* c3 <= 10329 = floor(4591*6144^2/2^24) */ + /* f2 = (4/9)c3 + (1/576)c2 + (1/147456)c1 + (1/37748736)c0 - [0,0.75] */ + /* claim: 2^19 f2 < x < 2^19(f2+1) */ + /* where x = 233017 c3 + 910(c2+2) */ + /* proof: x - 2^19 f2 = 1820 + (1/9)c3 - (2/9)c2 - (32/9)c1 - (1/72)c0 + 2^19[0,0.75] */ + /* at least 1820 - (2/9)255 - (32/9)255 - (1/72)255 > 0 */ + /* at most 1820 + (1/9)10329 + 2^19 0.75 < 2^19 */ + f2 = (233017*c3 + 910*(c2+2)) >> 19; + + c2 += c3 << 8; + c2 -= (f2 * 9) << 6; + c1 += c2 << 8; + /* f0 + f1*6144 */ + /* = c0 + c1*256 */ + /* c1 <= 110184 = floor(4591*6144/2^8) */ + /* f1 = (1/24)c1 + (1/6144)c0 - (1/6144)f0 */ + /* claim: 2^19 f1 < x < 2^19(f1+1) */ + /* where x = 21845(c1+2) + 85 c0 */ + /* proof: x - 2^19 f1 = 43690 - (1/3)c1 - (1/3)c0 + 2^19 [0,0.75] */ + /* at least 43690 - (1/3)110184 - (1/3)255 > 0 */ + /* at most 43690 + 2^19 0.75 < 2^19 */ + f1 = (21845*(c1+2) + 85*c0) >> 19; + + c1 -= (f1 * 3) << 3; + c0 += c1 << 8; + f0 = c0; + + *f++ = modq_freeze(f0 + q - qshift); + *f++ = modq_freeze(f1 + q - qshift); + *f++ = modq_freeze(f2 + q - qshift); + *f++ = modq_freeze(f3 + q - qshift); + *f++ = modq_freeze(f4 + q - qshift); + } + + c0 = *c++; + c1 = *c++; + c0 += c1 << 8; + *f++ = modq_freeze(c0 + q - qshift); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_mult.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_mult(modq *h,const modq *f,const small *g) +{ + modq fg[p + p - 1]; + modq result; + int i, j; + + for (i = 0;i < p;++i) { + result = 0; + for (j = 0;j <= i;++j) + result = modq_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + for (i = p;i < p + p - 1;++i) { + result = 0; + for (j = i - p + 1;j < p;++j) + result = modq_plusproduct(result,f[j],g[i - j]); + fg[i] = result; + } + + for (i = p + p - 2;i >= p;--i) { + fg[i - p] = modq_sum(fg[i - p],fg[i]); + fg[i - p + 1] = modq_sum(fg[i - p + 1],fg[i]); + } + + for (i = 0;i < p;++i) + h[i] = fg[i]; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_recip3.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +/* caller must ensure that x-y does not overflow */ +static int smaller_mask_rq_recip3(int x,int y) +{ + return (x - y) >> 31; +} + +static void vectormodq_product(modq *z,int len,const modq *x,const modq c) +{ + int i; + for (i = 0;i < len;++i) z[i] = modq_product(x[i],c); +} + +static void vectormodq_minusproduct(modq *z,int len,const modq *x,const modq *y,const modq c) +{ + int i; + for (i = 0;i < len;++i) z[i] = modq_minusproduct(x[i],y[i],c); +} + +static void vectormodq_shift(modq *z,int len) +{ + int i; + for (i = len - 1;i > 0;--i) z[i] = z[i - 1]; + z[0] = 0; +} + +/* +r = (3s)^(-1) mod m, returning 0, if s is invertible mod m +or returning -1 if s is not invertible mod m +r,s are polys of degree

= loops) break; + + c = modq_quotient(g[p],f[p]); + + vectormodq_minusproduct(g,p + 1,g,f,c); + vectormodq_shift(g,p + 1); + +#ifdef SIMPLER + vectormodq_minusproduct(v,loops + 1,v,u,c); + vectormodq_shift(v,loops + 1); +#else + if (loop < p) { + vectormodq_minusproduct(v,loop + 1,v,u,c); + vectormodq_shift(v,loop + 2); + } else { + vectormodq_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c); + vectormodq_shift(v + loop - p,p + 2); + } +#endif + + e -= 1; + + ++loop; + + swapmask = smaller_mask_rq_recip3(e,d) & modq_nonzero_mask(g[p]); + swap(&e,&d,sizeof e,swapmask); + swap(f,g,(p + 1) * sizeof(modq),swapmask); + +#ifdef SIMPLER + swap(u,v,(loops + 1) * sizeof(modq),swapmask); +#else + if (loop < p) { + swap(u,v,(loop + 1) * sizeof(modq),swapmask); + } else { + swap(u + loop - p,v + loop - p,(p + 1) * sizeof(modq),swapmask); + } +#endif + } + + c = modq_reciprocal(f[p]); + vectormodq_product(r,p,u + p,c); + return smaller_mask_rq_recip3(0,d); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_round3.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_round3(modq *h,const modq *f) +{ + int i; + + for (i = 0;i < p;++i) + h[i] = ((21846 * (f[i] + 2295) + 32768) >> 16) * 3 - 2295; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/rq_rounded.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void rq_encoderounded(unsigned char *c,const modq *f) +{ + crypto_int32 f0, f1, f2; + int i; + + for (i = 0;i < p/3;++i) { + f0 = *f++ + qshift; + f1 = *f++ + qshift; + f2 = *f++ + qshift; + f0 = (21846 * f0) >> 16; + f1 = (21846 * f1) >> 16; + f2 = (21846 * f2) >> 16; + /* now want f0 + f1*1536 + f2*1536^2 as a 32-bit integer */ + f2 *= 3; + f1 += f2 << 9; + f1 *= 3; + f0 += f1 << 9; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; + } + /* XXX: using p mod 3 = 2 */ + f0 = *f++ + qshift; + f1 = *f++ + qshift; + f0 = (21846 * f0) >> 16; + f1 = (21846 * f1) >> 16; + f1 *= 3; + f0 += f1 << 9; + *c++ = f0; f0 >>= 8; + *c++ = f0; f0 >>= 8; + *c++ = f0; +} + +static void rq_decoderounded(modq *f,const unsigned char *c) +{ + crypto_uint32 c0, c1, c2, c3; + crypto_uint32 f0, f1, f2; + int i; + + for (i = 0;i < p/3;++i) { + c0 = *c++; + c1 = *c++; + c2 = *c++; + c3 = *c++; + + /* f0 + f1*1536 + f2*1536^2 */ + /* = c0 + c1*256 + c2*256^2 + c3*256^3 */ + /* with each f between 0 and 1530 */ + + /* f2 = (64/9)c3 + (1/36)c2 + (1/9216)c1 + (1/2359296)c0 - [0,0.99675] */ + /* claim: 2^21 f2 < x < 2^21(f2+1) */ + /* where x = 14913081*c3 + 58254*c2 + 228*(c1+2) */ + /* proof: x - 2^21 f2 = 456 - (8/9)c0 + (4/9)c1 - (2/9)c2 + (1/9)c3 + 2^21 [0,0.99675] */ + /* at least 456 - (8/9)255 - (2/9)255 > 0 */ + /* at most 456 + (4/9)255 + (1/9)255 + 2^21 0.99675 < 2^21 */ + f2 = (14913081*c3 + 58254*c2 + 228*(c1+2)) >> 21; + + c2 += c3 << 8; + c2 -= (f2 * 9) << 2; + /* f0 + f1*1536 */ + /* = c0 + c1*256 + c2*256^2 */ + /* c2 <= 35 = floor((1530+1530*1536)/256^2) */ + /* f1 = (128/3)c2 + (1/6)c1 + (1/1536)c0 - (1/1536)f0 */ + /* claim: 2^21 f1 < x < 2^21(f1+1) */ + /* where x = 89478485*c2 + 349525*c1 + 1365*(c0+1) */ + /* proof: x - 2^21 f1 = 1365 - (1/3)c2 - (1/3)c1 - (1/3)c0 + (4096/3)f0 */ + /* at least 1365 - (1/3)35 - (1/3)255 - (1/3)255 > 0 */ + /* at most 1365 + (4096/3)1530 < 2^21 */ + f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21; + + c1 += c2 << 8; + c1 -= (f1 * 3) << 1; + + c0 += c1 << 8; + f0 = c0; + + *f++ = modq_freeze(f0 * 3 + q - qshift); + *f++ = modq_freeze(f1 * 3 + q - qshift); + *f++ = modq_freeze(f2 * 3 + q - qshift); + } + + c0 = *c++; + c1 = *c++; + c2 = *c++; + + f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21; + + c1 += c2 << 8; + c1 -= (f1 * 3) << 1; + + c0 += c1 << 8; + f0 = c0; + + *f++ = modq_freeze(f0 * 3 + q - qshift); + *f++ = modq_freeze(f1 * 3 + q - qshift); +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/small.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +/* XXX: these functions rely on p mod 4 = 1 */ + +/* all coefficients in -1, 0, 1 */ +static void small_encode(unsigned char *c,const small *f) +{ + small c0; + int i; + + for (i = 0;i < p/4;++i) { + c0 = *f++ + 1; + c0 += (*f++ + 1) << 2; + c0 += (*f++ + 1) << 4; + c0 += (*f++ + 1) << 6; + *c++ = c0; + } + c0 = *f++ + 1; + *c++ = c0; +} + +static void small_decode(small *f,const unsigned char *c) +{ + unsigned char c0; + int i; + + for (i = 0;i < p/4;++i) { + c0 = *c++; + *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2; + *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2; + *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2; + *f++ = ((small) (c0 & 3)) - 1; + } + c0 = *c++; + *f++ = ((small) (c0 & 3)) - 1; +} + +/* from supercop-20181216/crypto_kem/sntrup4591761/ref/swap.c */ +/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */ + + +static void swap(void *x,void *y,int bytes,int mask) +{ + int i; + char xi, yi, c, t; + + c = mask; + + for (i = 0;i < bytes;++i) { + xi = i[(char *) x]; + yi = i[(char *) y]; + t = c & (xi ^ yi); + xi ^= t; + yi ^= t; + i[(char *) x] = xi; + i[(char *) y] = yi; + } +} + diff --git a/sntrup4591761.sh b/sntrup4591761.sh new file mode 100644 index 000000000..5540ca4d9 --- /dev/null +++ b/sntrup4591761.sh @@ -0,0 +1,47 @@ +#!/bin/sh +FILES=" + supercop-20181216/crypto_sort/int32/portable3/int32_minmax.inc + supercop-20181216/crypto_sort/int32/portable3/sort.c + supercop-20181216/crypto_kem/sntrup4591761/ref/small.h + supercop-20181216/crypto_kem/sntrup4591761/ref/mod3.h + supercop-20181216/crypto_kem/sntrup4591761/ref/modq.h + supercop-20181216/crypto_kem/sntrup4591761/ref/params.h + supercop-20181216/crypto_kem/sntrup4591761/ref/r3.h + supercop-20181216/crypto_kem/sntrup4591761/ref/rq.h + supercop-20181216/crypto_kem/sntrup4591761/ref/swap.h + supercop-20181216/crypto_kem/sntrup4591761/ref/dec.c + supercop-20181216/crypto_kem/sntrup4591761/ref/enc.c + supercop-20181216/crypto_kem/sntrup4591761/ref/keypair.c + supercop-20181216/crypto_kem/sntrup4591761/ref/r3_mult.c + supercop-20181216/crypto_kem/sntrup4591761/ref/r3_recip.c + supercop-20181216/crypto_kem/sntrup4591761/ref/randomsmall.c + supercop-20181216/crypto_kem/sntrup4591761/ref/randomweightw.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_mult.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_recip3.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_round3.c + supercop-20181216/crypto_kem/sntrup4591761/ref/rq_rounded.c + supercop-20181216/crypto_kem/sntrup4591761/ref/small.c + supercop-20181216/crypto_kem/sntrup4591761/ref/swap.c +" +### + +set -e +DIR=/data/git/mfriedl +cd $DIR +echo '#include ' +echo '#include "crypto_api.h"' +echo +for i in $FILES; do + echo "/* from $i */" + b=$(basename $i .c) + grep \ + -v '#include' $i | \ + grep -v "extern crypto_int32 small_random32" | + sed -e "s/crypto_kem_/crypto_kem_sntrup4591761_/g" \ + -e "s/smaller_mask/smaller_mask_${b}/g" \ + -e "s/void crypto_sort/void crypto_sort_int32/" \ + -e "s/^extern void /static void /" \ + -e "s/^void /static void /" + echo +done diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 88449f672..83a768700 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.120 2018/06/06 18:29:18 markus Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.121 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -272,6 +272,7 @@ keygrab_ssh2(con *c) # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* * do the key-exchange until an error occurs or until diff --git a/ssh_api.c b/ssh_api.c index 182c0d7e4..73981aa37 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.10 2019/01/19 21:43:56 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.11 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -111,6 +111,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; ssh->kex->load_host_public_key=&_ssh_host_public_key; ssh->kex->load_host_private_key=&_ssh_host_private_key; ssh->kex->sign=&_ssh_host_key_sign; @@ -128,6 +129,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; diff --git a/sshconnect2.c b/sshconnect2.c index 65d8be667..05657fd73 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.296 2019/01/21 01:05:00 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.297 2019/01/21 10:20:12 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -213,6 +213,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) # endif #endif ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key=&verify_host_key_callback; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); diff --git a/sshd.c b/sshd.c index f6927672e..330b8052d 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.527 2019/01/19 21:43:56 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.528 2019/01/21 10:20:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2219,6 +2219,7 @@ do_ssh2_kex(struct ssh *ssh) # endif #endif kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; -- cgit v1.2.3 From 2f6a9ddbbf6ca8623c53c323ff17fb6d68d66970 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:24:09 +0000 Subject: upstream: use KEM API for vanilla c25519 KEX OpenBSD-Commit-ID: 38d937b85ff770886379dd66a8f32ab0c1c35c1f --- Makefile.in | 2 - kex.h | 7 ++- kexc25519.c | 122 ++++++++++++++++++++++++++++++++++++++++++++---- kexc25519c.c | 145 ---------------------------------------------------------- kexc25519s.c | 136 ------------------------------------------------------ kexkemc.c | 30 ++++++++++-- kexkems.c | 18 ++++++-- monitor.c | 4 +- ssh-keyscan.c | 4 +- ssh_api.c | 6 +-- sshconnect2.c | 4 +- sshd.c | 4 +- 12 files changed, 170 insertions(+), 312 deletions(-) delete mode 100644 kexc25519c.c delete mode 100644 kexc25519s.c (limited to 'sshd.c') diff --git a/Makefile.in b/Makefile.in index 2b22e9f47..89f930367 100644 --- a/Makefile.in +++ b/Makefile.in @@ -98,8 +98,6 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ - kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.h b/kex.h index 258a64712..2eec2e04f 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.99 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.100 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -211,6 +211,11 @@ int kexc25519_server(struct ssh *); int kex_kem_client(struct ssh *); int kex_kem_server(struct ssh *); +int kex_c25519_keypair(struct kex *); +int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, + struct sshbuf **); +int kex_c25519_dec(struct kex *, const u_char *, size_t, struct sshbuf **); + int kex_kem_sntrup4591761x25519_keypair(struct kex *); int kex_kem_sntrup4591761x25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); diff --git a/kexc25519.c b/kexc25519.c index 3911baf14..a06c6e44b 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,6 +1,6 @@ -/* $OpenBSD: kexc25519.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.14 2019/01/21 10:24:09 djm Exp $ */ /* - * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. + * Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2013 Aris Adamantiadis. All rights reserved. * @@ -29,20 +29,16 @@ #include -#include +#include #include +#include -#include -#include - -#include "sshbuf.h" -#include "ssh2.h" #include "sshkey.h" -#include "cipher.h" #include "kex.h" -#include "log.h" +#include "sshbuf.h" #include "digest.h" #include "ssherr.h" +#include "ssh2.h" extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) @@ -142,3 +138,109 @@ kex_c25519_hash( #endif return 0; } + +int +kex_c25519_keypair(struct kex *kex) +{ + struct sshbuf *buf = NULL; + u_char *cp = NULL; + int r; + + if ((buf = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_reserve(buf, CURVE25519_SIZE, &cp)) != 0) + goto out; + kexc25519_keygen(kex->c25519_client_key, cp); +#ifdef DEBUG_KEXECDH + dump_digest("client public key c25519:", cp, CURVE25519_SIZE); +#endif + kex->kem_client_pub = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} + +int +kex_c25519_enc(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + struct sshbuf *server_blob = NULL; + struct sshbuf *buf = NULL; + u_char *server_pub; + u_char server_key[CURVE25519_SIZE]; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + if (pklen != CURVE25519_SIZE) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +#ifdef DEBUG_KEXECDH + dump_digest("client public key 25519:", pkblob, CURVE25519_SIZE); +#endif + /* allocate space for encrypted KEM key and ECDH pub key */ + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0) + goto out; + kexc25519_keygen(server_key, server_pub); + /* allocate shared secret */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = kexc25519_shared_key_ext(server_key, pkblob, buf, 0)) < 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + *server_blobp = server_blob; + *shared_secretp = buf; + server_blob = NULL; + buf = NULL; + out: + explicit_bzero(server_key, sizeof(server_key)); + sshbuf_free(server_blob); + sshbuf_free(buf); + return r; +} + +int +kex_c25519_dec(struct kex *kex, const u_char *pkblob, + size_t pklen, struct sshbuf **shared_secretp) +{ + struct sshbuf *buf = NULL; + int r; + + *shared_secretp = NULL; + + if (pklen != CURVE25519_SIZE) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +#ifdef DEBUG_KEXECDH + dump_digest("server public key c25519:", pkblob, CURVE25519_SIZE); +#endif + /* shared secret */ + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, pkblob, + buf, 0)) < 0) + goto out; +#ifdef DEBUG_KEXECDH + dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); +#endif + *shared_secretp = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} diff --git a/kexc25519c.c b/kexc25519c.c deleted file mode 100644 index cc6e54cc7..000000000 --- a/kexc25519c.c +++ /dev/null @@ -1,145 +0,0 @@ -/* $OpenBSD: kexc25519c.c,v 1.13 2019/01/21 10:20:12 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * Copyright (c) 2013 Aris Adamantiadis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#include - -#include -#include -#include - -#include "sshkey.h" -#include "cipher.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" -#include "sshbuf.h" -#include "digest.h" -#include "ssherr.h" - -static int -input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh); - -int -kexc25519_client(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - int r; - - kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey); -#ifdef DEBUG_KEXECDH - dump_digest("client private key:", kex->c25519_client_key, - sizeof(kex->c25519_client_key)); -#endif - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || - (r = sshpkt_put_string(ssh, kex->c25519_client_pubkey, - sizeof(kex->c25519_client_pubkey))) != 0 || - (r = sshpkt_send(ssh)) != 0) - return r; - - debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply); - return 0; -} - -static int -input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - struct sshkey *server_host_key = NULL; - struct sshbuf *shared_secret = NULL; - u_char *server_pubkey = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, pklen, sbloblen, hashlen; - int r; - - /* hostkey */ - if ((r = sshpkt_get_string(ssh, &server_host_key_blob, - &sbloblen)) != 0 || - (r = sshkey_from_blob(server_host_key_blob, sbloblen, - &server_host_key)) != 0) - goto out; - if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) - goto out; - - /* Q_S, server public key */ - /* signed H */ - if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 || - (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if (pklen != CURVE25519_SIZE) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } - -#ifdef DEBUG_KEXECDH - dump_digest("server public key:", server_pubkey, CURVE25519_SIZE); -#endif - - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey, - shared_secret)) != 0) - goto out; - - /* calc and verify H */ - hashlen = sizeof(hash); - if ((r = kex_c25519_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, - kex->c25519_client_pubkey, sizeof(kex->c25519_client_pubkey), - server_pubkey, pklen, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, - kex->hostkey_alg, ssh->compat)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); -out: - explicit_bzero(hash, sizeof(hash)); - explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); - free(server_host_key_blob); - free(server_pubkey); - free(signature); - sshkey_free(server_host_key); - sshbuf_free(shared_secret); - return r; -} diff --git a/kexc25519s.c b/kexc25519s.c deleted file mode 100644 index ace4d5c79..000000000 --- a/kexc25519s.c +++ /dev/null @@ -1,136 +0,0 @@ -/* $OpenBSD: kexc25519s.c,v 1.16 2019/01/21 10:20:12 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * Copyright (c) 2013 Aris Adamantiadis. All rights reserved. - * - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#include -#include -#include -#include - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" -#include "sshbuf.h" -#include "ssherr.h" - -static int input_kex_c25519_init(int, u_int32_t, struct ssh *); - -int -kexc25519_server(struct ssh *ssh) -{ - debug("expecting SSH2_MSG_KEX_ECDH_INIT"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_c25519_init); - return 0; -} - -static int -input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - struct sshkey *server_host_private, *server_host_public; - struct sshbuf *shared_secret = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char server_key[CURVE25519_SIZE]; - u_char *client_pubkey = NULL; - u_char server_pubkey[CURVE25519_SIZE]; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, pklen, sbloblen, hashlen; - int r; - - /* generate private key */ - kexc25519_keygen(server_key, server_pubkey); -#ifdef DEBUG_KEXECDH - dump_digest("server private key:", server_key, sizeof(server_key)); -#endif - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) - goto out; - if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if (pklen != CURVE25519_SIZE) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } -#ifdef DEBUG_KEXECDH - dump_digest("client public key:", client_pubkey, CURVE25519_SIZE); -#endif - - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kexc25519_shared_key(server_key, client_pubkey, - shared_secret)) < 0) - goto out; - - /* calc H */ - if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, - &sbloblen)) != 0) - goto out; - hashlen = sizeof(hash); - if ((r = kex_c25519_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - client_pubkey, pklen, - server_pubkey, sizeof(server_pubkey), - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) - goto out; - - /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || - (r = sshpkt_put_string(ssh, server_pubkey, sizeof(server_pubkey))) != 0 || - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); -out: - explicit_bzero(hash, sizeof(hash)); - explicit_bzero(server_key, sizeof(server_key)); - free(server_host_key_blob); - free(signature); - free(client_pubkey); - sshbuf_free(shared_secret); - return r; -} diff --git a/kexkemc.c b/kexkemc.c index 47f15c30c..13f36a116 100644 --- a/kexkemc.c +++ b/kexkemc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkemc.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kexkemc.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -47,7 +47,18 @@ kex_kem_client(struct ssh *ssh) struct kex *kex = ssh->kex; int r; - if ((r = kex_kem_sntrup4591761x25519_keypair(kex)) != 0) + switch (kex->kex_type) { + case KEX_C25519_SHA256: + r = kex_c25519_keypair(kex); + break; + case KEX_KEM_SNTRUP4591761X25519_SHA512: + r = kex_kem_sntrup4591761x25519_keypair(kex); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } + if (r != 0) return r; if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || (r = sshpkt_put_stringb(ssh, kex->kem_client_pub)) != 0 || @@ -87,8 +98,19 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) goto out; /* compute shared secret */ - if ((r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, - &shared_secret)) != 0) + switch (kex->kex_type) { + case KEX_C25519_SHA256: + r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); + break; + case KEX_KEM_SNTRUP4591761X25519_SHA512: + r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen, + &shared_secret); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } + if (r !=0 ) goto out; /* calc and verify H */ diff --git a/kexkems.c b/kexkems.c index 43cf82018..89237902b 100644 --- a/kexkems.c +++ b/kexkems.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkems.c,v 1.1 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: kexkems.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -68,8 +68,20 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) goto out; /* compute shared secret */ - if ((r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, - &server_pubkey, &shared_secret)) != 0) + switch (kex->kex_type) { + case KEX_C25519_SHA256: + r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, + &shared_secret); + break; + case KEX_KEM_SNTRUP4591761X25519_SHA512: + r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey, pklen, + &server_pubkey, &shared_secret); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } + if (r !=0 ) goto out; /* calc H */ diff --git a/monitor.c b/monitor.c index b10fdebf2..9f86d5b75 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.193 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.194 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1688,7 +1688,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) kex->kex[KEX_ECDH_SHA2] = kexecdh_server; # endif #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_C25519_SHA256] = kex_kem_server; kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 83a768700..9eebc1445 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.121 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.122 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -271,7 +271,7 @@ keygrab_ssh2(con *c) c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif - c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* diff --git a/ssh_api.c b/ssh_api.c index 73981aa37..fe9fbf5a7 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.11 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.12 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -110,7 +110,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server; + ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server; ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; ssh->kex->load_host_public_key=&_ssh_host_public_key; ssh->kex->load_host_private_key=&_ssh_host_private_key; @@ -128,7 +128,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } diff --git a/sshconnect2.c b/sshconnect2.c index 05657fd73..be19722bb 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.297 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.298 2019/01/21 10:24:09 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -212,7 +212,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; # endif #endif - ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; ssh->kex->verify_host_key=&verify_host_key_callback; diff --git a/sshd.c b/sshd.c index 330b8052d..665b22b1e 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.528 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.529 2019/01/21 10:24:09 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2218,7 +2218,7 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_ECDH_SHA2] = kexecdh_server; # endif #endif - kex->kex[KEX_C25519_SHA256] = kexc25519_server; + kex->kex[KEX_C25519_SHA256] = kex_kem_server; kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; -- cgit v1.2.3 From 9c9c97e14fe190931f341876ad98213e1e1dc19f Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:28:01 +0000 Subject: upstream: use KEM API for vanilla DH KEX from markus@ ok djm@ OpenBSD-Commit-ID: af56466426b08a8be275412ae2743319e3d277c9 --- Makefile.in | 2 + kex.h | 10 ++-- kexdh.c | 140 +++++++++++++++++++++++++++++++++-------------------- kexdhc.c | 151 ---------------------------------------------------------- kexdhs.c | 142 ------------------------------------------------------ kexkemc.c | 16 ++++++- kexkems.c | 10 +++- monitor.c | 12 ++--- ssh-keyscan.c | 12 ++--- ssh_api.c | 22 ++++----- sshconnect2.c | 12 ++--- sshd.c | 12 ++--- 12 files changed, 155 insertions(+), 386 deletions(-) delete mode 100644 kexdhc.c delete mode 100644 kexdhs.c (limited to 'sshd.c') diff --git a/Makefile.in b/Makefile.in index 89f930367..3a179a66f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -98,6 +98,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgexc.o kexecdhc.o \ + kexgexs.o kexecdhs.o \ sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.h b/kex.h index 2eec2e04f..de5e473e1 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.100 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.101 2019/01/21 10:28:01 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -211,6 +211,11 @@ int kexc25519_server(struct ssh *); int kex_kem_client(struct ssh *); int kex_kem_server(struct ssh *); +int kex_dh_keypair(struct kex *); +int kex_dh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, + struct sshbuf **); +int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); + int kex_c25519_keypair(struct kex *); int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); @@ -224,9 +229,6 @@ int kex_kem_sntrup4591761x25519_dec(struct kex *, const u_char *, size_t, int kex_dh_keygen(struct kex *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); -int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *, - const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, - const BIGNUM *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, diff --git a/kexdh.c b/kexdh.c index 5324857b2..4b811b617 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,6 +1,6 @@ -/* $OpenBSD: kexdh.c,v 1.29 2019/01/21 10:03:37 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.30 2019/01/21 10:28:01 djm Exp $ */ /* - * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2019 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,17 +30,11 @@ #include #include +#include +#include -#include - -#include "openbsd-compat/openssl-compat.h" - -#include "ssh2.h" #include "sshkey.h" -#include "cipher.h" #include "kex.h" -#include "dh.h" -#include "ssherr.h" #include "sshbuf.h" #include "digest.h" #include "dh.h" @@ -113,53 +107,95 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) } int -kex_dh_hash( - int hash_alg, - const struct sshbuf *client_version, - const struct sshbuf *server_version, - const u_char *ckexinit, size_t ckexinitlen, - const u_char *skexinit, size_t skexinitlen, - const u_char *serverhostkeyblob, size_t sbloblen, - const BIGNUM *client_dh_pub, - const BIGNUM *server_dh_pub, - const u_char *shared_secret, size_t secretlen, - u_char *hash, size_t *hashlen) +kex_dh_keypair(struct kex *kex) { - struct sshbuf *b; + const BIGNUM *pub_key; + struct sshbuf *buf = NULL; int r; - if (*hashlen < ssh_digest_bytes(hash_alg)) - return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) < 0 || - (r = sshbuf_put_stringb(b, server_version)) < 0 || - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || - (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || - (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || - (r = sshbuf_put(b, shared_secret, secretlen)) != 0) { - sshbuf_free(b); + if ((r = kex_dh_keygen(kex)) != 0) return r; - } -#ifdef DEBUG_KEX - sshbuf_dump(b, stderr); + DH_get0_key(kex->dh, &pub_key, NULL); + if ((buf = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 || + (r = sshbuf_get_u32(buf, NULL)) != 0) + goto out; +#ifdef DEBUG_KEXDH + DHparams_print_fp(stderr, kex->dh); + fprintf(stderr, "pub= "); + BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); #endif - if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { - sshbuf_free(b); - return SSH_ERR_LIBCRYPTO_ERROR; + kex->kem_client_pub = buf; + buf = NULL; + out: + sshbuf_free(buf); + return r; +} + +int +kex_dh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + const BIGNUM *pub_key; + struct sshbuf *server_blob = NULL; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + if ((r = kex_dh_keygen(kex)) != 0) + goto out; + DH_get0_key(kex->dh, &pub_key, NULL); + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } - sshbuf_free(b); - *hashlen = ssh_digest_bytes(hash_alg); -#ifdef DEBUG_KEX - dump_digest("hash", hash, *hashlen); -#endif - return 0; + if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 || + (r = sshbuf_get_u32(server_blob, NULL)) != 0) + goto out; + if ((r = kex_dh_dec(kex, pkblob, pklen, shared_secretp)) != 0) + goto out; + *server_blobp = server_blob; + server_blob = NULL; + out: + DH_free(kex->dh); + kex->dh = NULL; + sshbuf_free(server_blob); + return r; +} + +int +kex_dh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **shared_secretp) +{ + struct sshbuf *buf = NULL; + BIGNUM *dh_pub = NULL; + int r; + + *shared_secretp = NULL; + + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_u32(buf, pklen)) != 0 || + (r = sshbuf_put(buf, pkblob, pklen)) != 0) { + goto out; + } + if ((r = sshbuf_get_bignum2(buf, &dh_pub)) != 0) { + goto out; + } + sshbuf_reset(buf); + if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0) + goto out; + *shared_secretp = buf; + buf = NULL; + out: + DH_free(kex->dh); + kex->dh = NULL; + sshbuf_free(buf); + return r; } #endif /* WITH_OPENSSL */ diff --git a/kexdhc.c b/kexdhc.c deleted file mode 100644 index a2af8cb08..000000000 --- a/kexdhc.c +++ /dev/null @@ -1,151 +0,0 @@ -/* $OpenBSD: kexdhc.c,v 1.29 2019/01/21 10:07:22 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef WITH_OPENSSL - -#include - -#include - -#include -#include -#include -#include - -#include "openbsd-compat/openssl-compat.h" - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "dh.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_dh(int, u_int32_t, struct ssh *); - -int -kexdh_client(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - int r; - const BIGNUM *pub_key; - - /* generate and send 'e', client DH public key */ - if ((r = kex_dh_keygen(kex)) != 0) - goto out; - debug("sending SSH2_MSG_KEXDH_INIT"); - DH_get0_key(kex->dh, &pub_key, NULL); - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || - (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); -#endif - debug("expecting SSH2_MSG_KEXDH_REPLY"); - ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh); - r = 0; - out: - return r; -} - -static int -input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - BIGNUM *dh_server_pub = NULL; - const BIGNUM *pub_key; - struct sshkey *server_host_key = NULL; - struct sshbuf *shared_secret = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen, hashlen; - int r; - - /* key, cert */ - if ((r = sshpkt_get_string(ssh, &server_host_key_blob, - &sbloblen)) != 0 || - (r = sshkey_from_blob(server_host_key_blob, sbloblen, - &server_host_key)) != 0) - goto out; - if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) - goto out; - /* DH parameter f, server public DH key, signed H */ - if ((r = sshpkt_get_bignum2(ssh, &dh_server_pub)) != 0 || - (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) - goto out; - - /* calc and verify H */ - DH_get0_key(kex->dh, &pub_key, NULL); - hashlen = sizeof(hash); - if ((r = kex_dh_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, - pub_key, - dh_server_pub, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, - kex->hostkey_alg, ssh->compat)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; - BN_clear_free(dh_server_pub); - sshbuf_free(shared_secret); - sshkey_free(server_host_key); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* WITH_OPENSSL */ diff --git a/kexdhs.c b/kexdhs.c deleted file mode 100644 index e33901bbf..000000000 --- a/kexdhs.c +++ /dev/null @@ -1,142 +0,0 @@ -/* $OpenBSD: kexdhs.c,v 1.35 2019/01/21 10:05:09 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef WITH_OPENSSL - -#include - -#include -#include -#include - -#include - -#include "openbsd-compat/openssl-compat.h" - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "dh.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" - -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_dh_init(int, u_int32_t, struct ssh *); - -int -kexdh_server(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - int r; - - /* generate server DH public key */ - if ((r = kex_dh_keygen(kex)) != 0) - return r; - debug("expecting SSH2_MSG_KEXDH_INIT"); - ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init); - return 0; -} - -int -input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - BIGNUM *dh_client_pub = NULL; - const BIGNUM *pub_key; - struct sshkey *server_host_public, *server_host_private; - struct sshbuf *shared_secret = NULL; - u_char *signature = NULL, *server_host_key_blob = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t sbloblen, slen; - size_t hashlen; - int r; - - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) - goto out; - - /* key, cert */ - if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - if ((shared_secret = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) - goto out; - if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, - &sbloblen)) != 0) - goto out; - /* calc H */ - DH_get0_key(kex->dh, &pub_key, NULL); - hashlen = sizeof(hash); - if ((r = kex_dh_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - dh_client_pub, - pub_key, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) - goto out; - - /* send server hostkey, DH pubkey 'f' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || - (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; - BN_clear_free(dh_client_pub); - sshbuf_free(shared_secret); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* WITH_OPENSSL */ diff --git a/kexkemc.c b/kexkemc.c index 13f36a116..384a4db59 100644 --- a/kexkemc.c +++ b/kexkemc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkemc.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: kexkemc.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -48,6 +48,13 @@ kex_kem_client(struct ssh *ssh) int r; switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + case KEX_DH_GRP16_SHA512: + case KEX_DH_GRP18_SHA512: + r = kex_dh_keypair(kex); + break; case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; @@ -99,6 +106,13 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) /* compute shared secret */ switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + case KEX_DH_GRP16_SHA512: + case KEX_DH_GRP18_SHA512: + r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); break; diff --git a/kexkems.c b/kexkems.c index 89237902b..f35906d53 100644 --- a/kexkems.c +++ b/kexkems.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkems.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: kexkems.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -69,6 +69,14 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) /* compute shared secret */ switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + case KEX_DH_GRP16_SHA512: + case KEX_DH_GRP18_SHA512: + r = kex_dh_enc(kex, client_pubkey, pklen, &server_pubkey, + &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, &shared_secret); diff --git a/monitor.c b/monitor.c index 9f86d5b75..01204c2cd 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.194 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.195 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1677,11 +1677,11 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) if ((kex = ssh->kex) != NULL) { /* XXX set callbacks */ #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; - kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; - kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 9eebc1445..3d2760056 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.122 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.123 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -260,11 +260,11 @@ keygrab_ssh2(con *c) exit(1); } #ifdef WITH_OPENSSL - c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC diff --git a/ssh_api.c b/ssh_api.c index fe9fbf5a7..ac614e599 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.12 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.13 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -99,11 +99,11 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->server = is_server; if (is_server) { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC @@ -117,11 +117,11 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->sign=&_ssh_host_key_sign; } else { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC diff --git a/sshconnect2.c b/sshconnect2.c index be19722bb..ebeff29bd 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.298 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.299 2019/01/21 10:28:02 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -201,11 +201,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC diff --git a/sshd.c b/sshd.c index 665b22b1e..eb92785bf 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.529 2019/01/21 10:24:09 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.530 2019/01/21 10:28:02 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2207,11 +2207,11 @@ do_ssh2_kex(struct ssh *ssh) fatal("kex_setup: %s", ssh_err(r)); kex = ssh->kex; #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server; - kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server; - kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC -- cgit v1.2.3 From 92dda34e373832f34a1944e5d9ebbebb184dedc1 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:29:56 +0000 Subject: upstream: use KEM API for vanilla ECDH from markus@ ok djm@ OpenBSD-Commit-ID: 6fbff96339a929835536b5730585d1d6057a352c --- Makefile.in | 3 +- kex.h | 12 ++-- kexecdh.c | 213 ++++++++++++++++++++++++++++++++++++++++++++-------------- kexecdhc.c | 199 ------------------------------------------------------ kexecdhs.c | 182 ------------------------------------------------- kexkemc.c | 8 ++- kexkems.c | 6 +- monitor.c | 4 +- ssh-keyscan.c | 4 +- ssh_api.c | 6 +- sshconnect2.c | 4 +- sshd.c | 4 +- 12 files changed, 193 insertions(+), 452 deletions(-) delete mode 100644 kexecdhc.c delete mode 100644 kexecdhs.c (limited to 'sshd.c') diff --git a/Makefile.in b/Makefile.in index 3a179a66f..fd539184a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -98,8 +98,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexgexc.o kexecdhc.o \ - kexgexs.o kexecdhs.o \ + kexgexc.o kexgexs.o \ sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.h b/kex.h index de5e473e1..9b4c23670 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.101 2019/01/21 10:28:01 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.102 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -216,6 +216,11 @@ int kex_dh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); int kex_dh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); +int kex_ecdh_keypair(struct kex *); +int kex_ecdh_enc(struct kex *, const u_char *, size_t, struct sshbuf **, + struct sshbuf **); +int kex_ecdh_dec(struct kex *, const u_char *, size_t, struct sshbuf **); + int kex_c25519_keypair(struct kex *); int kex_c25519_enc(struct kex *, const u_char *, size_t, struct sshbuf **, struct sshbuf **); @@ -237,11 +242,6 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); -int kex_ecdh_hash(int, const EC_GROUP *, - const struct sshbuf *, const struct sshbuf *, - const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, - const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *); - int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, diff --git a/kexecdh.c b/kexecdh.c index 4380427ea..263f9fd87 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,7 +1,7 @@ -/* $OpenBSD: kexecdh.c,v 1.7 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.8 2019/01/21 10:29:56 djm Exp $ */ /* - * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. + * Copyright (c) 2019 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,71 +30,184 @@ #include -#include +#include #include +#include -#include -#include -#include #include -#include "ssh2.h" #include "sshkey.h" -#include "cipher.h" #include "kex.h" #include "sshbuf.h" #include "digest.h" #include "ssherr.h" +static int +kex_ecdh_dec_key_group(struct kex *, const u_char *, size_t, EC_KEY *key, + const EC_GROUP *, struct sshbuf **); + int -kex_ecdh_hash( - int hash_alg, - const EC_GROUP *ec_group, - const struct sshbuf *client_version, - const struct sshbuf *server_version, - const u_char *ckexinit, size_t ckexinitlen, - const u_char *skexinit, size_t skexinitlen, - const u_char *serverhostkeyblob, size_t sbloblen, - const EC_POINT *client_dh_pub, - const EC_POINT *server_dh_pub, - const BIGNUM *shared_secret, - u_char *hash, size_t *hashlen) +kex_ecdh_keypair(struct kex *kex) +{ + EC_KEY *client_key = NULL; + const EC_GROUP *group; + const EC_POINT *public_key; + struct sshbuf *buf = NULL; + int r; + + if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_KEY_generate_key(client_key) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + group = EC_KEY_get0_group(client_key); + public_key = EC_KEY_get0_public_key(client_key); + + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_ec(buf, public_key, group)) != 0 || + (r = sshbuf_get_u32(buf, NULL)) != 0) + goto out; +#ifdef DEBUG_KEXECDH + fputs("client private key:\n", stderr); + sshkey_dump_ec_key(client_key); +#endif + kex->ec_client_key = client_key; + kex->ec_group = group; + client_key = NULL; /* owned by the kex */ + kex->kem_client_pub = buf; + buf = NULL; + out: + EC_KEY_free(client_key); + sshbuf_free(buf); + return r; +} + +int +kex_ecdh_enc(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **server_blobp, struct sshbuf **shared_secretp) +{ + const EC_GROUP *group; + const EC_POINT *pub_key; + EC_KEY *server_key = NULL; + struct sshbuf *server_blob = NULL; + int r; + + *server_blobp = NULL; + *shared_secretp = NULL; + + if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_KEY_generate_key(server_key) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + group = EC_KEY_get0_group(server_key); + +#ifdef DEBUG_KEXECDH + fputs("server private key:\n", stderr); + sshkey_dump_ec_key(server_key); +#endif + pub_key = EC_KEY_get0_public_key(server_key); + if ((server_blob = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 || + (r = sshbuf_get_u32(server_blob, NULL)) != 0) + goto out; + if ((r = kex_ecdh_dec_key_group(kex, pkblob, pklen, server_key, group, + shared_secretp)) != 0) + goto out; + *server_blobp = server_blob; + server_blob = NULL; + out: + EC_KEY_free(server_key); + sshbuf_free(server_blob); + return r; +} + +static int +kex_ecdh_dec_key_group(struct kex *kex, const u_char *pkblob, size_t pklen, + EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp) { - struct sshbuf *b; + struct sshbuf *buf = NULL; + BIGNUM *shared_secret = NULL; + EC_POINT *dh_pub = NULL; + u_char *kbuf = NULL; + size_t klen = 0; int r; - if (*hashlen < ssh_digest_bytes(hash_alg)) - return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) < 0 || - (r = sshbuf_put_stringb(b, server_version)) < 0 || - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || - (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || - (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || - (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { - sshbuf_free(b); - return r; + *shared_secretp = NULL; + + if ((buf = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_u32(buf, pklen)) != 0 || + (r = sshbuf_put(buf, pkblob, pklen)) != 0) { + goto out; + } + if ((dh_pub = EC_POINT_new(group)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) { + goto out; } -#ifdef DEBUG_KEX - sshbuf_dump(b, stderr); + sshbuf_reset(buf); + +#ifdef DEBUG_KEXECDH + fputs("public key:\n", stderr); + sshkey_dump_ec_point(group, dh_pub); #endif - if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { - sshbuf_free(b); - return SSH_ERR_LIBCRYPTO_ERROR; + if (sshkey_ec_validate_public(group, dh_pub) != 0) { + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } + klen = (EC_GROUP_get_degree(group) + 7) / 8; + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || + BN_bin2bn(kbuf, klen, shared_secret) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } - sshbuf_free(b); - *hashlen = ssh_digest_bytes(hash_alg); -#ifdef DEBUG_KEX - dump_digest("hash", hash, *hashlen); +#ifdef DEBUG_KEXECDH + dump_digest("shared secret", kbuf, klen); #endif - return 0; + if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0) + goto out; + *shared_secretp = buf; + buf = NULL; + out: + EC_POINT_clear_free(dh_pub); + BN_clear_free(shared_secret); + freezero(kbuf, klen); + sshbuf_free(buf); + return r; +} + +int +kex_ecdh_dec(struct kex *kex, const u_char *pkblob, size_t pklen, + struct sshbuf **shared_secretp) +{ + int r; + + r = kex_ecdh_dec_key_group(kex, pkblob, pklen, kex->ec_client_key, + kex->ec_group, shared_secretp); + EC_KEY_free(kex->ec_client_key); + kex->ec_client_key = NULL; + return r; } #endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ diff --git a/kexecdhc.c b/kexecdhc.c deleted file mode 100644 index bfb9f4707..000000000 --- a/kexecdhc.c +++ /dev/null @@ -1,199 +0,0 @@ -/* $OpenBSD: kexecdhc.c,v 1.16 2019/01/21 10:07:22 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - -#include - -#include -#include -#include - -#include - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "dh.h" -#include "ssh2.h" -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *); - -int -kexecdh_client(struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - EC_KEY *client_key = NULL; - const EC_GROUP *group; - const EC_POINT *public_key; - int r; - - if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (EC_KEY_generate_key(client_key) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - group = EC_KEY_get0_group(client_key); - public_key = EC_KEY_get0_public_key(client_key); - - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 || - (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - debug("sending SSH2_MSG_KEX_ECDH_INIT"); - -#ifdef DEBUG_KEXECDH - fputs("client private key:\n", stderr); - sshkey_dump_ec_key(client_key); -#endif - kex->ec_client_key = client_key; - kex->ec_group = group; - client_key = NULL; /* owned by the kex */ - - debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply); - r = 0; - out: - EC_KEY_free(client_key); - return r; -} - -static int -input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - const EC_GROUP *group; - EC_POINT *server_public = NULL; - EC_KEY *client_key; - BIGNUM *shared_secret = NULL; - struct sshkey *server_host_key = NULL; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen; - size_t klen = 0, hashlen; - int r; - - group = kex->ec_group; - client_key = kex->ec_client_key; - - /* hostkey */ - if ((r = sshpkt_get_string(ssh, &server_host_key_blob, - &sbloblen)) != 0 || - (r = sshkey_from_blob(server_host_key_blob, sbloblen, - &server_host_key)) != 0) - goto out; - if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) - goto out; - - /* Q_S, server public key */ - /* signed H */ - if ((server_public = EC_POINT_new(group)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 || - (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - -#ifdef DEBUG_KEXECDH - fputs("server public key:\n", stderr); - sshkey_dump_ec_point(group, server_public); -#endif - if (sshkey_ec_validate_public(group, server_public) != 0) { - sshpkt_disconnect(ssh, "invalid server public key"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - klen = (EC_GROUP_get_degree(group) + 7) / 8; - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (ECDH_compute_key(kbuf, klen, server_public, - client_key, NULL) != (int)klen || - BN_bin2bn(kbuf, klen, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -#ifdef DEBUG_KEXECDH - dump_digest("shared secret", kbuf, klen); -#endif - /* calc and verify H */ - hashlen = sizeof(hash); - if ((r = kex_ecdh_hash( - kex->hash_alg, - group, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, - EC_KEY_get0_public_key(client_key), - server_public, - shared_secret, - hash, &hashlen)) != 0) - goto out; - - if ((r = sshkey_verify(server_host_key, signature, slen, hash, - hashlen, kex->hostkey_alg, ssh->compat)) != 0) - goto out; - - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - EC_KEY_free(kex->ec_client_key); - kex->ec_client_key = NULL; - EC_POINT_clear_free(server_public); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); - sshkey_free(server_host_key); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ - diff --git a/kexecdhs.c b/kexecdhs.c deleted file mode 100644 index b9254eed7..000000000 --- a/kexecdhs.c +++ /dev/null @@ -1,182 +0,0 @@ -/* $OpenBSD: kexecdhs.c,v 1.21 2019/01/21 10:05:09 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - -#include -#include -#include - -#include - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" -#include "kex.h" -#include "log.h" -#include "packet.h" -#include "ssh2.h" - -#include "dispatch.h" -#include "compat.h" -#include "ssherr.h" -#include "sshbuf.h" - -static int input_kex_ecdh_init(int, u_int32_t, struct ssh *); - -int -kexecdh_server(struct ssh *ssh) -{ - debug("expecting SSH2_MSG_KEX_ECDH_INIT"); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_ecdh_init); - return 0; -} - -static int -input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) -{ - struct kex *kex = ssh->kex; - EC_POINT *client_public; - EC_KEY *server_key = NULL; - const EC_GROUP *group; - const EC_POINT *public_key; - BIGNUM *shared_secret = NULL; - struct sshkey *server_host_private, *server_host_public; - u_char *server_host_key_blob = NULL, *signature = NULL; - u_char *kbuf = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t slen, sbloblen; - size_t klen = 0, hashlen; - int r; - - if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (EC_KEY_generate_key(server_key) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - group = EC_KEY_get0_group(server_key); - -#ifdef DEBUG_KEXECDH - fputs("server private key:\n", stderr); - sshkey_dump_ec_key(server_key); -#endif - - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) - goto out; - if ((client_public = EC_POINT_new(group)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) - goto out; - -#ifdef DEBUG_KEXECDH - fputs("client public key:\n", stderr); - sshkey_dump_ec_point(group, client_public); -#endif - if (sshkey_ec_validate_public(group, client_public) != 0) { - sshpkt_disconnect(ssh, "invalid client public key"); - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - - /* Calculate shared_secret */ - klen = (EC_GROUP_get_degree(group) + 7) / 8; - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (ECDH_compute_key(kbuf, klen, client_public, - server_key, NULL) != (int)klen || - BN_bin2bn(kbuf, klen, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -#ifdef DEBUG_KEXECDH - dump_digest("shared secret", kbuf, klen); -#endif - /* calc H */ - if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, - &sbloblen)) != 0) - goto out; - hashlen = sizeof(hash); - if ((r = kex_ecdh_hash( - kex->hash_alg, - group, - kex->client_version, - kex->server_version, - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - client_public, - EC_KEY_get0_public_key(server_key), - shared_secret, - hash, &hashlen)) != 0) - goto out; - - /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) - goto out; - - /* destroy_sensitive_data(); */ - - public_key = EC_KEY_get0_public_key(server_key); - /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || - (r = sshpkt_put_ec(ssh, public_key, group)) != 0 || - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - - if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - out: - explicit_bzero(hash, sizeof(hash)); - EC_KEY_free(kex->ec_client_key); - kex->ec_client_key = NULL; - EC_KEY_free(server_key); - if (kbuf) { - explicit_bzero(kbuf, klen); - free(kbuf); - } - BN_clear_free(shared_secret); - free(server_host_key_blob); - free(signature); - return r; -} -#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ - diff --git a/kexkemc.c b/kexkemc.c index 384a4db59..55055de27 100644 --- a/kexkemc.c +++ b/kexkemc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkemc.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: kexkemc.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -55,6 +55,9 @@ kex_kem_client(struct ssh *ssh) case KEX_DH_GRP18_SHA512: r = kex_dh_keypair(kex); break; + case KEX_ECDH_SHA2: + r = kex_ecdh_keypair(kex); + break; case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; @@ -113,6 +116,9 @@ input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh) case KEX_DH_GRP18_SHA512: r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret); break; + case KEX_ECDH_SHA2: + r = kex_ecdh_dec(kex, server_pubkey, pklen, &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret); break; diff --git a/kexkems.c b/kexkems.c index f35906d53..10ef12196 100644 --- a/kexkems.c +++ b/kexkems.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexkems.c,v 1.3 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: kexkems.c,v 1.4 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -77,6 +77,10 @@ input_kex_kem_init(int type, u_int32_t seq, struct ssh *ssh) r = kex_dh_enc(kex, client_pubkey, pklen, &server_pubkey, &shared_secret); break; + case KEX_ECDH_SHA2: + r = kex_ecdh_enc(kex, client_pubkey, pklen, &server_pubkey, + &shared_secret); + break; case KEX_C25519_SHA256: r = kex_c25519_enc(kex, client_pubkey, pklen, &server_pubkey, &shared_secret); diff --git a/monitor.c b/monitor.c index 01204c2cd..d3357b73c 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.195 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.196 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1685,7 +1685,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + kex->kex[KEX_ECDH_SHA2] = kex_kem_server; # endif #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_kem_server; diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 3d2760056..9541ecf4a 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.123 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.124 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -268,7 +268,7 @@ keygrab_ssh2(con *c) c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; diff --git a/ssh_api.c b/ssh_api.c index ac614e599..b21769d23 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.13 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.14 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -107,7 +107,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_server; # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server; @@ -125,7 +125,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; diff --git a/sshconnect2.c b/sshconnect2.c index ebeff29bd..aa5160185 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.299 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.300 2019/01/21 10:29:56 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -209,7 +209,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; # endif #endif ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; diff --git a/sshd.c b/sshd.c index eb92785bf..ddbedd6c6 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.530 2019/01/21 10:28:02 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.531 2019/01/21 10:29:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2215,7 +2215,7 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + kex->kex[KEX_ECDH_SHA2] = kex_kem_server; # endif #endif kex->kex[KEX_C25519_SHA256] = kex_kem_server; -- cgit v1.2.3 From aaca72d6f1279b842066e07bff797019efeb2c23 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 21 Jan 2019 10:40:11 +0000 Subject: upstream: rename kex->kem_client_pub -> kex->client_pub now that KEM has been renamed to kexgen from markus@ ok djm@ OpenBSD-Commit-ID: fac6da5dc63530ad0da537db022a9a4cfbe8bed8 --- Makefile.in | 2 +- kex.c | 4 ++-- kex.h | 19 ++++------------- kexc25519.c | 55 ++---------------------------------------------- kexdh.c | 4 ++-- kexecdh.c | 4 ++-- kexsntrup4591761x25519.c | 4 ++-- monitor.c | 18 ++++++++-------- ssh-keyscan.c | 18 ++++++++-------- ssh_api.c | 34 +++++++++++++++--------------- sshconnect2.c | 18 ++++++++-------- sshd.c | 18 ++++++++-------- 12 files changed, 68 insertions(+), 130 deletions(-) (limited to 'sshd.c') diff --git a/Makefile.in b/Makefile.in index fd539184a..6f001bb36 100644 --- a/Makefile.in +++ b/Makefile.in @@ -99,7 +99,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ - sntrup4591761.o kexsntrup4591761x25519.o kexkemc.o kexkems.o \ + sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ platform-pledge.o platform-tracing.o platform-misc.o diff --git a/kex.c b/kex.c index 4fb087863..cec9b2985 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.148 2019/01/21 10:33:49 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.149 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -655,7 +655,7 @@ kex_free(struct kex *kex) sshbuf_free(kex->my); sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); - sshbuf_free(kex->kem_client_pub); + sshbuf_free(kex->client_pub); free(kex->session_id); free(kex->failed_choice); free(kex->hostkey_alg); diff --git a/kex.h b/kex.h index 6798e33f9..44e6d1972 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.104 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.106 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -170,7 +170,7 @@ struct kex { u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */ - struct sshbuf *kem_client_pub; /* KEM */ + struct sshbuf *client_pub; }; int kex_names_valid(const char *); @@ -199,16 +199,10 @@ int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); int kex_send_newkeys(struct ssh *); int kex_start_rekex(struct ssh *); -int kexdh_client(struct ssh *); -int kexdh_server(struct ssh *); int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); -int kexecdh_client(struct ssh *); -int kexecdh_server(struct ssh *); -int kexc25519_client(struct ssh *); -int kexc25519_server(struct ssh *); -int kex_kem_client(struct ssh *); -int kex_kem_server(struct ssh *); +int kex_gen_client(struct ssh *); +int kex_gen_server(struct ssh *); int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, @@ -241,11 +235,6 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); -int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *, - const u_char *, size_t, const u_char *, size_t, - const u_char *, size_t, const struct sshbuf *, const struct sshbuf *, - const struct sshbuf *, u_char *, size_t *); - void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); diff --git a/kexc25519.c b/kexc25519.c index ec5bb574f..f13d766d7 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.15 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.17 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -88,57 +88,6 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE], return kexc25519_shared_key_ext(key, pub, out, 0); } -int -kex_c25519_hash( - int hash_alg, - const struct sshbuf *client_version, - const struct sshbuf *server_version, - const u_char *ckexinit, size_t ckexinitlen, - const u_char *skexinit, size_t skexinitlen, - const u_char *serverhostkeyblob, size_t sbloblen, - const struct sshbuf *client_pub, - const struct sshbuf *server_pub, - const struct sshbuf *shared_secret, - u_char *hash, size_t *hashlen) -{ - struct sshbuf *b; - int r; - - if (*hashlen < ssh_digest_bytes(hash_alg)) - return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) != 0 || - (r = sshbuf_put_stringb(b, server_version)) != 0 || - /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ - (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || - (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || - (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || - (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || - (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || - (r = sshbuf_put_stringb(b, client_pub)) != 0 || - (r = sshbuf_put_stringb(b, server_pub)) != 0 || - (r = sshbuf_putb(b, shared_secret)) != 0) { - sshbuf_free(b); - return r; - } -#ifdef DEBUG_KEX - sshbuf_dump(b, stderr); -#endif - if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { - sshbuf_free(b); - return SSH_ERR_LIBCRYPTO_ERROR; - } - sshbuf_free(b); - *hashlen = ssh_digest_bytes(hash_alg); -#ifdef DEBUG_KEX - dump_digest("hash", hash, *hashlen); -#endif - return 0; -} - int kex_c25519_keypair(struct kex *kex) { @@ -154,7 +103,7 @@ kex_c25519_keypair(struct kex *kex) #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); #endif - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: sshbuf_free(buf); diff --git a/kexdh.c b/kexdh.c index 943774624..6812add20 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.31 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -128,7 +128,7 @@ kex_dh_keypair(struct kex *kex) BN_print_fp(stderr, pub_key); fprintf(stderr, "\n"); #endif - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: sshbuf_free(buf); diff --git a/kexecdh.c b/kexecdh.c index ae9018773..0aeab2e9b 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.9 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved. @@ -80,7 +80,7 @@ kex_ecdh_keypair(struct kex *kex) kex->ec_client_key = client_key; kex->ec_group = group; client_key = NULL; /* owned by the kex */ - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: EC_KEY_free(client_key); diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c index d845f3d44..b0605b96a 100644 --- a/kexsntrup4591761x25519.c +++ b/kexsntrup4591761x25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexsntrup4591761x25519.c,v 1.2 2019/01/21 10:35:09 djm Exp $ */ +/* $OpenBSD: kexsntrup4591761x25519.c,v 1.3 2019/01/21 10:40:11 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -58,7 +58,7 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex) #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); #endif - kex->kem_client_pub = buf; + kex->client_pub = buf; buf = NULL; out: sshbuf_free(buf); diff --git a/monitor.c b/monitor.c index d3357b73c..60e529444 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.196 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.197 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1677,19 +1677,19 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) if ((kex = ssh->kex) != NULL) { /* XXX set callbacks */ #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; - kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; - kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_kem_server; + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kex_kem_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 9541ecf4a..144daa6df 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.124 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.125 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -260,19 +260,19 @@ keygrab_ssh2(con *c) exit(1); } #ifdef WITH_OPENSSL - c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; - c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; + c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; + c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; + c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif - c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; - c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; + c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* * do the key-exchange until an error occurs or until diff --git a/ssh_api.c b/ssh_api.c index b21769d23..57509973b 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.14 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.15 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -99,37 +99,37 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) ssh->kex->server = is_server; if (is_server) { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_server; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_server; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; ssh->kex->load_host_public_key=&_ssh_host_public_key; ssh->kex->load_host_private_key=&_ssh_host_private_key; ssh->kex->sign=&_ssh_host_key_sign; } else { #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; diff --git a/sshconnect2.c b/sshconnect2.c index aa5160185..2aa7b9933 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.300 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.301 2019/01/21 10:38:54 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -201,19 +201,19 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); #ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_kem_client; + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif - ssh->kex->kex[KEX_C25519_SHA256] = kex_kem_client; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_client; + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); diff --git a/sshd.c b/sshd.c index ddbedd6c6..058260d6f 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.531 2019/01/21 10:29:56 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.532 2019/01/21 10:38:54 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2207,19 +2207,19 @@ do_ssh2_kex(struct ssh *ssh) fatal("kex_setup: %s", ssh_err(r)); kex = ssh->kex; #ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA1] = kex_kem_server; - kex->kex[KEX_DH_GRP14_SHA256] = kex_kem_server; - kex->kex[KEX_DH_GRP16_SHA512] = kex_kem_server; - kex->kex[KEX_DH_GRP18_SHA512] = kex_kem_server; + kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_kem_server; + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif - kex->kex[KEX_C25519_SHA256] = kex_kem_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_kem_server; + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; -- cgit v1.2.3 From 76a24b3fa193a9ca3e47a8779d497cb06500798b Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 1 Mar 2019 02:32:39 +0000 Subject: upstream: Fix two race conditions in sshd relating to SIGHUP: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Recently-forked child processes will briefly remain listening to listen_socks. If the main server sshd process completes its restart via execv() before these sockets are closed by the child processes then it can fail to listen at the desired addresses/ports and/or fail to restart. 2. When a SIGHUP is received, there may be forked child processes that are awaiting their reexecution state. If the main server sshd process restarts before passing this state, these child processes will yield errors and use a fallback path of reading the current sshd_config from the filesystem rather than use the one that sshd was started with. To fix both of these cases, we reuse the startup_pipes that are shared between the main server sshd and forked children. Previously this was used solely to implement tracking of pre-auth child processes for MaxStartups, but this extends the messaging over these pipes to include a child->parent message that the parent process is safe to restart. This message is sent from the child after it has completed its preliminaries: closing listen_socks and receiving its reexec state. bz#2953, reported by Michal Koutný; ok markus@ dtucker@ OpenBSD-Commit-ID: 7df09eacfa3ce13e9a7b1e9f17276ecc924d65ab --- sshd.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 28 deletions(-) (limited to 'sshd.c') diff --git a/sshd.c b/sshd.c index 058260d6f..cbd3bce91 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.532 2019/01/21 10:38:54 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.533 2019/03/01 02:32:39 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -213,9 +213,26 @@ u_int session_id2_len = 0; /* record remote hostname or ip */ u_int utmp_len = HOST_NAME_MAX+1; -/* options.max_startup sized array of fd ints */ +/* + * startup_pipes/flags are used for tracking children of the listening sshd + * process early in their lifespans. This tracking is needed for three things: + * + * 1) Implementing the MaxStartups limit of concurrent unauthenticated + * connections. + * 2) Avoiding a race condition for SIGHUP processing, where child processes + * may have listen_socks open that could collide with main listener process + * after it restarts. + * 3) Ensuring that rexec'd sshd processes have received their initial state + * from the parent listen process before handling SIGHUP. + * + * Child processes signal that they have completed closure of the listen_socks + * and (if applicable) received their rexec state by sending a char over their + * sock. Child processes signal that authentication has completed by closing + * the sock (or by exiting). + */ static int *startup_pipes = NULL; -static int startup_pipe; /* in child */ +static int *startup_flags = NULL; /* Indicates child closed listener */ +static int startup_pipe = -1; /* in child */ /* variables used for privilege separation */ int use_privsep = -1; @@ -901,14 +918,9 @@ server_accept_inetd(int *sock_in, int *sock_out) { int fd; - startup_pipe = -1; if (rexeced_flag) { close(REEXEC_CONFIG_PASS_FD); *sock_in = *sock_out = dup(STDIN_FILENO); - if (!debug_flag) { - startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); - close(REEXEC_STARTUP_PIPE_FD); - } } else { *sock_in = dup(STDIN_FILENO); *sock_out = dup(STDOUT_FILENO); @@ -1033,8 +1045,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) { fd_set *fdset; int i, j, ret, maxfd; - int startups = 0; + int startups = 0, listening = 0, lameduck = 0; int startup_p[2] = { -1 , -1 }; + char c = 0; struct sockaddr_storage from; socklen_t fromlen; pid_t pid; @@ -1048,6 +1061,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) maxfd = listen_socks[i]; /* pipes connected to unauthenticated childs */ startup_pipes = xcalloc(options.max_startups, sizeof(int)); + startup_flags = xcalloc(options.max_startups, sizeof(int)); for (i = 0; i < options.max_startups; i++) startup_pipes[i] = -1; @@ -1056,8 +1070,15 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) * the daemon is killed with a signal. */ for (;;) { - if (received_sighup) - sighup_restart(); + if (received_sighup) { + if (!lameduck) { + debug("Received SIGHUP; waiting for children"); + close_listen_socks(); + lameduck = 1; + } + if (listening <= 0) + sighup_restart(); + } free(fdset); fdset = xcalloc(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask)); @@ -1083,19 +1104,37 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) if (ret < 0) continue; - for (i = 0; i < options.max_startups; i++) - if (startup_pipes[i] != -1 && - FD_ISSET(startup_pipes[i], fdset)) { - /* - * the read end of the pipe is ready - * if the child has closed the pipe - * after successful authentication - * or if the child has died - */ + for (i = 0; i < options.max_startups; i++) { + if (startup_pipes[i] == -1 || + !FD_ISSET(startup_pipes[i], fdset)) + continue; + switch (read(startup_pipes[i], &c, sizeof(c))) { + case -1: + if (errno == EINTR || errno == EAGAIN) + continue; + if (errno != EPIPE) { + error("%s: startup pipe %d (fd=%d): " + "read %s", __func__, i, + startup_pipes[i], strerror(errno)); + } + /* FALLTHROUGH */ + case 0: + /* child exited or completed auth */ close(startup_pipes[i]); startup_pipes[i] = -1; startups--; + if (startup_flags[i]) + listening--; + break; + case 1: + /* child has finished preliminaries */ + if (startup_flags[i]) { + listening--; + startup_flags[i] = 0; + } + break; } + } for (i = 0; i < num_listen_socks; i++) { if (!FD_ISSET(listen_socks[i], fdset)) continue; @@ -1149,6 +1188,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) if (maxfd < startup_p[0]) maxfd = startup_p[0]; startups++; + startup_flags[j] = 1; break; } @@ -1174,7 +1214,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) send_rexec_state(config_s[0], cfg); close(config_s[0]); } - break; + return; } /* @@ -1183,13 +1223,14 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) * parent continues listening. */ platform_pre_fork(); + listening++; if ((pid = fork()) == 0) { /* * Child. Close the listening and * max_startup sockets. Start using * the accepted socket. Reinitialize * logging (since our pid has changed). - * We break out of the loop to handle + * We return from this function to handle * the connection. */ platform_post_fork_child(); @@ -1204,7 +1245,18 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) log_stderr); if (rexec_flag) close(config_s[0]); - break; + else { + /* + * Signal parent that the preliminaries + * for this child are complete. For the + * re-exec case, this happens after the + * child has received the rexec state + * from the server. + */ + (void)atomicio(vwrite, startup_pipe, + "\0", 1); + } + return; } /* Parent. Stay in the loop. */ @@ -1236,10 +1288,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) #endif explicit_bzero(rnd, sizeof(rnd)); } - - /* child process check (or debug mode) */ - if (num_listen_socks < 0) - break; } } @@ -1569,8 +1617,18 @@ main(int ac, char **av) /* Fetch our configuration */ if ((cfg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); - if (rexeced_flag) + if (rexeced_flag) { recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); + if (!debug_flag) { + startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); + close(REEXEC_STARTUP_PIPE_FD); + /* + * Signal parent that this child is at a point where + * they can go away if they have a SIGHUP pending. + */ + (void)atomicio(vwrite, startup_pipe, "\0", 1); + } + } else if (strcasecmp(config_file_name, "none") != 0) load_server_config(config_file_name, cfg); -- cgit v1.2.3