See attached: (1) patch against 7.9p1, tested with openssl 1.1.0j and openssl 1.1.1a on linux/i386; passes regression test and connects to unpatched sshd without problems; I hacked a bit regress/unittests/kex, and benchmarked do_kex_with_key("curve25519-sha256@xxxxxxxxxx", KEY_ED25519, 256); Before: 0.3295s per call After: 0.2183s per call That is, 50% speedup; assuming ed25519 (added to openssl in 1.1.1) takes about same time as ecdh/x25519, there are potential for total 200% speedup in KEX. (2) rebased patch against git master; passes regression test; I relied on presence of NID_X25519 for autodetection; probably it makes sense to check if is actually working it autoconf; then again, maybe not (it won't work when cross-compiling anyway). P.S. given amount of feedback I received so far, it seems everyone follows motto "it cannot be secure if it is not slow".
>From 2718c5db54215445d8c7cdb5aeade68df999f2a8 Mon Sep 17 00:00:00 2001 From: "Yuriy M. Kaminskiy" <yumkam@xxxxxxxxx> Date: Sun, 17 Feb 2019 02:35:10 +0300 Subject: [PATCH] use kex/x25519 from openssl when possible --- configure.ac | 2 ++ kex.h | 33 +++++++++++++++++--- kexc25519.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- kexc25519c.c | 11 +++++-- kexc25519s.c | 8 +++-- 5 files changed, 140 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 7379ab35..9b3269b4 100644 --- a/configure.ac +++ b/configure.ac @@ -2697,6 +2697,8 @@ if test "x$openssl" = "xyes" ; then ) AC_CHECK_FUNCS([ \ + EVP_PKEY_get_raw_public_key \ + EVP_PKEY_new_raw_public_key \ BN_is_prime_ex \ DSA_generate_parameters_ex \ EVP_DigestInit_ex \ diff --git a/kex.h b/kex.h index 593de120..663b63ff 100644 --- a/kex.h +++ b/kex.h @@ -40,6 +40,9 @@ # define EC_GROUP void # define EC_POINT void # endif /* OPENSSL_HAS_ECC */ +# if defined(NID_X25519) +# define WITH_OPENSSL_X25519 +# endif #else /* WITH_OPENSSL */ # define DH void # define BIGNUM void @@ -128,6 +131,12 @@ struct newkeys { struct ssh; +#ifdef WITH_OPENSSL_X25519 +typedef EVP_PKEY *x25519_t; +#else +typedef u_char x25519_t[CURVE25519_SIZE]; +#endif + struct kex { u_char *session_id; size_t session_id_len; @@ -163,7 +172,7 @@ 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 */ + x25519_t c25519_client_key; /* 25519 */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ }; @@ -218,12 +227,26 @@ int kex_c25519_hash(int, const char *, const char *, const u_char *, size_t, const u_char *, const u_char *, const u_char *, size_t, u_char *, size_t *); -void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) +#ifdef WITH_OPENSSL_X25519 +typedef x25519_t *x25519_ref_t; +#define x25519_ref(KEY) (&(KEY)) +#define x25519_t_bounds(NUM) /* */ +#define x25519_t_init(KEY) ((KEY) = NULL) +#define x25519_t_fini(KEY) (EVP_PKEY_free((KEY)), ((KEY) = NULL)) +#else +typedef x25519_t x25519_ref_t; +#define x25519_ref(KEY) ((KEY)) +#define x25519_t_init(KEY) ((void)0) +#define x25519_t_bounds(NUM) \ + __attribute__((__bounded__(__minbytes__, NUM, CURVE25519_SIZE))) +#define x25519_t_fini(KEY) explicit_bzero((KEY),sizeof((KEY))) +#endif +int kexc25519_keygen(x25519_ref_t key, u_char pub[CURVE25519_SIZE]) + x25519_t_bounds(1) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], +int kexc25519_shared_key(x25519_t key, const u_char pub[CURVE25519_SIZE], struct sshbuf *out) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + x25519_t_bounds(1) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) diff --git a/kexc25519.c b/kexc25519.c index 0897b8c5..c5d9529b 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -34,6 +34,7 @@ #include <openssl/bn.h> #include <openssl/evp.h> +#include <openssl/x509.h> #include "sshbuf.h" #include "ssh2.h" @@ -50,34 +51,127 @@ extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE))); -void -kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) +int +kexc25519_keygen(x25519_ref_t key, u_char pub[CURVE25519_SIZE]) { +#ifdef WITH_OPENSSL_X25519 + int r = SSH_ERR_LIBCRYPTO_ERROR; +#ifndef HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY + unsigned char *pp = NULL; +#else + size_t pklen; +#endif + EVP_PKEY_CTX *pctx; + + x25519_t_fini(*key); + if ((pctx = EVP_PKEY_CTX_new_id(NID_X25519, NULL)) == NULL) + goto out; + if (EVP_PKEY_keygen_init(pctx) <= 0) + goto out; + if (EVP_PKEY_keygen(pctx, key) <= 0) + goto out; +#ifndef HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY + /* DER pubkey representation ends with 32-byte raw key */ + r = i2d_PUBKEY(*key, &pp); + if (r <= 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (r < CURVE25519_SIZE) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + memcpy(pub, pp + r - CURVE25519_SIZE, CURVE25519_SIZE); +#else + if (EVP_PKEY_get_raw_public_key(*key, NULL, &pklen) <= 0) + goto out; + if (pklen != CURVE25519_SIZE) + goto out; + if (EVP_PKEY_get_raw_public_key(*key, pub, &pklen) <= 0) + goto out; +#endif + r = 0; +out: +#ifndef HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY + OPENSSL_free(pp); +#endif + EVP_PKEY_CTX_free(pctx); + return r; +#else static const u_char basepoint[CURVE25519_SIZE] = {9}; arc4random_buf(key, CURVE25519_SIZE); crypto_scalarmult_curve25519(pub, key, basepoint); + return 0; +#endif } int -kexc25519_shared_key(const u_char key[CURVE25519_SIZE], +kexc25519_shared_key(x25519_t key, const u_char pub[CURVE25519_SIZE], struct sshbuf *out) { u_char shared_key[CURVE25519_SIZE]; int r; +#ifdef WITH_OPENSSL_X25519 + size_t pklen; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pubpk = NULL; +#endif /* Check for all-zero public key */ explicit_bzero(shared_key, CURVE25519_SIZE); if (timingsafe_bcmp(pub, shared_key, CURVE25519_SIZE) == 0) return SSH_ERR_KEY_INVALID_EC_VALUE; +#ifdef WITH_OPENSSL_X25519 + r = SSH_ERR_LIBCRYPTO_ERROR; + pctx = EVP_PKEY_CTX_new(key, NULL); +#ifdef HAVE_EVP_PKEY_NEW_RAW_PUBLIC_KEY + pubpk = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, pub, CURVE25519_SIZE); +#else + { + /* encode raw X25519 key as DER: */ + unsigned char buf[12+CURVE25519_SIZE] = + /* SEQUENCE */ + "\x30\x2a" + /* SEQUENCE */ + "\x30\x05" + /* OBJECT :X25519 */ + "\x06\x03\x2b\x65\x6e" + /* BITSTRING 00 <raw key> */ + "\x03\x21" "\x00"; + const unsigned char *pp = buf; + memcpy(buf + 12, pub, CURVE25519_SIZE); + pubpk = d2i_PUBKEY(NULL, &pp, 12L + CURVE25519_SIZE); + /* assert(pp == buf + 12 + CURVE25519_SIZE); */ + } +#endif + if (pubpk == NULL) + goto out; + if (EVP_PKEY_derive_init(pctx) <= 0) + goto out; + if (EVP_PKEY_derive_set_peer(pctx, pubpk) <= 0) + goto out; + if (EVP_PKEY_derive(pctx, NULL, &pklen) <= 0) + goto out; + if (pklen != CURVE25519_SIZE) + goto out; + if (EVP_PKEY_derive(pctx, shared_key, &pklen) <= 0) + goto out; +#else crypto_scalarmult_curve25519(shared_key, key, pub); +#endif #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); explicit_bzero(shared_key, CURVE25519_SIZE); +#ifdef WITH_OPENSSL_X25519 +out: + EVP_PKEY_free(pubpk); + EVP_PKEY_CTX_free(pctx); +#endif return r; } diff --git a/kexc25519c.c b/kexc25519c.c index a8d92149..acc6646b 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -52,7 +52,9 @@ kexc25519_client(struct ssh *ssh) struct kex *kex = ssh->kex; int r; - kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey); + if ((r = kexc25519_keygen(x25519_ref(kex->c25519_client_key), + kex->c25519_client_pubkey)) < 0) + goto out; #ifdef DEBUG_KEXECDH dump_digest("client private key:", kex->c25519_client_key, sizeof(kex->c25519_client_key)); @@ -61,11 +63,14 @@ kexc25519_client(struct ssh *ssh) (r = sshpkt_put_string(ssh, kex->c25519_client_pubkey, sizeof(kex->c25519_client_pubkey))) != 0 || (r = sshpkt_send(ssh)) != 0) - return r; + goto out; debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply); return 0; +out: + x25519_t_fini(kex->c25519_client_key); + return r; } static int @@ -159,7 +164,7 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); - explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); + x25519_t_fini(kex->c25519_client_key); free(server_host_key_blob); free(server_pubkey); free(signature); diff --git a/kexc25519s.c b/kexc25519s.c index 0800a7a4..312d6de9 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -58,15 +58,17 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) 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]; + x25519_t server_key; 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; + x25519_t_init(server_key); /* generate private key */ - kexc25519_keygen(server_key, server_pubkey); + if ((r = kexc25519_keygen(x25519_ref(server_key), server_pubkey)) < 0) + goto out; #ifdef DEBUG_KEXECDH dump_digest("server private key:", server_key, sizeof(server_key)); #endif @@ -149,7 +151,7 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); - explicit_bzero(server_key, sizeof(server_key)); + x25519_t_fini(server_key); free(server_host_key_blob); free(signature); free(client_pubkey); -- 2.11.0
>From f2835f9f0cc628deadce879ba491ec91f6a7b0ed Mon Sep 17 00:00:00 2001 From: "Yuriy M. Kaminskiy" <yumkam@xxxxxxxxx> Date: Sun, 17 Feb 2019 01:10:40 +0300 Subject: [PATCH] use kex/x25519 from openssl when possible --- configure.ac | 2 + kex.h | 38 ++++++++++++--- kexc25519.c | 118 +++++++++++++++++++++++++++++++++++++++++++---- kexgen.c | 2 +- kexsntrup4591761x25519.c | 11 +++-- 5 files changed, 152 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 30be6c18..faf84259 100644 --- a/configure.ac +++ b/configure.ac @@ -2701,6 +2701,8 @@ if test "x$openssl" = "xyes" ; then ) AC_CHECK_FUNCS([ \ + EVP_PKEY_get_raw_public_key \ + EVP_PKEY_new_raw_public_key \ BN_is_prime_ex \ DSA_generate_parameters_ex \ EVP_CIPHER_CTX_ctrl \ diff --git a/kex.h b/kex.h index 6d446d1c..30e59b5b 100644 --- a/kex.h +++ b/kex.h @@ -35,7 +35,11 @@ #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC +# include <openssl/evp.h> # include <openssl/ec.h> +# if defined(NID_X25519) +# define WITH_OPENSSL_X25519 +# endif # else /* OPENSSL_HAS_ECC */ # define EC_KEY void # define EC_GROUP void @@ -132,6 +136,12 @@ struct newkeys { struct ssh; +#ifdef WITH_OPENSSL_X25519 +typedef EVP_PKEY *x25519_t; +#else +typedef u_char x25519_t[CURVE25519_SIZE]; +#endif + struct kex { u_char *session_id; size_t session_id_len; @@ -167,7 +177,7 @@ 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 + KEM */ + x25519_t c25519_client_key; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */ struct sshbuf *client_pub; @@ -235,16 +245,30 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); -void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) +#ifdef WITH_OPENSSL_X25519 +typedef x25519_t *x25519_ref_t; +#define x25519_ref(KEY) (&(KEY)) +#define x25519_t_bounds(NUM) /* */ +#define x25519_t_init(KEY) ((KEY) = NULL) +#define x25519_t_fini(KEY) (EVP_PKEY_free((KEY)), ((KEY) = NULL)) +#else +typedef x25519_t x25519_ref_t; +#define x25519_ref(KEY) ((KEY)) +#define x25519_t_init(KEY) ((void)0) +#define x25519_t_bounds(NUM) \ + __attribute__((__bounded__(__minbytes__, NUM, CURVE25519_SIZE))) +#define x25519_t_fini(KEY) explicit_bzero((KEY),sizeof((KEY))) +#endif +int kexc25519_keygen(x25519_ref_t key, u_char pub[CURVE25519_SIZE]) + x25519_t_bounds(1) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], +int kexc25519_shared_key(const x25519_t key, const u_char pub[CURVE25519_SIZE], struct sshbuf *out) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + x25519_t_bounds(1) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], +int kexc25519_shared_key_ext(const x25519_t key, const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + x25519_t_bounds(1) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) diff --git a/kexc25519.c b/kexc25519.c index f13d766d..22b639b1 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -40,30 +40,122 @@ #include "ssherr.h" #include "ssh2.h" +#if defined(WITH_OPENSSL_X25519) && !(defined(HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY) && defined(HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY)) +#include <openssl/x509.h> +#endif + extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE))); -void -kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) +int +kexc25519_keygen(x25519_ref_t key, u_char pub[CURVE25519_SIZE]) { +#ifdef WITH_OPENSSL_X25519 + int r = SSH_ERR_LIBCRYPTO_ERROR; +#ifndef HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY + unsigned char *pp = NULL; +#else + size_t pklen; +#endif + EVP_PKEY_CTX *pctx; + + x25519_t_fini(*key); + if ((pctx = EVP_PKEY_CTX_new_id(NID_X25519, NULL)) == NULL) + goto out; + if (EVP_PKEY_keygen_init(pctx) <= 0) + goto out; + if (EVP_PKEY_keygen(pctx, key) <= 0) + goto out; +#ifndef HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY + /* DER pubkey representation ends with 32-byte raw key */ + r = i2d_PUBKEY(*key, &pp); + if (r <= 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (r < CURVE25519_SIZE) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + memcpy(pub, pp + r - CURVE25519_SIZE, CURVE25519_SIZE); +#else + if (EVP_PKEY_get_raw_public_key(*key, NULL, &pklen) <= 0) + goto out; + if (pklen != CURVE25519_SIZE) + goto out; + if (EVP_PKEY_get_raw_public_key(*key, pub, &pklen) <= 0) + goto out; +#endif + r = 0; +out: +#ifndef HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY + OPENSSL_free(pp); +#endif + EVP_PKEY_CTX_free(pctx); + return r; +#else static const u_char basepoint[CURVE25519_SIZE] = {9}; arc4random_buf(key, CURVE25519_SIZE); crypto_scalarmult_curve25519(pub, key, basepoint); + return 0; +#endif } int -kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], +kexc25519_shared_key_ext(const x25519_t key, const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw) { u_char shared_key[CURVE25519_SIZE]; u_char zero[CURVE25519_SIZE]; int r; +#ifdef WITH_OPENSSL_X25519 + size_t pklen; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pubpk = NULL; +#endif +#ifdef WITH_OPENSSL_X25519 + r = SSH_ERR_LIBCRYPTO_ERROR; + pctx = EVP_PKEY_CTX_new(key, NULL); +#ifdef HAVE_EVP_PKEY_NEW_RAW_PUBLIC_KEY + pubpk = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, pub, CURVE25519_SIZE); +#else + { + /* encode raw X25519 key as DER: */ + unsigned char buf[12+CURVE25519_SIZE] = + /* SEQUENCE */ + "\x30\x2a" + /* SEQUENCE */ + "\x30\x05" + /* OBJECT :X25519 */ + "\x06\x03\x2b\x65\x6e" + /* BITSTRING 00 <raw key> */ + "\x03\x21" "\x00"; + const unsigned char *pp = buf; + memcpy(buf + 12, pub, CURVE25519_SIZE); + pubpk = d2i_PUBKEY(NULL, &pp, 12L + CURVE25519_SIZE); + /* assert(pp == buf + 12 + CURVE25519_SIZE); */ + } +#endif + if (pubpk == NULL) + goto out; + if (EVP_PKEY_derive_init(pctx) <= 0) + goto out; + if (EVP_PKEY_derive_set_peer(pctx, pubpk) <= 0) + goto out; + if (EVP_PKEY_derive(pctx, NULL, &pklen) <= 0) + goto out; + if (pklen != CURVE25519_SIZE) + goto out; + if (EVP_PKEY_derive(pctx, shared_key, &pklen) <= 0) + goto out; +#else crypto_scalarmult_curve25519(shared_key, key, pub); +#endif /* Check for all-zero shared secret */ explicit_bzero(zero, CURVE25519_SIZE); @@ -78,11 +170,16 @@ kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], else r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); explicit_bzero(shared_key, CURVE25519_SIZE); +#ifdef WITH_OPENSSL_X25519 +out: + EVP_PKEY_free(pubpk); + EVP_PKEY_CTX_free(pctx); +#endif return r; } int -kexc25519_shared_key(const u_char key[CURVE25519_SIZE], +kexc25519_shared_key(const x25519_t key, const u_char pub[CURVE25519_SIZE], struct sshbuf *out) { return kexc25519_shared_key_ext(key, pub, out, 0); @@ -99,7 +196,8 @@ kex_c25519_keypair(struct kex *kex) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_reserve(buf, CURVE25519_SIZE, &cp)) != 0) goto out; - kexc25519_keygen(kex->c25519_client_key, cp); + if ((r = kexc25519_keygen(x25519_ref(kex->c25519_client_key), cp)) < 0) + goto out; #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); #endif @@ -107,6 +205,8 @@ kex_c25519_keypair(struct kex *kex) buf = NULL; out: sshbuf_free(buf); + if (r < 0) + x25519_t_fini(kex->c25519_client_key); return r; } @@ -118,9 +218,10 @@ kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf *buf = NULL; const u_char *client_pub; u_char *server_pub; - u_char server_key[CURVE25519_SIZE]; + x25519_t server_key; int r; + x25519_t_init(server_key); *server_blobp = NULL; *shared_secretp = NULL; @@ -139,7 +240,8 @@ kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob, } if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0) goto out; - kexc25519_keygen(server_key, server_pub); + if ((r = kexc25519_keygen(x25519_ref(server_key), server_pub)) < 0) + goto out; /* allocate shared secret */ if ((buf = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; @@ -156,7 +258,7 @@ kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob, server_blob = NULL; buf = NULL; out: - explicit_bzero(server_key, sizeof(server_key)); + x25519_t_fini(server_key); sshbuf_free(server_blob); sshbuf_free(buf); return r; diff --git a/kexgen.c b/kexgen.c index bb0cb5c1..21c5b2f4 100644 --- a/kexgen.c +++ b/kexgen.c @@ -214,7 +214,7 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); - explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); + x25519_t_fini(kex->c25519_client_key); explicit_bzero(kex->sntrup4591761_client_key, sizeof(kex->sntrup4591761_client_key)); sshbuf_free(server_host_key_blob); diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c index 3b9b664f..28121961 100644 --- a/kexsntrup4591761x25519.c +++ b/kexsntrup4591761x25519.c @@ -56,7 +56,8 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex) crypto_kem_sntrup4591761_PUBLICKEYBYTES); #endif cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES; - kexc25519_keygen(kex->c25519_client_key, cp); + if ((r = kexc25519_keygen(x25519_ref(kex->c25519_client_key), cp)) < 0) + goto out; #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); #endif @@ -64,6 +65,8 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex) buf = NULL; out: sshbuf_free(buf); + if (r < 0) + x25519_t_fini(kex->c25519_client_key); return r; } @@ -76,11 +79,12 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, struct sshbuf *buf = NULL; const u_char *client_pub; u_char *kem_key, *ciphertext, *server_pub; - u_char server_key[CURVE25519_SIZE]; + x25519_t server_key; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t need; int r; + x25519_t_init(server_key); *server_blobp = NULL; *shared_secretp = NULL; @@ -119,7 +123,8 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, crypto_kem_sntrup4591761_enc(ciphertext, kem_key, client_pub); /* generate ECDH key pair, store server pubkey after ciphertext */ server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; - kexc25519_keygen(server_key, server_pub); + if ((r = kexc25519_keygen(x25519_ref(server_key), server_pub)) < 0) + goto out; /* append ECDH shared key */ client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES; if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0) -- 2.11.0
_______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev