summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2014-01-09 23:20:02 +0000
committerDamien Miller <djm@cvs.openbsd.org>2014-01-09 23:20:02 +0000
commit3c69bcd01bec3c42c28c5b015a38895efe3392df (patch)
treeb34d4cdb3ad8a27c99385a1c1a68cf2c2fc6d423 /usr.bin/ssh
parent9480debea37ac22aede40ebf0f2ca9f6191ad797 (diff)
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@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/digest.c144
-rw-r--r--usr.bin/ssh/digest.h55
-rw-r--r--usr.bin/ssh/hostfile.c3
-rw-r--r--usr.bin/ssh/kex.c93
-rw-r--r--usr.bin/ssh/kex.h10
-rw-r--r--usr.bin/ssh/kexc25519.c17
-rw-r--r--usr.bin/ssh/kexc25519c.c4
-rw-r--r--usr.bin/ssh/kexc25519s.c4
-rw-r--r--usr.bin/ssh/kexdh.c17
-rw-r--r--usr.bin/ssh/kexecdh.c18
-rw-r--r--usr.bin/ssh/kexecdhc.c4
-rw-r--r--usr.bin/ssh/kexecdhs.c4
-rw-r--r--usr.bin/ssh/kexgex.c24
-rw-r--r--usr.bin/ssh/kexgexc.c4
-rw-r--r--usr.bin/ssh/kexgexs.c4
-rw-r--r--usr.bin/ssh/key.c40
-rw-r--r--usr.bin/ssh/key.h4
-rw-r--r--usr.bin/ssh/lib/Makefile4
-rw-r--r--usr.bin/ssh/roaming_client.c14
-rw-r--r--usr.bin/ssh/roaming_common.c14
-rw-r--r--usr.bin/ssh/schnorr.c57
-rw-r--r--usr.bin/ssh/schnorr.h8
-rw-r--r--usr.bin/ssh/ssh-dss.c31
-rw-r--r--usr.bin/ssh/ssh-ecdsa.c42
-rw-r--r--usr.bin/ssh/ssh-rsa.c54
-rw-r--r--usr.bin/ssh/sshconnect2.c4
26 files changed, 444 insertions, 233 deletions
diff --git a/usr.bin/ssh/digest.c b/usr.bin/ssh/digest.c
new file mode 100644
index 00000000000..667d3d948c0
--- /dev/null
+++ b/usr.bin/ssh/digest.c
@@ -0,0 +1,144 @@
+/* $OpenBSD: digest.c,v 1.1 2014/01/09 23:20:00 djm Exp $ */
+/*
+ * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
+ *
+ * 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 <sys/types.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bn.h> /* for buffer.h */
+#include <openssl/ec.h> /* for buffer.h */
+#include <openssl/evp.h>
+
+#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 },
+ { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
+ { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 },
+ { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 },
+ { -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/usr.bin/ssh/digest.h b/usr.bin/ssh/digest.h
new file mode 100644
index 00000000000..faefda3f533
--- /dev/null
+++ b/usr.bin/ssh/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 <djm@mindrot.org>
+ *
+ * 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/usr.bin/ssh/hostfile.c b/usr.bin/ssh/hostfile.c
index 0ebc82757ee..8225711a43c 100644
--- a/usr.bin/ssh/hostfile.c
+++ b/usr.bin/ssh/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 <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -54,6 +54,7 @@
#include "hostfile.h"
#include "log.h"
#include "misc.h"
+#include "digest.h"
struct hostkeys {
struct hostkey_entry *entries;
diff --git a/usr.bin/ssh/kex.c b/usr.bin/ssh/kex.c
index 8d568006620..a85347666bf 100644
--- a/usr.bin/ssh/kex.c
+++ b/usr.bin/ssh/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.
*
@@ -46,6 +46,7 @@
#include "dispatch.h"
#include "monitor.h"
#include "roaming.h"
+#include "digest.h"
/* prototype */
static void kex_kexinit_finish(Kex *);
@@ -55,18 +56,21 @@ 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_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 },
- { 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_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 },
- { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, EVP_sha256 },
- { NULL, -1, -1, NULL},
+ { 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 },
+ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
+ { 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 },
+ { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
+ SSH_DIGEST_SHA512 },
+ { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
+ { NULL, -1, -1, -1},
};
char *
@@ -387,7 +391,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;
}
@@ -513,27 +517,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:
@@ -541,12 +549,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
@@ -596,33 +607,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/usr.bin/ssh/kex.h b/usr.bin/ssh/kex.h
index b8a889f5401..612b9503943 100644
--- a/usr.bin/ssh/kex.h
+++ b/usr.bin/ssh/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.
@@ -130,7 +130,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;
@@ -167,15 +167,15 @@ 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 *);
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 *);
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/usr.bin/ssh/kexc25519.c b/usr.bin/ssh/kexc25519.c
index df80cf9b16e..22c705205a1 100644
--- a/usr.bin/ssh/kexc25519.c
+++ b/usr.bin/ssh/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.
@@ -39,6 +39,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])
@@ -76,7 +77,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,
@@ -88,8 +89,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);
@@ -111,15 +111,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/usr.bin/ssh/kexc25519c.c b/usr.bin/ssh/kexc25519c.c
index cc68c0c6477..5d7d31e6eb8 100644
--- a/usr.bin/ssh/kexc25519c.c
+++ b/usr.bin/ssh/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.
@@ -95,7 +95,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/usr.bin/ssh/kexc25519s.c b/usr.bin/ssh/kexc25519s.c
index 22d84b17f0d..8de3f0acee9 100644
--- a/usr.bin/ssh/kexc25519s.c
+++ b/usr.bin/ssh/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.
@@ -79,7 +79,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/usr.bin/ssh/kexdh.c b/usr.bin/ssh/kexdh.c
index 8e6ae6348e4..f750dc79ac1 100644
--- a/usr.bin/ssh/kexdh.c
+++ b/usr.bin/ssh/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.
*
@@ -34,6 +34,8 @@
#include "key.h"
#include "cipher.h"
#include "kex.h"
+#include "digest.h"
+#include "log.h"
void
kex_dh_hash(
@@ -48,9 +50,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);
@@ -72,15 +72,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/usr.bin/ssh/kexecdh.c b/usr.bin/ssh/kexecdh.c
index 93d9b02c1ac..ba99f3db220 100644
--- a/usr.bin/ssh/kexecdh.c
+++ b/usr.bin/ssh/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.
@@ -40,10 +40,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,
@@ -56,8 +57,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);
@@ -79,16 +79,14 @@ 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);
}
-
diff --git a/usr.bin/ssh/kexecdhc.c b/usr.bin/ssh/kexecdhc.c
index 977b9aa1537..a7b0b879fbe 100644
--- a/usr.bin/ssh/kexecdhc.c
+++ b/usr.bin/ssh/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.
@@ -120,7 +120,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/usr.bin/ssh/kexecdhs.c b/usr.bin/ssh/kexecdhs.c
index b16cce949b2..334276275fb 100644
--- a/usr.bin/ssh/kexecdhs.c
+++ b/usr.bin/ssh/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.
@@ -105,7 +105,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/usr.bin/ssh/kexgex.c b/usr.bin/ssh/kexgex.c
index 70206ef5c15..23ee598e91f 100644
--- a/usr.bin/ssh/kexgex.c
+++ b/usr.bin/ssh/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.
@@ -34,10 +34,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,
@@ -50,8 +52,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);
@@ -82,15 +83,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/usr.bin/ssh/kexgexc.c b/usr.bin/ssh/kexgexc.c
index b988d30e54c..160b655eef0 100644
--- a/usr.bin/ssh/kexgexc.c
+++ b/usr.bin/ssh/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.
@@ -167,7 +167,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/usr.bin/ssh/kexgexs.c b/usr.bin/ssh/kexgexs.c
index 1df2243c398..415d8c7398d 100644
--- a/usr.bin/ssh/kexgexs.c
+++ b/usr.bin/ssh/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.
@@ -157,7 +157,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/usr.bin/ssh/key.c b/usr.bin/ssh/key.c
index 17384d1a0b6..5b075ebe181 100644
--- a/usr.bin/ssh/key.c
+++ b/usr.bin/ssh/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 <ylo@cs.hut.fi>, Espoo, Finland
@@ -51,6 +51,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);
@@ -345,28 +346,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;
case SSH_FP_SHA256:
- md = EVP_sha256();
+ hash_alg = SSH_DIGEST_SHA256;
break;
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:
@@ -395,18 +394,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;
}
@@ -2132,8 +2132,8 @@ key_curve_nid_to_name(int nid)
return NULL;
}
-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);
@@ -2141,11 +2141,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/usr.bin/ssh/key.h b/usr.bin/ssh/key.h
index 6a6ea6aa334..99300425ad1 100644
--- a/usr.bin/ssh/key.h
+++ b/usr.bin/ssh/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.
@@ -124,7 +124,7 @@ const char *key_curve_nid_to_name(int);
u_int key_curve_nid_to_bits(int);
int key_ecdsa_bits_to_nid(int);
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 *);
char *key_alg_list(int, int);
diff --git a/usr.bin/ssh/lib/Makefile b/usr.bin/ssh/lib/Makefile
index 67ef309ebc2..362606ebcfb 100644
--- a/usr.bin/ssh/lib/Makefile
+++ b/usr.bin/ssh/lib/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.70 2013/12/06 13:39:49 markus Exp $
+# $OpenBSD: Makefile,v 1.71 2014/01/09 23:20:01 djm Exp $
.PATH: ${.CURDIR}/..
.include "${.CURDIR}/../Makefile.inc"
@@ -14,7 +14,7 @@ SRCS= authfd.c authfile.c bufaux.c bufec.c bufbn.c buffer.c canohost.c \
kexdhc.c kexgexc.c kexecdhc.c msg.c progressmeter.c dns.c \
monitor_fdpass.c umac.c addrmatch.c schnorr.c jpake.c ssh-pkcs11.c \
krl.c smult_curve25519_ref.c kexc25519.c kexc25519c.c \
- chacha.c poly1305.c cipher-chachapoly.c ssh-ed25519.c
+ chacha.c poly1305.c cipher-chachapoly.c ssh-ed25519.c digest.c
# ed25519, from supercop
SRCS+= sc25519.c ge25519.c fe25519.c ed25519.c verify.c hash.c blocks.c
diff --git a/usr.bin/ssh/roaming_client.c b/usr.bin/ssh/roaming_client.c
index 32fdd51f206..50b9d764ee4 100644
--- a/usr.bin/ssh/roaming_client.c
+++ b/usr.bin/ssh/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
*
@@ -44,6 +44,7 @@
#include "roaming.h"
#include "ssh2.h"
#include "sshconnect.h"
+#include "digest.h"
/* import */
extern Options options;
@@ -86,10 +87,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();
@@ -103,14 +102,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/usr.bin/ssh/roaming_common.c b/usr.bin/ssh/roaming_common.c
index a5c7a9473ec..660a69e8a48 100644
--- a/usr.bin/ssh/roaming_common.c
+++ b/usr.bin/ssh/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
*
@@ -32,6 +32,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;
@@ -221,9 +222,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);
@@ -231,12 +230,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/usr.bin/ssh/schnorr.c b/usr.bin/ssh/schnorr.c
index 8088a1b5921..0e20e1b0159 100644
--- a/usr.bin/ssh/schnorr.c
+++ b/usr.bin/ssh/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.
*
@@ -39,6 +39,7 @@
#include "log.h"
#include "schnorr.h"
+#include "digest.h"
/* #define SCHNORR_DEBUG */ /* Privacy-violating debugging */
/* #define SCHNORR_MAIN */ /* Include main() selftest */
@@ -53,12 +54,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;
@@ -84,7 +85,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;
@@ -109,7 +110,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.
*
@@ -119,7 +120,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;
@@ -169,7 +170,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;
@@ -219,7 +220,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;
@@ -244,13 +245,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;
@@ -298,7 +299,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;
@@ -381,7 +382,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);
@@ -439,43 +440,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/usr.bin/ssh/schnorr.h b/usr.bin/ssh/schnorr.h
index 9730b47cef3..e2405c10290 100644
--- a/usr.bin/ssh/schnorr.h
+++ b/usr.bin/ssh/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/usr.bin/ssh/ssh-dss.c b/usr.bin/ssh/ssh-dss.c
index 9b28af7f9e4..cd206fd44c3 100644
--- a/usr.bin/ssh/ssh-dss.c
+++ b/usr.bin/ssh/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.
*
@@ -35,6 +35,7 @@
#include "compat.h"
#include "log.h"
#include "key.h"
+#include "digest.h"
#define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN)
@@ -44,10 +45,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 ||
@@ -56,9 +55,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));
@@ -108,10 +109,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;
@@ -170,9 +169,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/usr.bin/ssh/ssh-ecdsa.c b/usr.bin/ssh/ssh-ecdsa.c
index acd14d7cbf8..4570aa3d355 100644
--- a/usr.bin/ssh/ssh-ecdsa.c
+++ b/usr.bin/ssh/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.
@@ -38,15 +38,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;
@@ -56,10 +56,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));
@@ -94,9 +100,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;
@@ -108,8 +113,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);
@@ -150,9 +153,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/usr.bin/ssh/ssh-rsa.c b/usr.bin/ssh/ssh-rsa.c
index c2ed72cc36f..27b50808593 100644
--- a/usr.bin/ssh/ssh-rsa.c
+++ b/usr.bin/ssh/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 <markus@openbsd.org>
*
@@ -29,6 +29,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 *);
@@ -37,9 +38,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;
@@ -50,14 +50,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);
@@ -106,12 +110,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) {
@@ -158,17 +161,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);
@@ -195,7 +201,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;
@@ -204,8 +210,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/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c
index a992668a0d9..846a730cf59 100644
--- a/usr.bin/ssh/sshconnect2.c
+++ b/usr.bin/ssh/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.
@@ -1000,7 +1000,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__);