Introduce digest API and use it to perform all hashing operations
authordjm <djm@openbsd.org>
Thu, 9 Jan 2014 23:20:00 +0000 (23:20 +0000)
committerdjm <djm@openbsd.org>
Thu, 9 Jan 2014 23:20:00 +0000 (23:20 +0000)
rather than calling OpenSSL EVP_Digest* directly. Will make it easier
to build a reduced-feature OpenSSH without OpenSSL in future;
feedback, ok markus@

26 files changed:
usr.bin/ssh/digest.c [new file with mode: 0644]
usr.bin/ssh/digest.h [new file with mode: 0644]
usr.bin/ssh/hostfile.c
usr.bin/ssh/kex.c
usr.bin/ssh/kex.h
usr.bin/ssh/kexc25519.c
usr.bin/ssh/kexc25519c.c
usr.bin/ssh/kexc25519s.c
usr.bin/ssh/kexdh.c
usr.bin/ssh/kexecdh.c
usr.bin/ssh/kexecdhc.c
usr.bin/ssh/kexecdhs.c
usr.bin/ssh/kexgex.c
usr.bin/ssh/kexgexc.c
usr.bin/ssh/kexgexs.c
usr.bin/ssh/key.c
usr.bin/ssh/key.h
usr.bin/ssh/lib/Makefile
usr.bin/ssh/roaming_client.c
usr.bin/ssh/roaming_common.c
usr.bin/ssh/schnorr.c
usr.bin/ssh/schnorr.h
usr.bin/ssh/ssh-dss.c
usr.bin/ssh/ssh-ecdsa.c
usr.bin/ssh/ssh-rsa.c
usr.bin/ssh/sshconnect2.c

diff --git a/usr.bin/ssh/digest.c b/usr.bin/ssh/digest.c
new file mode 100644 (file)
index 0000000..667d3d9
--- /dev/null
@@ -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 (file)
index 0000000..faefda3
--- /dev/null
@@ -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 */
+
index 0ebc827..8225711 100644 (file)
@@ -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;
index 8d56800..a853476 100644 (file)
@@ -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)
index b8a889f..612b950 100644 (file)
@@ -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 *);
 
index df80cf9..22c7052 100644 (file)
@@ -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);
 }
index cc68c0c..5d7d31e 100644 (file)
@@ -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),
index 22d84b1..8de3f0a 100644 (file)
@@ -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),
index 8e6ae63..f750dc7 100644 (file)
@@ -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);
 }
index 93d9b02..ba99f3d 100644 (file)
@@ -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.
 #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);
 }
-
index 977b9aa..a7b0b87 100644 (file)
@@ -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,
index b16cce9..3342762 100644 (file)
@@ -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,
index 70206ef..23ee598 100644 (file)
@@ -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.
 #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);
 }
index b988d30..160b655 100644 (file)
@@ -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),
index 1df2243..415d8c7 100644 (file)
@@ -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),
index 17384d1..5b075eb 100644 (file)
@@ -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
index 6a6ea6a..9930042 100644 (file)
@@ -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);
index 67ef309..362606e 100644 (file)
@@ -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
index 32fdd51..50b9d76 100644 (file)
@@ -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;
index a5c7a94..660a69e 100644 (file)
@@ -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);
 }
index 8088a1b..0e20e1b 100644 (file)
@@ -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 */
 
 /*
  * 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 */
index 9730b47..e2405c1 100644 (file)
@@ -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,
index 9b28af7..cd206fd 100644 (file)
@@ -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));
index acd14d7..4570aa3 100644 (file)
@@ -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.
 #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));
index c2ed72c..27b5080 100644 (file)
@@ -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;
index a992668..846a730 100644 (file)
@@ -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__);