From 1e1242604eb0fd510fe93f81245c529237ffc513 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 4 Nov 2013 08:26:52 +1100 Subject: - markus@cvs.openbsd.org 2013/11/02 21:59:15 [kex.c kex.h myproposal.h ssh-keyscan.c sshconnect2.c sshd.c] use curve25519 for default key exchange (curve25519-sha256@libssh.org); initial patch from Aris Adamantiadis; ok djm@ --- kex.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'kex.h') diff --git a/kex.h b/kex.h index 9f1e1adb3..0f67f5934 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.56 2013/07/19 07:37:48 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.57 2013/11/02 21:59:15 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -43,6 +43,7 @@ #define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256" #define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384" #define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" +#define KEX_CURVE25519_SHA256 "curve25519-sha256@libssh.org" #define COMP_NONE 0 #define COMP_ZLIB 1 @@ -74,6 +75,7 @@ enum kex_exchange { KEX_DH_GEX_SHA1, KEX_DH_GEX_SHA256, KEX_ECDH_SHA2, + KEX_C25519_SHA256, KEX_MAX }; @@ -161,6 +163,8 @@ void kexgex_client(Kex *); void kexgex_server(Kex *); void kexecdh_client(Kex *); void kexecdh_server(Kex *); +void kexc25519_client(Kex *); +void kexc25519_server(Kex *); void kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, @@ -175,6 +179,19 @@ kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int, char *, int, u_char *, int, const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char **, u_int *); #endif +void +kex_c25519_hash(const EVP_MD *, char *, char *, char *, int, + char *, int, u_char *, int, const u_char *, const u_char *, + const BIGNUM *, u_char **, u_int *); + +#define CURVE25519_SIZE 32 +void kexc25519_keygen(u_char[CURVE25519_SIZE], u_char[CURVE25519_SIZE]) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +BIGNUM *kexc25519_shared_key(const u_char[CURVE25519_SIZE], + const u_char[CURVE25519_SIZE]) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); void derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); -- cgit v1.2.3 From 690d989008e18af3603a5e03f1276c9bad090370 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 8 Nov 2013 12:16:49 +1100 Subject: - dtucker@cvs.openbsd.org 2013/11/07 11:58:27 [cipher.c cipher.h kex.c kex.h mac.c mac.h servconf.c ssh.c] Output the effective values of Ciphers, MACs and KexAlgorithms when the default has not been overridden. ok markus@ --- ChangeLog | 5 +++++ cipher.c | 8 ++++---- cipher.h | 4 ++-- kex.c | 6 +++--- kex.h | 4 ++-- mac.c | 8 ++++---- mac.h | 4 ++-- servconf.c | 9 ++++++--- ssh.c | 8 ++++---- 9 files changed, 32 insertions(+), 24 deletions(-) (limited to 'kex.h') diff --git a/ChangeLog b/ChangeLog index ca7cb03e0..a7098f6d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ - dtucker@cvs.openbsd.org 2013/11/08 01:06:14 [regress/rekey.sh] Rekey less frequently during tests to speed them up + - (djm) OpenBSD CVS Sync + - dtucker@cvs.openbsd.org 2013/11/07 11:58:27 + [cipher.c cipher.h kex.c kex.h mac.c mac.h servconf.c ssh.c] + Output the effective values of Ciphers, MACs and KexAlgorithms when + the default has not been overridden. ok markus@ 20131107 - (djm) [ssh-pkcs11.c] Bring back "non-constant initialiser" fix (rev 1.5) diff --git a/cipher.c b/cipher.c index a2cbe2bea..54315f488 100644 --- a/cipher.c +++ b/cipher.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.89 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: cipher.c,v 1.90 2013/11/07 11:58:27 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -100,9 +100,9 @@ static const struct Cipher ciphers[] = { /*--*/ -/* Returns a comma-separated list of supported ciphers. */ +/* Returns a list of supported ciphers separated by the specified char. */ char * -cipher_alg_list(void) +cipher_alg_list(char sep) { char *ret = NULL; size_t nlen, rlen = 0; @@ -112,7 +112,7 @@ cipher_alg_list(void) if (c->number != SSH_CIPHER_SSH2) continue; if (ret != NULL) - ret[rlen++] = '\n'; + ret[rlen++] = sep; nlen = strlen(c->name); ret = xrealloc(ret, 1, rlen + nlen + 2); memcpy(ret + rlen, c->name, nlen + 1); diff --git a/cipher.h b/cipher.h index b878d50f4..46502348b 100644 --- a/cipher.h +++ b/cipher.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.h,v 1.40 2013/04/19 01:06:50 djm Exp $ */ +/* $OpenBSD: cipher.h,v 1.41 2013/11/07 11:58:27 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -75,7 +75,7 @@ const Cipher *cipher_by_number(int); int cipher_number(const char *); char *cipher_name(int); int ciphers_valid(const char *); -char *cipher_alg_list(void); +char *cipher_alg_list(char); void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, const u_char *, u_int, int); void cipher_crypt(CipherContext *, u_char *, const u_char *, diff --git a/kex.c b/kex.c index 07f25e2e2..0b139dc67 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.92 2013/11/02 21:59:15 markus Exp $ */ +/* $OpenBSD: kex.c,v 1.93 2013/11/07 11:58:27 dtucker Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -85,7 +85,7 @@ static const struct kexalg kexalgs[] = { }; char * -kex_alg_list(void) +kex_alg_list(char sep) { char *ret = NULL; size_t nlen, rlen = 0; @@ -93,7 +93,7 @@ kex_alg_list(void) for (k = kexalgs; k->name != NULL; k++) { if (ret != NULL) - ret[rlen++] = '\n'; + ret[rlen++] = sep; nlen = strlen(k->name); ret = xrealloc(ret, 1, rlen + nlen + 2); memcpy(ret + rlen, k->name, nlen + 1); diff --git a/kex.h b/kex.h index 0f67f5934..800a69233 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.57 2013/11/02 21:59:15 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.58 2013/11/07 11:58:27 dtucker Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -146,7 +146,7 @@ struct Kex { }; int kex_names_valid(const char *); -char *kex_alg_list(void); +char *kex_alg_list(char); Kex *kex_setup(char *[PROPOSAL_MAX]); void kex_finish(Kex *); diff --git a/mac.c b/mac.c index c4dfb501d..c71b6a741 100644 --- a/mac.c +++ b/mac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mac.c,v 1.24 2013/06/03 00:03:18 dtucker Exp $ */ +/* $OpenBSD: mac.c,v 1.25 2013/11/07 11:58:27 dtucker Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -91,9 +91,9 @@ static const struct macalg macs[] = { { NULL, 0, NULL, 0, 0, 0, 0 } }; -/* Returns a comma-separated list of supported MACs. */ +/* Returns a list of supported MACs separated by the specified char. */ char * -mac_alg_list(void) +mac_alg_list(char sep) { char *ret = NULL; size_t nlen, rlen = 0; @@ -101,7 +101,7 @@ mac_alg_list(void) for (m = macs; m->name != NULL; m++) { if (ret != NULL) - ret[rlen++] = '\n'; + ret[rlen++] = sep; nlen = strlen(m->name); ret = xrealloc(ret, 1, rlen + nlen + 2); memcpy(ret + rlen, m->name, nlen + 1); diff --git a/mac.h b/mac.h index 260798ab3..fbe18c463 100644 --- a/mac.h +++ b/mac.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mac.h,v 1.7 2013/04/19 01:06:50 djm Exp $ */ +/* $OpenBSD: mac.h,v 1.8 2013/11/07 11:58:27 dtucker Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -24,7 +24,7 @@ */ int mac_valid(const char *); -char *mac_alg_list(void); +char *mac_alg_list(char); int mac_setup(Mac *, char *); int mac_init(Mac *); u_char *mac_compute(Mac *, u_int32_t, u_char *, int); diff --git a/servconf.c b/servconf.c index 0f1bdd09a..3593223f7 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.244 2013/10/29 09:48:02 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.245 2013/11/07 11:58:27 dtucker Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -2037,8 +2037,9 @@ dump_config(ServerOptions *o) /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); dump_cfg_string(sXAuthLocation, o->xauth_location); - dump_cfg_string(sCiphers, o->ciphers); - dump_cfg_string(sMacs, o->macs); + dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : + cipher_alg_list(',')); + dump_cfg_string(sMacs, o->macs ? o->macs : mac_alg_list(',')); dump_cfg_string(sBanner, o->banner); dump_cfg_string(sForceCommand, o->adm_forced_command); dump_cfg_string(sChrootDirectory, o->chroot_directory); @@ -2050,6 +2051,8 @@ dump_config(ServerOptions *o) dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); dump_cfg_string(sHostKeyAgent, o->host_key_agent); + dump_cfg_string(sKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : + kex_alg_list(',')); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); diff --git a/ssh.c b/ssh.c index ef94591b1..e2c43634a 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.391 2013/10/25 23:04:51 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.392 2013/11/07 11:58:27 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -520,11 +520,11 @@ main(int ac, char **av) case 'Q': /* deprecated */ cp = NULL; if (strcasecmp(optarg, "cipher") == 0) - cp = cipher_alg_list(); + cp = cipher_alg_list('\n'); else if (strcasecmp(optarg, "mac") == 0) - cp = mac_alg_list(); + cp = mac_alg_list('\n'); else if (strcasecmp(optarg, "kex") == 0) - cp = kex_alg_list(); + cp = kex_alg_list('\n'); else if (strcasecmp(optarg, "key") == 0) cp = key_alg_list(); if (cp == NULL) -- cgit v1.2.3 From b3051d01e505c9c2dc00faab472a0d06fa6b0e65 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 10 Jan 2014 10:58:53 +1100 Subject: - djm@cvs.openbsd.org 2014/01/09 23:20:00 [digest.c digest.h hostfile.c kex.c kex.h kexc25519.c kexc25519c.c] [kexc25519s.c kexdh.c kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c] [kexgexs.c key.c key.h roaming_client.c roaming_common.c schnorr.c] [schnorr.h ssh-dss.c ssh-ecdsa.c ssh-rsa.c sshconnect2.c] Introduce digest API and use it to perform all hashing operations rather than calling OpenSSL EVP_Digest* directly. Will make it easier to build a reduced-feature OpenSSH without OpenSSL in future; feedback, ok markus@ --- ChangeLog | 9 ++++ Makefile.in | 4 +- digest.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ digest.h | 55 +++++++++++++++++++++ hostfile.c | 3 +- kex.c | 94 ++++++++++++++++++++--------------- kex.h | 10 ++-- kexc25519.c | 17 +++---- kexc25519c.c | 4 +- kexc25519s.c | 4 +- kexdh.c | 17 +++---- kexecdh.c | 18 +++---- kexecdhc.c | 4 +- kexecdhs.c | 4 +- kexgex.c | 24 ++++----- kexgexc.c | 4 +- kexgexs.c | 4 +- key.c | 42 ++++++++-------- key.h | 4 +- roaming_client.c | 14 +++--- roaming_common.c | 14 +++--- schnorr.c | 57 +++++++++------------ schnorr.h | 8 +-- ssh-dss.c | 31 ++++++------ ssh-ecdsa.c | 42 ++++++++++------ ssh-rsa.c | 54 +++++++++++--------- sshconnect2.c | 4 +- 27 files changed, 458 insertions(+), 235 deletions(-) create mode 100644 digest.c create mode 100644 digest.h (limited to 'kex.h') diff --git a/ChangeLog b/ChangeLog index df1d5ea6a..a1d37bc25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,15 @@ with the year, and rearrange a comparison to avoid a potentional signed arithmetic overflow that would give the wrong result. ok djm@ + - djm@cvs.openbsd.org 2014/01/09 23:20:00 + [digest.c digest.h hostfile.c kex.c kex.h kexc25519.c kexc25519c.c] + [kexc25519s.c kexdh.c kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c] + [kexgexs.c key.c key.h roaming_client.c roaming_common.c schnorr.c] + [schnorr.h ssh-dss.c ssh-ecdsa.c ssh-rsa.c sshconnect2.c] + Introduce digest API and use it to perform all hashing operations + rather than calling OpenSSL EVP_Digest* directly. Will make it easier + to build a reduced-feature OpenSSH without OpenSSL in future; + feedback, ok markus@ 20140108 - (djm) [regress/.cvsignore] Ignore regress test droppings; ok dtucker@ diff --git a/Makefile.in b/Makefile.in index e789b476a..4a930c665 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.348 2013/12/08 04:53:28 djm Exp $ +# $Id: Makefile.in,v 1.349 2014/01/09 23:58:53 djm Exp $ # uncomment if you run a non bourne compatable shell. Ie. csh #SHELL = @SH@ @@ -75,7 +75,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ - ssh-ed25519.o \ + ssh-ed25519.o digest.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ diff --git a/digest.c b/digest.c new file mode 100644 index 000000000..59a8ffe0d --- /dev/null +++ b/digest.c @@ -0,0 +1,148 @@ +/* $OpenBSD: digest.c,v 1.1 2014/01/09 23:20:00 djm Exp $ */ +/* + * Copyright (c) 2013 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include +#include +#include +#include + +#include /* for buffer.h */ +#include /* for buffer.h */ +#include + +#include "buffer.h" +#include "digest.h" + +struct ssh_digest_ctx { + int alg; + EVP_MD_CTX mdctx; +}; + +struct ssh_digest { + int id; + const char *name; + size_t digest_len; + const EVP_MD *(*mdfunc)(void); +}; + +/* NB. Indexed directly by algorithm number */ +const struct ssh_digest digests[] = { + { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, + { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 }, + { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, +#ifdef HAVE_EVP_SHA256 /* XXX replace with local if missing */ + { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, + { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, + { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, +#endif + { -1, NULL, 0, NULL }, +}; + +static const struct ssh_digest * +ssh_digest_by_alg(int alg) +{ + if (alg < 0 || alg >= SSH_DIGEST_MAX) + return NULL; + if (digests[alg].id != alg) /* sanity */ + return NULL; + return &(digests[alg]); +} + +size_t +ssh_digest_bytes(int alg) +{ + const struct ssh_digest *digest = ssh_digest_by_alg(alg); + + return digest == NULL ? 0 : digest->digest_len; +} + +struct ssh_digest_ctx * +ssh_digest_start(int alg) +{ + const struct ssh_digest *digest = ssh_digest_by_alg(alg); + struct ssh_digest_ctx *ret; + + if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL)) + return NULL; + ret->alg = alg; + EVP_MD_CTX_init(&ret->mdctx); + if (EVP_DigestInit_ex(&ret->mdctx, digest->mdfunc(), NULL) != 1) { + free(ret); + return NULL; + } + return ret; +} + +int +ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) +{ + if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) + return -1; + return 0; +} + +int +ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) +{ + return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); +} + +int +ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) +{ + const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); + u_int l = dlen; + + if (dlen > UINT_MAX) + return -1; + if (dlen < digest->digest_len) /* No truncation allowed */ + return -1; + if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) + return -1; + if (l != digest->digest_len) /* sanity */ + return -1; + return 0; +} + +void +ssh_digest_free(struct ssh_digest_ctx *ctx) +{ + EVP_MD_CTX_cleanup(&ctx->mdctx); + memset(ctx, 0, sizeof(*ctx)); +} + +int +ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) +{ + struct ssh_digest_ctx *ctx = ssh_digest_start(alg); + + if (ctx == NULL) + return -1; + if (ssh_digest_update(ctx, m, mlen) != 0 || + ssh_digest_final(ctx, d, dlen) != 0) + return -1; + ssh_digest_free(ctx); + return 0; +} + +int +ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) +{ + return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); +} diff --git a/digest.h b/digest.h new file mode 100644 index 000000000..faefda3f5 --- /dev/null +++ b/digest.h @@ -0,0 +1,55 @@ +/* $OpenBSD: digest.h,v 1.1 2014/01/09 23:20:00 djm Exp $ */ +/* + * Copyright (c) 2013 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _DIGEST_H +#define _DIGEST_H + +/* Maximum digest output length */ +#define SSH_DIGEST_MAX_LENGTH 64 + +/* Digest algorithms */ +#define SSH_DIGEST_MD5 0 +#define SSH_DIGEST_RIPEMD160 1 +#define SSH_DIGEST_SHA1 2 +#define SSH_DIGEST_SHA256 3 +#define SSH_DIGEST_SHA384 4 +#define SSH_DIGEST_SHA512 5 +#define SSH_DIGEST_MAX 6 + +/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ +size_t ssh_digest_bytes(int alg); + +/* One-shot API */ +int ssh_digest_memory(int alg, const void *m, size_t mlen, + u_char *d, size_t dlen) + __attribute__((__bounded__(__buffer__, 2, 3))) + __attribute__((__bounded__(__buffer__, 4, 5))); +int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) + __attribute__((__bounded__(__buffer__, 3, 4))); + +/* Update API */ +struct ssh_digest_ctx; +struct ssh_digest_ctx *ssh_digest_start(int alg); +int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) + __attribute__((__bounded__(__buffer__, 2, 3))); +int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b); +int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) + __attribute__((__bounded__(__buffer__, 2, 3))); +void ssh_digest_free(struct ssh_digest_ctx *ctx); + +#endif /* _DIGEST_H */ + diff --git a/hostfile.c b/hostfile.c index 2ff4c48b4..2778fb5df 100644 --- a/hostfile.c +++ b/hostfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.52 2013/07/12 00:19:58 djm Exp $ */ +/* $OpenBSD: hostfile.c,v 1.53 2014/01/09 23:20:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -57,6 +57,7 @@ #include "hostfile.h" #include "log.h" #include "misc.h" +#include "digest.h" struct hostkeys { struct hostkey_entry *entries; diff --git a/kex.c b/kex.c index b38bae0f0..dbb1a9816 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.93 2013/11/07 11:58:27 dtucker Exp $ */ +/* $OpenBSD: kex.c,v 1.94 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -49,6 +49,7 @@ #include "dispatch.h" #include "monitor.h" #include "roaming.h" +#include "digest.h" #if OPENSSL_VERSION_NUMBER >= 0x00907000L # if defined(HAVE_EVP_SHA256) @@ -66,26 +67,30 @@ struct kexalg { char *name; int type; int ec_nid; - const EVP_MD *(*mdfunc)(void); + int hash_alg; }; static const struct kexalg kexalgs[] = { - { KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, - { KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 }, - { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 }, + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, + { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, + { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 - { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 }, + { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, #endif #ifdef OPENSSL_HAS_ECC - { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 }, - { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, + { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, + NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, + { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, + SSH_DIGEST_SHA384 }, # ifdef OPENSSL_HAS_NISTP521 - { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, + { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, + SSH_DIGEST_SHA512 }, # endif #endif + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 - { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, EVP_sha256 }, + { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, #endif - { NULL, -1, -1, NULL}, + { NULL, -1, -1, -1}, }; char * @@ -406,7 +411,7 @@ choose_kex(Kex *k, char *client, char *server) if ((kexalg = kex_alg_by_name(k->name)) == NULL) fatal("unsupported kex alg %s", k->name); k->kex_type = kexalg->type; - k->evp_md = kexalg->mdfunc(); + k->hash_alg = kexalg->hash_alg; k->ec_nid = kexalg->ec_nid; } @@ -532,27 +537,31 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, BIGNUM *shared_secret) { Buffer b; - EVP_MD_CTX md; + struct ssh_digest_ctx *hashctx; char c = id; u_int have; - int mdsz; + size_t mdsz; u_char *digest; - if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0) - fatal("bad kex md size %d", mdsz); + if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) + fatal("bad kex md size %zu", mdsz); digest = xmalloc(roundup(need, mdsz)); buffer_init(&b); buffer_put_bignum2(&b, shared_secret); /* K1 = HASH(K || H || "A" || session_id) */ - EVP_DigestInit(&md, kex->evp_md); - if (!(datafellows & SSH_BUG_DERIVEKEY)) - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestUpdate(&md, hash, hashlen); - EVP_DigestUpdate(&md, &c, 1); - EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); - EVP_DigestFinal(&md, digest, NULL); + if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) + fatal("%s: ssh_digest_start failed", __func__); + if (ssh_digest_update_buffer(hashctx, &b) != 0 || + ssh_digest_update(hashctx, hash, hashlen) != 0 || + ssh_digest_update(hashctx, &c, 1) != 0 || + ssh_digest_update(hashctx, kex->session_id, + kex->session_id_len) != 0) + fatal("%s: ssh_digest_update failed", __func__); + if (ssh_digest_final(hashctx, digest, mdsz) != 0) + fatal("%s: ssh_digest_final failed", __func__); + ssh_digest_free(hashctx); /* * expand key: @@ -560,12 +569,15 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, * Key = K1 || K2 || ... || Kn */ for (have = mdsz; need > have; have += mdsz) { - EVP_DigestInit(&md, kex->evp_md); - if (!(datafellows & SSH_BUG_DERIVEKEY)) - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestUpdate(&md, hash, hashlen); - EVP_DigestUpdate(&md, digest, have); - EVP_DigestFinal(&md, digest + have, NULL); + if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) + fatal("%s: ssh_digest_start failed", __func__); + if (ssh_digest_update_buffer(hashctx, &b) != 0 || + ssh_digest_update(hashctx, hash, hashlen) != 0 || + ssh_digest_update(hashctx, digest, have) != 0) + fatal("%s: ssh_digest_update failed", __func__); + if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) + fatal("%s: ssh_digest_final failed", __func__); + ssh_digest_free(hashctx); } buffer_free(&b); #ifdef DEBUG_KEX @@ -615,33 +627,33 @@ void derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, u_int8_t cookie[8], u_int8_t id[16]) { - const EVP_MD *evp_md = EVP_md5(); - EVP_MD_CTX md; - u_int8_t nbuf[2048], obuf[EVP_MAX_MD_SIZE]; + u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; int len; + struct ssh_digest_ctx *hashctx; - EVP_DigestInit(&md, evp_md); + if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) + fatal("%s: ssh_digest_start", __func__); len = BN_num_bytes(host_modulus); if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) fatal("%s: bad host modulus (len %d)", __func__, len); BN_bn2bin(host_modulus, nbuf); - EVP_DigestUpdate(&md, nbuf, len); + if (ssh_digest_update(hashctx, nbuf, len) != 0) + fatal("%s: ssh_digest_update failed", __func__); len = BN_num_bytes(server_modulus); if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) fatal("%s: bad server modulus (len %d)", __func__, len); BN_bn2bin(server_modulus, nbuf); - EVP_DigestUpdate(&md, nbuf, len); - - EVP_DigestUpdate(&md, cookie, 8); - - EVP_DigestFinal(&md, obuf, NULL); - memcpy(id, obuf, 16); + if (ssh_digest_update(hashctx, nbuf, len) != 0 || + ssh_digest_update(hashctx, cookie, 8) != 0) + fatal("%s: ssh_digest_update failed", __func__); + if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) + fatal("%s: ssh_digest_final failed", __func__); + memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); memset(nbuf, 0, sizeof(nbuf)); memset(obuf, 0, sizeof(obuf)); - memset(&md, 0, sizeof(md)); } #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) diff --git a/kex.h b/kex.h index 800a69233..fbe4940e8 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.58 2013/11/07 11:58:27 dtucker Exp $ */ +/* $OpenBSD: kex.h,v 1.59 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -133,7 +133,7 @@ struct Kex { Buffer peer; sig_atomic_t done; int flags; - const EVP_MD *evp_md; + int hash_alg; int ec_nid; char *client_version_string; char *server_version_string; @@ -170,17 +170,17 @@ void kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); void -kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *, +kexgex_hash(int, char *, char *, char *, int, char *, int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); #ifdef OPENSSL_HAS_ECC void -kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int, +kex_ecdh_hash(int, const EC_GROUP *, char *, char *, char *, int, char *, int, u_char *, int, const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char **, u_int *); #endif void -kex_c25519_hash(const EVP_MD *, char *, char *, char *, int, +kex_c25519_hash(int, char *, char *, char *, int, char *, int, u_char *, int, const u_char *, const u_char *, const BIGNUM *, u_char **, u_int *); diff --git a/kexc25519.c b/kexc25519.c index 348a7d50d..8dd363991 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.2 2013/11/02 22:02:14 markus Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.3 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -41,6 +41,7 @@ #include "cipher.h" #include "kex.h" #include "log.h" +#include "digest.h" extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) @@ -78,7 +79,7 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE], void kex_c25519_hash( - const EVP_MD *evp_md, + int hash_alg, char *client_version_string, char *server_version_string, char *ckexinit, int ckexinitlen, @@ -90,8 +91,7 @@ kex_c25519_hash( u_char **hash, u_int *hashlen) { Buffer b; - EVP_MD_CTX md; - static u_char digest[EVP_MAX_MD_SIZE]; + static u_char digest[SSH_DIGEST_MAX_LENGTH]; buffer_init(&b); buffer_put_cstring(&b, client_version_string); @@ -113,15 +113,14 @@ kex_c25519_hash( #ifdef DEBUG_KEX buffer_dump(&b); #endif - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&md, digest, NULL); + if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) + fatal("%s: digest_buffer failed", __func__); buffer_free(&b); #ifdef DEBUG_KEX - dump_digest("hash", digest, EVP_MD_size(evp_md)); + dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); #endif *hash = digest; - *hashlen = EVP_MD_size(evp_md); + *hashlen = ssh_digest_bytes(hash_alg); } diff --git a/kexc25519c.c b/kexc25519c.c index f741566cc..4655c2542 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.2 2013/11/02 22:02:14 markus Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.3 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -97,7 +97,7 @@ kexc25519_client(Kex *kex) /* calc and verify H */ kex_c25519_hash( - kex->evp_md, + kex->hash_alg, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->my), buffer_len(&kex->my), diff --git a/kexc25519s.c b/kexc25519s.c index 784841b82..dc4f56c80 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.2 2013/11/02 22:02:14 markus Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.3 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -81,7 +81,7 @@ kexc25519_server(Kex *kex) /* calc H */ key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); kex_c25519_hash( - kex->evp_md, + kex->hash_alg, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), diff --git a/kexdh.c b/kexdh.c index 56e22f5bc..e7cdadc90 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.23 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: kexdh.c,v 1.24 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -36,6 +36,8 @@ #include "key.h" #include "cipher.h" #include "kex.h" +#include "digest.h" +#include "log.h" void kex_dh_hash( @@ -50,9 +52,7 @@ kex_dh_hash( u_char **hash, u_int *hashlen) { Buffer b; - static u_char digest[EVP_MAX_MD_SIZE]; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; + static u_char digest[SSH_DIGEST_MAX_LENGTH]; buffer_init(&b); buffer_put_cstring(&b, client_version_string); @@ -74,15 +74,14 @@ kex_dh_hash( #ifdef DEBUG_KEX buffer_dump(&b); #endif - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&md, digest, NULL); + if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, digest, sizeof(digest)) != 0) + fatal("%s: ssh_digest_buffer failed", __func__); buffer_free(&b); #ifdef DEBUG_KEX - dump_digest("hash", digest, EVP_MD_size(evp_md)); + dump_digest("hash", digest, ssh_digest_bytes(SSH_DIGEST_SHA1)); #endif *hash = digest; - *hashlen = EVP_MD_size(evp_md); + *hashlen = ssh_digest_bytes(SSH_DIGEST_SHA1); } diff --git a/kexecdh.c b/kexecdh.c index c948fe20a..c52c5e234 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.4 2013/04/19 01:06:50 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.5 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -44,10 +44,11 @@ #include "cipher.h" #include "kex.h" #include "log.h" +#include "digest.h" void kex_ecdh_hash( - const EVP_MD *evp_md, + int hash_alg, const EC_GROUP *ec_group, char *client_version_string, char *server_version_string, @@ -60,8 +61,7 @@ kex_ecdh_hash( u_char **hash, u_int *hashlen) { Buffer b; - EVP_MD_CTX md; - static u_char digest[EVP_MAX_MD_SIZE]; + static u_char digest[SSH_DIGEST_MAX_LENGTH]; buffer_init(&b); buffer_put_cstring(&b, client_version_string); @@ -83,17 +83,15 @@ kex_ecdh_hash( #ifdef DEBUG_KEX buffer_dump(&b); #endif - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&md, digest, NULL); + if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) + fatal("%s: ssh_digest_buffer failed", __func__); buffer_free(&b); #ifdef DEBUG_KEX - dump_digest("hash", digest, EVP_MD_size(evp_md)); + dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); #endif *hash = digest; - *hashlen = EVP_MD_size(evp_md); + *hashlen = ssh_digest_bytes(hash_alg); } - #endif /* OPENSSL_HAS_ECC */ diff --git a/kexecdhc.c b/kexecdhc.c index 6193836c7..fc62cec55 100644 --- a/kexecdhc.c +++ b/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.4 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kexecdhc.c,v 1.5 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -124,7 +124,7 @@ kexecdh_client(Kex *kex) /* calc and verify H */ kex_ecdh_hash( - kex->evp_md, + kex->hash_alg, group, kex->client_version_string, kex->server_version_string, diff --git a/kexecdhs.c b/kexecdhs.c index 431fd2c2c..d1dd8c7fb 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.7 2013/11/02 22:24:24 markus Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.8 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -109,7 +109,7 @@ kexecdh_server(Kex *kex) /* calc H */ key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); kex_ecdh_hash( - kex->evp_md, + kex->hash_alg, group, kex->client_version_string, kex->server_version_string, diff --git a/kexgex.c b/kexgex.c index b60ab5c53..c2e6bc16d 100644 --- a/kexgex.c +++ b/kexgex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgex.c,v 1.27 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: kexgex.c,v 1.28 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -36,10 +36,12 @@ #include "cipher.h" #include "kex.h" #include "ssh2.h" +#include "digest.h" +#include "log.h" void kexgex_hash( - const EVP_MD *evp_md, + int hash_alg, char *client_version_string, char *server_version_string, char *ckexinit, int ckexinitlen, @@ -52,8 +54,7 @@ kexgex_hash( u_char **hash, u_int *hashlen) { Buffer b; - static u_char digest[EVP_MAX_MD_SIZE]; - EVP_MD_CTX md; + static u_char digest[SSH_DIGEST_MAX_LENGTH]; buffer_init(&b); buffer_put_cstring(&b, client_version_string); @@ -84,15 +85,14 @@ kexgex_hash( #ifdef DEBUG_KEXDH buffer_dump(&b); #endif - - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&md, digest, NULL); + if (ssh_digest_buffer(hash_alg, &b, digest, sizeof(digest)) != 0) + fatal("%s: ssh_digest_buffer failed", __func__); buffer_free(&b); - *hash = digest; - *hashlen = EVP_MD_size(evp_md); -#ifdef DEBUG_KEXDH - dump_digest("hash", digest, *hashlen); + +#ifdef DEBUG_KEX + dump_digest("hash", digest, ssh_digest_bytes(hash_alg)); #endif + *hash = digest; + *hashlen = ssh_digest_bytes(hash_alg); } diff --git a/kexgexc.c b/kexgexc.c index 5a3be2005..ca771edfe 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.14 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -170,7 +170,7 @@ kexgex_client(Kex *kex) /* calc and verify H */ kexgex_hash( - kex->evp_md, + kex->hash_alg, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->my), buffer_len(&kex->my), diff --git a/kexgexs.c b/kexgexs.c index 4e473fc73..90853403e 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.16 2013/07/19 07:37:48 markus Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.17 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -160,7 +160,7 @@ kexgex_server(Kex *kex) /* calc H */ kexgex_hash( - kex->evp_md, + kex->hash_alg, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), diff --git a/key.c b/key.c index b0bb46f3d..914233808 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.114 2013/12/29 04:20:04 djm Exp $ */ +/* $OpenBSD: key.c,v 1.115 2014/01/09 23:20:00 djm Exp $ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -56,6 +56,7 @@ #include "log.h" #include "misc.h" #include "ssh2.h" +#include "digest.h" static int to_blob(const Key *, u_char **, u_int *, int); static Key *key_from_blob2(const u_char *, u_int, int); @@ -358,30 +359,26 @@ u_char* key_fingerprint_raw(const Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) { - const EVP_MD *md = NULL; - EVP_MD_CTX ctx; u_char *blob = NULL; u_char *retval = NULL; u_int len = 0; - int nlen, elen; + int nlen, elen, hash_alg = -1; *dgst_raw_length = 0; + /* XXX switch to DIGEST_* directly? */ switch (dgst_type) { case SSH_FP_MD5: - md = EVP_md5(); + hash_alg = SSH_DIGEST_MD5; break; case SSH_FP_SHA1: - md = EVP_sha1(); + hash_alg = SSH_DIGEST_SHA1; break; -#ifdef HAVE_EVP_SHA256 case SSH_FP_SHA256: - md = EVP_sha256(); + hash_alg = SSH_DIGEST_SHA256; break; -#endif default: - fatal("key_fingerprint_raw: bad digest type %d", - dgst_type); + fatal("%s: bad digest type %d", __func__, dgst_type); } switch (k->type) { case KEY_RSA1: @@ -410,18 +407,19 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type, case KEY_UNSPEC: return retval; default: - fatal("key_fingerprint_raw: bad key type %d", k->type); + fatal("%s: bad key type %d", __func__, k->type); break; } if (blob != NULL) { - retval = xmalloc(EVP_MAX_MD_SIZE); - EVP_DigestInit(&ctx, md); - EVP_DigestUpdate(&ctx, blob, len); - EVP_DigestFinal(&ctx, retval, dgst_raw_length); + retval = xmalloc(SSH_DIGEST_MAX_LENGTH); + if ((ssh_digest_memory(hash_alg, blob, len, + retval, SSH_DIGEST_MAX_LENGTH)) != 0) + fatal("%s: digest_memory failed", __func__); memset(blob, 0, len); free(blob); + *dgst_raw_length = ssh_digest_bytes(hash_alg); } else { - fatal("key_fingerprint_raw: blob is null"); + fatal("%s: blob is null", __func__); } return retval; } @@ -2211,8 +2209,8 @@ key_curve_nid_to_name(int nid) } #ifdef OPENSSL_HAS_ECC -const EVP_MD * -key_ec_nid_to_evpmd(int nid) +int +key_ec_nid_to_hash_alg(int nid) { int kbits = key_curve_nid_to_bits(nid); @@ -2220,11 +2218,11 @@ key_ec_nid_to_evpmd(int nid) fatal("%s: invalid nid %d", __func__, nid); /* RFC5656 section 6.2.1 */ if (kbits <= 256) - return EVP_sha256(); + return SSH_DIGEST_SHA256; else if (kbits <= 384) - return EVP_sha384(); + return SSH_DIGEST_SHA384; else - return EVP_sha512(); + return SSH_DIGEST_SHA512; } int diff --git a/key.h b/key.h index 6a049d277..d8ad13d08 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.40 2013/12/06 13:39:49 markus Exp $ */ +/* $OpenBSD: key.h,v 1.41 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -131,7 +131,7 @@ u_int key_curve_nid_to_bits(int); int key_ecdsa_bits_to_nid(int); #ifdef OPENSSL_HAS_ECC int key_ecdsa_key_to_nid(EC_KEY *); -const EVP_MD *key_ec_nid_to_evpmd(int nid); +int key_ec_nid_to_hash_alg(int nid); int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); int key_ec_validate_private(const EC_KEY *); #endif diff --git a/roaming_client.c b/roaming_client.c index 2fb623121..de049cdc1 100644 --- a/roaming_client.c +++ b/roaming_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roaming_client.c,v 1.6 2013/10/16 02:31:46 djm Exp $ */ +/* $OpenBSD: roaming_client.c,v 1.7 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2004-2009 AppGate Network Security AB * @@ -48,6 +48,7 @@ #include "roaming.h" #include "ssh2.h" #include "sshconnect.h" +#include "digest.h" /* import */ extern Options options; @@ -90,10 +91,8 @@ request_roaming(void) static void roaming_auth_required(void) { - u_char digest[SHA_DIGEST_LENGTH]; - EVP_MD_CTX md; + u_char digest[SSH_DIGEST_MAX_LENGTH]; Buffer b; - const EVP_MD *evp_md = EVP_sha1(); u_int64_t chall, oldchall; chall = packet_get_int64(); @@ -107,14 +106,13 @@ roaming_auth_required(void) buffer_init(&b); buffer_put_int64(&b, cookie); buffer_put_int64(&b, chall); - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&md, digest, NULL); + if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, digest, sizeof(digest)) != 0) + fatal("%s: ssh_digest_buffer failed", __func__); buffer_free(&b); packet_start(SSH2_MSG_KEX_ROAMING_AUTH); packet_put_int64(key1 ^ get_recv_bytes()); - packet_put_raw(digest, sizeof(digest)); + packet_put_raw(digest, ssh_digest_bytes(SSH_DIGEST_SHA1)); packet_send(); oldkey1 = key1; diff --git a/roaming_common.c b/roaming_common.c index 86b3372ef..787bef04a 100644 --- a/roaming_common.c +++ b/roaming_common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roaming_common.c,v 1.11 2013/11/03 10:37:19 djm Exp $ */ +/* $OpenBSD: roaming_common.c,v 1.12 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2004-2009 AppGate Network Security AB * @@ -36,6 +36,7 @@ #include "cipher.h" #include "buffer.h" #include "roaming.h" +#include "digest.h" static size_t out_buf_size = 0; static char *out_buf = NULL; @@ -225,9 +226,7 @@ resend_bytes(int fd, u_int64_t *offset) void calculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge) { - const EVP_MD *md = EVP_sha1(); - EVP_MD_CTX ctx; - u_char hash[EVP_MAX_MD_SIZE]; + u_char hash[SSH_DIGEST_MAX_LENGTH]; Buffer b; buffer_init(&b); @@ -235,12 +234,11 @@ calculate_new_key(u_int64_t *key, u_int64_t cookie, u_int64_t challenge) buffer_put_int64(&b, cookie); buffer_put_int64(&b, challenge); - EVP_DigestInit(&ctx, md); - EVP_DigestUpdate(&ctx, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestFinal(&ctx, hash, NULL); + if (ssh_digest_buffer(SSH_DIGEST_SHA1, &b, hash, sizeof(hash)) != 0) + fatal("%s: digest_buffer failed", __func__); buffer_clear(&b); - buffer_append(&b, hash, EVP_MD_size(md)); + buffer_append(&b, hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); *key = buffer_get_int64(&b); buffer_free(&b); } diff --git a/schnorr.c b/schnorr.c index 93822fed4..aa3a57770 100644 --- a/schnorr.c +++ b/schnorr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: schnorr.c,v 1.8 2013/11/08 00:39:15 djm Exp $ */ +/* $OpenBSD: schnorr.c,v 1.9 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2008 Damien Miller. All rights reserved. * @@ -41,6 +41,7 @@ #include "log.h" #include "schnorr.h" +#include "digest.h" #include "openbsd-compat/openssl-compat.h" @@ -57,12 +58,12 @@ /* * Calculate hash component of Schnorr signature H(g || g^v || g^x || id) - * using the hash function defined by "evp_md". Returns signature as + * using the hash function defined by "hash_alg". Returns signature as * bignum or NULL on error. */ static BIGNUM * schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, - const EVP_MD *evp_md, const BIGNUM *g_v, const BIGNUM *g_x, + int hash_alg, const BIGNUM *g_v, const BIGNUM *g_x, const u_char *id, u_int idlen) { u_char *digest; @@ -88,7 +89,7 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), "%s: hashblob", __func__)); - if (hash_buffer(buffer_ptr(&b), buffer_len(&b), evp_md, + if (hash_buffer(buffer_ptr(&b), buffer_len(&b), hash_alg, &digest, &digest_len) != 0) { error("%s: hash_buffer", __func__); goto out; @@ -113,7 +114,7 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, /* * Generate Schnorr signature to prove knowledge of private value 'x' used * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' - * using the hash function "evp_md". + * using the hash function "hash_alg". * 'idlen' bytes from 'id' will be included in the signature hash as an anti- * replay salt. * @@ -123,7 +124,7 @@ schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, */ int schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - const EVP_MD *evp_md, const BIGNUM *x, const BIGNUM *g_x, + int hash_alg, const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p) { int success = -1; @@ -173,7 +174,7 @@ schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); /* h = H(g || g^v || g^x || id) */ - if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, g_v, g_x, + if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, g_v, g_x, id, idlen)) == NULL) { error("%s: schnorr_hash failed", __func__); goto out; @@ -223,7 +224,7 @@ schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, Buffer b; BIGNUM *r, *e; - if (schnorr_sign(grp_p, grp_q, grp_g, EVP_sha256(), + if (schnorr_sign(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256, x, g_x, id, idlen, &r, &e) != 0) return -1; @@ -248,13 +249,13 @@ schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, /* * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and - * 'grp_g' using hash "evp_md". + * 'grp_g' using hash "hash_alg". * Signature hash will be salted with 'idlen' bytes from 'id'. * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. */ int schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - const EVP_MD *evp_md, const BIGNUM *g_x, const u_char *id, u_int idlen, + int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen, const BIGNUM *r, const BIGNUM *e) { int success = -1; @@ -302,7 +303,7 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__)); /* h = H(g || g^v || g^x || id) */ - if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, e, g_x, + if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, e, g_x, id, idlen)) == NULL) { error("%s: schnorr_hash failed", __func__); goto out; @@ -385,7 +386,7 @@ schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, goto out; } - ret = schnorr_verify(grp_p, grp_q, grp_g, EVP_sha256(), + ret = schnorr_verify(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256, g_x, id, idlen, r, e); out: BN_clear_free(e); @@ -443,43 +444,33 @@ bn_rand_range_gt_one(const BIGNUM *high) return NULL; } +/* XXX convert all callers of this to use ssh_digest_memory() directly */ /* * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success, * with digest via 'digestp' (caller to free) and length via 'lenp'. * Returns -1 on failure. */ int -hash_buffer(const u_char *buf, u_int len, const EVP_MD *md, +hash_buffer(const u_char *buf, u_int len, int hash_alg, u_char **digestp, u_int *lenp) { - u_char digest[EVP_MAX_MD_SIZE]; - u_int digest_len; - EVP_MD_CTX evp_md_ctx; - int success = -1; + u_char digest[SSH_DIGEST_MAX_LENGTH]; + u_int digest_len = ssh_digest_bytes(hash_alg); - EVP_MD_CTX_init(&evp_md_ctx); - - if (EVP_DigestInit_ex(&evp_md_ctx, md, NULL) != 1) { - error("%s: EVP_DigestInit_ex", __func__); - goto out; - } - if (EVP_DigestUpdate(&evp_md_ctx, buf, len) != 1) { - error("%s: EVP_DigestUpdate", __func__); - goto out; + if (digest_len == 0) { + error("%s: invalid hash", __func__); + return -1; } - if (EVP_DigestFinal_ex(&evp_md_ctx, digest, &digest_len) != 1) { - error("%s: EVP_DigestFinal_ex", __func__); - goto out; + if (ssh_digest_memory(hash_alg, buf, len, digest, digest_len) != 0) { + error("%s: digest_memory failed", __func__); + return -1; } *digestp = xmalloc(digest_len); *lenp = digest_len; memcpy(*digestp, digest, *lenp); - success = 0; - out: - EVP_MD_CTX_cleanup(&evp_md_ctx); bzero(digest, sizeof(digest)); digest_len = 0; - return success; + return 0; } /* print formatted string followed by bignum */ diff --git a/schnorr.h b/schnorr.h index 9730b47ce..e2405c102 100644 --- a/schnorr.h +++ b/schnorr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: schnorr.h,v 1.1 2009/03/05 07:18:19 djm Exp $ */ +/* $OpenBSD: schnorr.h,v 1.2 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2009 Damien Miller. All rights reserved. * @@ -27,7 +27,7 @@ struct modp_group { }; BIGNUM *bn_rand_range_gt_one(const BIGNUM *high); -int hash_buffer(const u_char *, u_int, const EVP_MD *, u_char **, u_int *); +int hash_buffer(const u_char *, u_int, int, u_char **, u_int *); void debug3_bn(const BIGNUM *, const char *, ...) __attribute__((__nonnull__ (2))) __attribute__((format(printf, 2, 3))); @@ -40,7 +40,7 @@ void modp_group_free(struct modp_group *); /* Signature and verification functions */ int schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - const EVP_MD *evp_md, const BIGNUM *x, const BIGNUM *g_x, + int hash_alg, const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p); int schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, @@ -48,7 +48,7 @@ schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, u_char **sig, u_int *siglen); int schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - const EVP_MD *evp_md, const BIGNUM *g_x, const u_char *id, u_int idlen, + int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen, const BIGNUM *r, const BIGNUM *e); int schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, diff --git a/ssh-dss.c b/ssh-dss.c index a6292aa84..7b897475c 100644 --- a/ssh-dss.c +++ b/ssh-dss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.c,v 1.29 2013/12/27 22:30:17 djm Exp $ */ +/* $OpenBSD: ssh-dss.c,v 1.30 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -38,6 +38,7 @@ #include "compat.h" #include "log.h" #include "key.h" +#include "digest.h" #define INTBLOB_LEN 20 #define SIGBLOB_LEN (2*INTBLOB_LEN) @@ -47,10 +48,8 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { DSA_SIG *sig; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN]; - u_int rlen, slen, len, dlen; + u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; + u_int rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); Buffer b; if (key == NULL || key_type_plain(key->type) != KEY_DSA || @@ -59,9 +58,11 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp, return -1; } - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); + if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, + digest, sizeof(digest)) != 0) { + error("%s: ssh_digest_memory failed", __func__); + return -1; + } sig = DSA_do_sign(digest, dlen, key->dsa); memset(digest, 'd', sizeof(digest)); @@ -111,10 +112,8 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { DSA_SIG *sig; - const EVP_MD *evp_md = EVP_sha1(); - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE], *sigblob; - u_int len, dlen; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; + u_int len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); int rlen, ret; Buffer b; @@ -173,9 +172,11 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, free(sigblob); /* sha1 the data */ - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); + if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, + digest, sizeof(digest)) != 0) { + error("%s: digest_memory failed", __func__); + return -1; + } ret = DSA_do_verify(digest, dlen, sig, key->dsa); memset(digest, 'd', sizeof(digest)); diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c index 52f9e74c0..10ad9da60 100644 --- a/ssh-ecdsa.c +++ b/ssh-ecdsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ecdsa.c,v 1.7 2013/12/27 22:30:17 djm Exp $ */ +/* $OpenBSD: ssh-ecdsa.c,v 1.8 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -42,15 +42,15 @@ #include "compat.h" #include "log.h" #include "key.h" +#include "digest.h" int ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { ECDSA_SIG *sig; - const EVP_MD *evp_md; - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE]; + int hash_alg; + u_char digest[SSH_DIGEST_MAX_LENGTH]; u_int len, dlen; Buffer b, bb; @@ -60,10 +60,16 @@ ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, return -1; } - evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid); - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); + hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); + if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { + error("%s: bad hash algorithm %d", __func__, hash_alg); + return -1; + } + if (ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest)) != 0) { + error("%s: digest_memory failed", __func__); + return -1; + } sig = ECDSA_do_sign(digest, dlen, key->ecdsa); memset(digest, 'd', sizeof(digest)); @@ -98,9 +104,8 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { ECDSA_SIG *sig; - const EVP_MD *evp_md; - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE], *sigblob; + int hash_alg; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; u_int len, dlen; int rlen, ret; Buffer b, bb; @@ -112,8 +117,6 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, return -1; } - evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid); - /* fetch signature */ buffer_init(&b); buffer_append(&b, signature, signaturelen); @@ -154,9 +157,16 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, free(sigblob); /* hash the data */ - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); + hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); + if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { + error("%s: bad hash algorithm %d", __func__, hash_alg); + return -1; + } + if (ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest)) != 0) { + error("%s: digest_memory failed", __func__); + return -1; + } ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa); memset(digest, 'd', sizeof(digest)); diff --git a/ssh-rsa.c b/ssh-rsa.c index b1ac50b31..a2112d033 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.49 2013/12/30 23:52:27 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.50 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -32,6 +32,7 @@ #include "compat.h" #include "misc.h" #include "ssh.h" +#include "digest.h" static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); @@ -40,9 +41,8 @@ int ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { - const EVP_MD *evp_md; - EVP_MD_CTX md; - u_char digest[EVP_MAX_MD_SIZE], *sig; + int hash_alg; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sig; u_int slen, dlen, len; int ok, nid; Buffer b; @@ -53,14 +53,18 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, return -1; } + /* hash the data */ + hash_alg = SSH_DIGEST_SHA1; nid = NID_sha1; - if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { - error("%s: EVP_get_digestbynid %d failed", __func__, nid); + if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { + error("%s: bad hash algorithm %d", __func__, hash_alg); + return -1; + } + if (ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest)) != 0) { + error("%s: ssh_digest_memory failed", __func__); return -1; } - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); slen = RSA_size(key->rsa); sig = xmalloc(slen); @@ -109,12 +113,11 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; - const EVP_MD *evp_md; - EVP_MD_CTX md; + int hash_alg; char *ktype; - u_char digest[EVP_MAX_MD_SIZE], *sigblob; + u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; u_int len, dlen, modlen; - int rlen, ret, nid; + int rlen, ret; if (key == NULL || key_type_plain(key->type) != KEY_RSA || key->rsa == NULL) { @@ -161,17 +164,20 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, memset(sigblob, 0, diff); len = modlen; } - nid = NID_sha1; - if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { - error("%s: EVP_get_digestbynid %d failed", __func__, nid); - free(sigblob); + /* hash the data */ + hash_alg = SSH_DIGEST_SHA1; + if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { + error("%s: bad hash algorithm %d", __func__, hash_alg); + return -1; + } + if (ssh_digest_memory(hash_alg, data, datalen, + digest, sizeof(digest)) != 0) { + error("%s: ssh_digest_memory failed", __func__); return -1; } - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); - ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); + ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, + key->rsa); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); free(sigblob); @@ -198,7 +204,7 @@ static const u_char id_sha1[] = { }; static int -openssh_RSA_verify(int type, u_char *hash, u_int hashlen, +openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen, u_char *sigbuf, u_int siglen, RSA *rsa) { u_int ret, rsasize, oidlen = 0, hlen = 0; @@ -207,8 +213,8 @@ openssh_RSA_verify(int type, u_char *hash, u_int hashlen, u_char *decrypted = NULL; ret = 0; - switch (type) { - case NID_sha1: + switch (hash_alg) { + case SSH_DIGEST_SHA1: oid = id_sha1; oidlen = sizeof(id_sha1); hlen = 20; diff --git a/sshconnect2.c b/sshconnect2.c index 0d339b9c5..8acffc5c3 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.200 2013/12/30 23:52:28 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.201 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -1006,7 +1006,7 @@ jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme, debug3("%s: crypted = %s", __func__, crypted); #endif - if (hash_buffer(crypted, strlen(crypted), EVP_sha256(), + if (hash_buffer(crypted, strlen(crypted), SSH_DIGEST_SHA1, &secret, &secret_len) != 0) fatal("%s: hash_buffer", __func__); -- cgit v1.2.3 From 91b580e4bec55118bf96ab3cdbe5a50839e75d0a Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 12 Jan 2014 19:21:22 +1100 Subject: - djm@cvs.openbsd.org 2014/01/12 08:13:13 [bufaux.c buffer.h kex.c kex.h kexc25519.c kexc25519c.c kexc25519s.c] [kexdhc.c kexdhs.c kexecdhc.c kexecdhs.c kexgexc.c kexgexs.c] avoid use of OpenSSL BIGNUM type and functions for KEX with Curve25519 by adding a buffer_put_bignum2_from_string() that stores a string using the bignum encoding rules. Will make it easier to build a reduced-feature OpenSSH without OpenSSL in the future; ok markus@ --- ChangeLog | 8 +++++++ bufaux.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- buffer.h | 6 ++++- kex.c | 23 +++++++++++++++---- kex.h | 11 +++++---- kexc25519.c | 18 ++++++--------- kexc25519c.c | 15 ++++++------ kexc25519s.c | 15 +++++++----- kexdhc.c | 4 ++-- kexdhs.c | 4 ++-- kexecdhc.c | 4 ++-- kexecdhs.c | 4 ++-- kexgexc.c | 4 ++-- kexgexs.c | 4 ++-- 14 files changed, 147 insertions(+), 48 deletions(-) (limited to 'kex.h') diff --git a/ChangeLog b/ChangeLog index 99b846e3c..e30cec1a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,14 @@ - djm@cvs.openbsd.org 2014/01/10 05:59:19 [sshd_config] the /etc/ssh/ssh_host_ed25519_key is loaded by default too + - djm@cvs.openbsd.org 2014/01/12 08:13:13 + [bufaux.c buffer.h kex.c kex.h kexc25519.c kexc25519c.c kexc25519s.c] + [kexdhc.c kexdhs.c kexecdhc.c kexecdhs.c kexgexc.c kexgexs.c] + avoid use of OpenSSL BIGNUM type and functions for KEX with + Curve25519 by adding a buffer_put_bignum2_from_string() that stores + a string using the bignum encoding rules. Will make it easier to + build a reduced-feature OpenSSH without OpenSSL in the future; + ok markus@ 20140110 - (djm) OpenBSD CVS Sync diff --git a/bufaux.c b/bufaux.c index 3e70b8d90..9401fe1d0 100644 --- a/bufaux.c +++ b/bufaux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bufaux.c,v 1.53 2013/11/08 11:15:19 dtucker Exp $ */ +/* $OpenBSD: bufaux.c,v 1.54 2014/01/12 08:13:13 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -315,3 +315,76 @@ buffer_put_char(Buffer *buffer, int value) buffer_append(buffer, &ch, 1); } + +/* Pseudo bignum functions */ + +void * +buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr) +{ + u_int len; + u_char *bin, *p, *ret; + + if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) { + error("%s: invalid bignum", __func__); + return NULL; + } + + if (len > 0 && (bin[0] & 0x80)) { + error("%s: negative numbers not supported", __func__); + free(bin); + return NULL; + } + if (len > 8 * 1024) { + error("%s: cannot handle BN of size %d", __func__, len); + free(bin); + return NULL; + } + /* Skip zero prefix on numbers with the MSB set */ + if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) { + p++; + len--; + } + ret = xmalloc(len); + memcpy(ret, p, len); + memset(p, '\0', len); + free(bin); + return ret; +} + +void * +buffer_get_bignum2_as_string(Buffer *buffer, u_int *l) +{ + void *ret = buffer_get_bignum2_as_string_ret(buffer, l); + + if (ret == NULL) + fatal("%s: buffer error", __func__); + return ret; +} + +/* + * Stores a string using the bignum encoding rules (\0 pad if MSB set). + */ +void +buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) +{ + u_char *buf, *p; + int pad = 0; + + if (l > 8 * 1024) + fatal("%s: length %u too long", __func__, l); + p = buf = xmalloc(l + 1); + /* + * If most significant bit is set then prepend a zero byte to + * avoid interpretation as a negative number. + */ + if (l > 0 && (s[0] & 0x80) != 0) { + *p++ = '\0'; + pad = 1; + } + memcpy(p, s, l); + buffer_put_string(buffer, buf, l + pad); + memset(buf, '\0', l + pad); + free(buf); +} + + diff --git a/buffer.h b/buffer.h index 4fa2ca112..7df8a38fa 100644 --- a/buffer.h +++ b/buffer.h @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.h,v 1.22 2013/07/12 00:19:58 djm Exp $ */ +/* $OpenBSD: buffer.h,v 1.23 2014/01/12 08:13:13 djm Exp $ */ /* * Author: Tatu Ylonen @@ -86,6 +86,10 @@ char *buffer_get_cstring_ret(Buffer *, u_int *); void *buffer_get_string_ptr_ret(Buffer *, u_int *); int buffer_get_char_ret(u_char *, Buffer *); +void *buffer_get_bignum2_as_string_ret(Buffer *, u_int *); +void *buffer_get_bignum2_as_string(Buffer *, u_int *); +void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int); + #ifdef OPENSSL_HAS_ECC #include diff --git a/kex.c b/kex.c index dbb1a9816..7d054cdcb 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.94 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.95 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -534,7 +534,7 @@ kex_choose_conf(Kex *kex) static u_char * derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, - BIGNUM *shared_secret) + const u_char *shared_secret, u_int slen) { Buffer b; struct ssh_digest_ctx *hashctx; @@ -548,7 +548,7 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, digest = xmalloc(roundup(need, mdsz)); buffer_init(&b); - buffer_put_bignum2(&b, shared_secret); + buffer_append(&b, shared_secret, slen); /* K1 = HASH(K || H || "A" || session_id) */ if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) @@ -591,14 +591,15 @@ Newkeys *current_keys[MODE_MAX]; #define NKEYS 6 void -kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret) +kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, + const u_char *shared_secret, u_int slen) { u_char *keys[NKEYS]; u_int i, mode, ctos; for (i = 0; i < NKEYS; i++) { keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, - shared_secret); + shared_secret, slen); } debug2("kex_derive_keys"); @@ -613,6 +614,18 @@ kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret) } } +void +kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) +{ + Buffer shared_secret; + + buffer_init(&shared_secret); + buffer_put_bignum2(&shared_secret, secret); + kex_derive_keys(kex, hash, hashlen, + buffer_ptr(&shared_secret), buffer_len(&shared_secret)); + buffer_free(&shared_secret); +} + Newkeys * kex_get_newkeys(int mode) { diff --git a/kex.h b/kex.h index fbe4940e8..7e2878f70 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.59 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.60 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -153,7 +153,8 @@ void kex_finish(Kex *); void kex_send_kexinit(Kex *); void kex_input_kexinit(int, u_int32_t, void *); -void kex_derive_keys(Kex *, u_char *, u_int, BIGNUM *); +void kex_derive_keys(Kex *, u_char *, u_int, const u_char *, u_int); +void kex_derive_keys_bn(Kex *, u_char *, u_int, const BIGNUM *); Newkeys *kex_get_newkeys(int); @@ -182,14 +183,14 @@ kex_ecdh_hash(int, const EC_GROUP *, char *, char *, char *, int, void kex_c25519_hash(int, char *, char *, char *, int, char *, int, u_char *, int, const u_char *, const u_char *, - const BIGNUM *, u_char **, u_int *); + const u_char *, u_int, u_char **, u_int *); #define CURVE25519_SIZE 32 void kexc25519_keygen(u_char[CURVE25519_SIZE], u_char[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -BIGNUM *kexc25519_shared_key(const u_char[CURVE25519_SIZE], - const u_char[CURVE25519_SIZE]) +void kexc25519_shared_key(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], Buffer *out) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); diff --git a/kexc25519.c b/kexc25519.c index 8dd363991..48ca4aaa2 100644 --- a/kexc25519.c +++ b/kexc25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519.c,v 1.3 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexc25519.c,v 1.4 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -58,23 +58,19 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) crypto_scalarmult_curve25519(pub, key, basepoint); } -BIGNUM * +void kexc25519_shared_key(const u_char key[CURVE25519_SIZE], - const u_char pub[CURVE25519_SIZE]) + const u_char pub[CURVE25519_SIZE], Buffer *out) { u_char shared_key[CURVE25519_SIZE]; - BIGNUM *shared_secret; crypto_scalarmult_curve25519(shared_key, key, pub); #ifdef DEBUG_KEXECDH dump_digest("shared secret", shared_key, CURVE25519_SIZE); #endif - if ((shared_secret = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - if (BN_bin2bn(shared_key, sizeof(shared_key), shared_secret) == NULL) - fatal("%s: BN_bin2bn failed", __func__); + buffer_clear(out); + buffer_put_bignum2_from_string(out, shared_key, CURVE25519_SIZE); memset(shared_key, 0, CURVE25519_SIZE); /* XXX explicit_bzero() */ - return (shared_secret); } void @@ -87,7 +83,7 @@ kex_c25519_hash( u_char *serverhostkeyblob, int sbloblen, const u_char client_dh_pub[CURVE25519_SIZE], const u_char server_dh_pub[CURVE25519_SIZE], - const BIGNUM *shared_secret, + const u_char *shared_secret, u_int secretlen, u_char **hash, u_int *hashlen) { Buffer b; @@ -108,7 +104,7 @@ kex_c25519_hash( buffer_put_string(&b, serverhostkeyblob, sbloblen); buffer_put_string(&b, client_dh_pub, CURVE25519_SIZE); buffer_put_string(&b, server_dh_pub, CURVE25519_SIZE); - buffer_put_bignum2(&b, shared_secret); + buffer_append(&b, shared_secret, secretlen); #ifdef DEBUG_KEX buffer_dump(&b); diff --git a/kexc25519c.c b/kexc25519c.c index 4655c2542..a80678af6 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.3 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.4 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -45,7 +45,6 @@ void kexc25519_client(Kex *kex) { - BIGNUM *shared_secret; Key *server_host_key; u_char client_key[CURVE25519_SIZE]; u_char client_pubkey[CURVE25519_SIZE]; @@ -53,6 +52,7 @@ kexc25519_client(Kex *kex) u_char *server_host_key_blob = NULL, *signature = NULL; u_char *hash; u_int slen, sbloblen, hashlen; + Buffer shared_secret; kexc25519_keygen(client_key, client_pubkey); @@ -93,7 +93,8 @@ kexc25519_client(Kex *kex) signature = packet_get_string(&slen); packet_check_eom(); - shared_secret = kexc25519_shared_key(client_key, server_pubkey); + buffer_init(&shared_secret); + kexc25519_shared_key(client_key, server_pubkey, &shared_secret); /* calc and verify H */ kex_c25519_hash( @@ -105,7 +106,7 @@ kexc25519_client(Kex *kex) server_host_key_blob, sbloblen, client_pubkey, server_pubkey, - shared_secret, + buffer_ptr(&shared_secret), buffer_len(&shared_secret), &hash, &hashlen ); free(server_host_key_blob); @@ -121,8 +122,8 @@ kexc25519_client(Kex *kex) kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } - - kex_derive_keys(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); + kex_derive_keys(kex, hash, hashlen, + buffer_ptr(&shared_secret), buffer_len(&shared_secret)); + buffer_free(&shared_secret); kex_finish(kex); } diff --git a/kexc25519s.c b/kexc25519s.c index dc4f56c80..2b8e8efa1 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.3 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.4 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -42,7 +42,6 @@ void kexc25519_server(Kex *kex) { - BIGNUM *shared_secret; Key *server_host_private, *server_host_public; u_char *server_host_key_blob = NULL, *signature = NULL; u_char server_key[CURVE25519_SIZE]; @@ -50,6 +49,7 @@ kexc25519_server(Kex *kex) u_char server_pubkey[CURVE25519_SIZE]; u_char *hash; u_int slen, sbloblen, hashlen; + Buffer shared_secret; /* generate private key */ kexc25519_keygen(server_key, server_pubkey); @@ -76,7 +76,8 @@ kexc25519_server(Kex *kex) dump_digest("client public key:", client_pubkey, CURVE25519_SIZE); #endif - shared_secret = kexc25519_shared_key(server_key, client_pubkey); + buffer_init(&shared_secret); + kexc25519_shared_key(server_key, client_pubkey, &shared_secret); /* calc H */ key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); @@ -89,7 +90,7 @@ kexc25519_server(Kex *kex) server_host_key_blob, sbloblen, client_pubkey, server_pubkey, - shared_secret, + buffer_ptr(&shared_secret), buffer_len(&shared_secret), &hash, &hashlen ); @@ -117,7 +118,9 @@ kexc25519_server(Kex *kex) free(server_host_key_blob); /* have keys, free server key */ free(client_pubkey); - kex_derive_keys(kex, hash, hashlen, shared_secret); - BN_clear_free(shared_secret); + + kex_derive_keys(kex, hash, hashlen, + buffer_ptr(&shared_secret), buffer_len(&shared_secret)); + buffer_free(&shared_secret); kex_finish(kex); } diff --git a/kexdhc.c b/kexdhc.c index ccd137cac..78509af21 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.14 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -155,7 +155,7 @@ kexdh_client(Kex *kex) memcpy(kex->session_id, hash, kex->session_id_len); } - kex_derive_keys(kex, hash, hashlen, shared_secret); + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); } diff --git a/kexdhs.c b/kexdhs.c index 39b9aba54..d2c7adc96 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.16 2013/11/02 22:24:24 markus Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.17 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -154,7 +154,7 @@ kexdh_server(Kex *kex) /* have keys, free DH */ DH_free(dh); - kex_derive_keys(kex, hash, hashlen, shared_secret); + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); } diff --git a/kexecdhc.c b/kexecdhc.c index fc62cec55..e3d1cf5f9 100644 --- a/kexecdhc.c +++ b/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.5 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexecdhc.c,v 1.6 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -152,7 +152,7 @@ kexecdh_client(Kex *kex) memcpy(kex->session_id, hash, kex->session_id_len); } - kex_derive_keys(kex, hash, hashlen, shared_secret); + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); } diff --git a/kexecdhs.c b/kexecdhs.c index d1dd8c7fb..6fbb79c9d 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.8 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.9 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -148,7 +148,7 @@ kexecdh_server(Kex *kex) /* have keys, free server key */ EC_KEY_free(server_key); - kex_derive_keys(kex, hash, hashlen, shared_secret); + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); } diff --git a/kexgexc.c b/kexgexc.c index ca771edfe..a69ff2705 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.14 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.15 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -200,7 +200,7 @@ kexgex_client(Kex *kex) kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } - kex_derive_keys(kex, hash, hashlen, shared_secret); + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); diff --git a/kexgexs.c b/kexgexs.c index 90853403e..8773778ed 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.17 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.18 2014/01/12 08:13:13 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -201,7 +201,7 @@ kexgex_server(Kex *kex) /* have keys, free DH */ DH_free(dh); - kex_derive_keys(kex, hash, hashlen, shared_secret); + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); -- cgit v1.2.3 From 76eea4ab4e658670ca6e76dd1e6d17f262208b57 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 26 Jan 2014 09:37:25 +1100 Subject: - dtucker@cvs.openbsd.org 2014/01/25 10:12:50 [cipher.c cipher.h kex.c kex.h kexgexc.c] Add a special case for the DH group size for 3des-cbc, which has an effective strength much lower than the key size. This causes problems with some cryptlib implementations, which don't support group sizes larger than 4k but also don't use the largest group size it does support as specified in the RFC. Based on a patch from Petr Lautrbach at Redhat, reduced by me with input from Markus. ok djm@ markus@ --- ChangeLog | 11 +++++++++++ cipher.c | 10 +++++++++- cipher.h | 3 ++- kex.c | 9 ++++++--- kex.h | 3 ++- kexgexc.c | 4 ++-- 6 files changed, 32 insertions(+), 8 deletions(-) (limited to 'kex.h') diff --git a/ChangeLog b/ChangeLog index 44e56f4a6..64da7a475 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +20130126 + - OpenBSD CVS Sync + - dtucker@cvs.openbsd.org 2014/01/25 10:12:50 + [cipher.c cipher.h kex.c kex.h kexgexc.c] + Add a special case for the DH group size for 3des-cbc, which has an + effective strength much lower than the key size. This causes problems + with some cryptlib implementations, which don't support group sizes larger + than 4k but also don't use the largest group size it does support as + specified in the RFC. Based on a patch from Petr Lautrbach at Redhat, + reduced by me with input from Markus. ok djm@ markus@ + 20130125 - (djm) [configure.ac] Fix detection of capsicum sandbox on FreeBSD - (djm) [configure.ac] Do not attempt to use capsicum sandbox unless diff --git a/cipher.c b/cipher.c index 76e6c5963..2476e6539 100644 --- a/cipher.c +++ b/cipher.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.93 2013/12/06 13:34:54 markus Exp $ */ +/* $OpenBSD: cipher.c,v 1.94 2014/01/25 10:12:50 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -141,6 +141,14 @@ cipher_keylen(const Cipher *c) return (c->key_len); } +u_int +cipher_seclen(const Cipher *c) +{ + if (strcmp("3des-cbc", c->name) == 0) + return 14; + return cipher_keylen(c); +} + u_int cipher_authlen(const Cipher *c) { diff --git a/cipher.h b/cipher.h index d78245615..133d2e73d 100644 --- a/cipher.h +++ b/cipher.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.h,v 1.43 2013/12/06 13:34:54 markus Exp $ */ +/* $OpenBSD: cipher.h,v 1.44 2014/01/25 10:12:50 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -89,6 +89,7 @@ void cipher_cleanup(CipherContext *); void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); u_int cipher_blocksize(const Cipher *); u_int cipher_keylen(const Cipher *); +u_int cipher_seclen(const Cipher *); u_int cipher_authlen(const Cipher *); u_int cipher_ivlen(const Cipher *); u_int cipher_is_cbc(const Cipher *); diff --git a/kex.c b/kex.c index 7d054cdcb..39d16f8e3 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.95 2014/01/12 08:13:13 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.96 2014/01/25 10:12:50 dtucker Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -458,7 +458,7 @@ kex_choose_conf(Kex *kex) char **my, **peer; char **cprop, **sprop; int nenc, nmac, ncomp; - u_int mode, ctos, need, authlen; + u_int mode, ctos, need, dh_need, authlen; int first_kex_follows, type; my = kex_buf2prop(&kex->my, NULL); @@ -506,7 +506,7 @@ kex_choose_conf(Kex *kex) choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); - need = 0; + need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; if (need < newkeys->enc.key_len) @@ -517,9 +517,12 @@ kex_choose_conf(Kex *kex) need = newkeys->enc.iv_len; if (need < newkeys->mac.key_len) need = newkeys->mac.key_len; + if (dh_need < cipher_seclen(newkeys->enc.cipher)) + dh_need = cipher_seclen(newkeys->enc.cipher); } /* XXX need runden? */ kex->we_need = need; + kex->dh_need = dh_need; /* ignore the next message if the proposals do not match */ if (first_kex_follows && !proposals_match(my, peer) && diff --git a/kex.h b/kex.h index 7e2878f70..1aa3ec26a 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.60 2014/01/12 08:13:13 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.61 2014/01/25 10:12:50 dtucker Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -124,6 +124,7 @@ struct Kex { u_int session_id_len; Newkeys *newkeys[MODE_MAX]; u_int we_need; + u_int dh_need; int server; char *name; int hostkey_type; diff --git a/kexgexc.c b/kexgexc.c index a69ff2705..629b5fbbc 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.15 2014/01/12 08:13:13 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.16 2014/01/25 10:12:50 dtucker Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -58,7 +58,7 @@ kexgex_client(Kex *kex) int min, max, nbits; DH *dh; - nbits = dh_estimate(kex->we_need * 8); + nbits = dh_estimate(kex->dh_need * 8); if (datafellows & SSH_OLD_DHGEX) { /* Old GEX request */ -- cgit v1.2.3