pass negotiated signing algorithm though to sshkey_verify() and
authordjm <djm@openbsd.org>
Mon, 18 Dec 2017 02:25:15 +0000 (02:25 +0000)
committerdjm <djm@openbsd.org>
Mon, 18 Dec 2017 02:25:15 +0000 (02:25 +0000)
check that the negotiated algorithm matches the type in the
signature (only matters for RSA SHA1/SHA2 sigs). ok markus@

18 files changed:
usr.bin/ssh/auth2-hostbased.c
usr.bin/ssh/auth2-pubkey.c
usr.bin/ssh/clientloop.c
usr.bin/ssh/kexc25519c.c
usr.bin/ssh/kexdhc.c
usr.bin/ssh/kexecdhc.c
usr.bin/ssh/kexgexc.c
usr.bin/ssh/key.c
usr.bin/ssh/key.h
usr.bin/ssh/krl.c
usr.bin/ssh/monitor.c
usr.bin/ssh/monitor_wrap.c
usr.bin/ssh/monitor_wrap.h
usr.bin/ssh/serverloop.c
usr.bin/ssh/ssh-keygen.c
usr.bin/ssh/ssh-rsa.c
usr.bin/ssh/sshkey.c
usr.bin/ssh/sshkey.h

index 3ea8311..70c3177 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.31 2017/06/24 06:34:38 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.32 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -143,7 +143,7 @@ userauth_hostbased(struct ssh *ssh)
        authenticated = 0;
        if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
            PRIVSEP(sshkey_verify(key, sig, slen,
-           sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0)
+           sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0)
                authenticated = 1;
 
        auth2_record_key(authctxt, authenticated, key);
index 73cc2ed..c23a3d5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.71 2017/09/07 23:48:09 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.72 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -195,7 +195,7 @@ userauth_pubkey(struct ssh *ssh)
                authenticated = 0;
                if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
                    PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
-                   sshbuf_len(b), ssh->compat)) == 0) {
+                   sshbuf_len(b), pkalg, ssh->compat)) == 0) {
                        authenticated = 1;
                }
                sshbuf_free(b);
index be13321..c7b9ff2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.307 2017/11/25 05:58:47 dtucker Exp $ */
+/* $OpenBSD: clientloop.c,v 1.308 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1919,7 +1919,8 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
                        goto out;
                }
                if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
-                   sshbuf_ptr(signdata), sshbuf_len(signdata), 0)) != 0) {
+                   sshbuf_ptr(signdata), sshbuf_len(signdata),
+                   ssh->kex->hostkey_alg, 0)) != 0) {
                        error("%s: server gave bad signature for %s key %zu",
                            __func__, sshkey_type(ctx->keys[i]), i);
                        goto out;
index 5661d21..0d72f8f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexc25519c.c,v 1.8 2017/05/31 04:17:12 djm Exp $ */
+/* $OpenBSD: kexc25519c.c,v 1.9 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -139,7 +139,7 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh)
                goto out;
 
        if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
-           ssh->compat)) != 0)
+           kex->hostkey_alg, ssh->compat)) != 0)
                goto out;
 
        /* save session id */
index efc2772..6b60f59 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexdhc.c,v 1.20 2017/05/30 14:23:52 markus Exp $ */
+/* $OpenBSD: kexdhc.c,v 1.21 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  *
@@ -178,7 +178,7 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
                goto out;
 
        if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
-           ssh->compat)) != 0)
+           kex->hostkey_alg, ssh->compat)) != 0)
                goto out;
 
        /* save session id */
index 3222803..ee6f848 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexecdhc.c,v 1.11 2017/05/30 14:23:52 markus Exp $ */
+/* $OpenBSD: kexecdhc.c,v 1.12 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -184,7 +184,7 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
                goto out;
 
        if ((r = sshkey_verify(server_host_key, signature, slen, hash,
-           hashlen, ssh->compat)) != 0)
+           hashlen, kex->hostkey_alg, ssh->compat)) != 0)
                goto out;
 
        /* save session id */
index 6107486..45a5682 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexc.c,v 1.25 2017/05/30 14:23:52 markus Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.26 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -225,7 +225,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
                goto out;
 
        if ((r = sshkey_verify(server_host_key, signature, slen, hash,
-           hashlen, ssh->compat)) != 0)
+           hashlen, kex->hostkey_alg, ssh->compat)) != 0)
                goto out;
 
        /* save session id */
index 921a9b5..9fae701 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.c,v 1.131 2017/05/30 14:16:41 markus Exp $ */
+/* $OpenBSD: key.c,v 1.132 2017/12/18 02:25:15 djm Exp $ */
 /*
  * placed in the public domain
  */
@@ -93,21 +93,6 @@ key_sign(const Key *key, u_char **sigp, u_int *lenp,
        return 0;
 }
 
-int
-key_verify(const Key *key, const u_char *signature, u_int signaturelen,
-    const u_char *data, u_int datalen)
-{
-       int r;
-
-       if ((r = sshkey_verify(key, signature, signaturelen,
-           data, datalen, datafellows)) != 0) {
-               fatal_on_fatal_errors(r, __func__, 0);
-               error("%s: %s", __func__, ssh_err(r));
-               return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1;
-       }
-       return 1;
-}
-
 Key *
 key_demote(const Key *k)
 {
index a14f370..fd59cbf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.h,v 1.51 2017/05/30 14:16:41 markus Exp $ */
+/* $OpenBSD: key.h,v 1.52 2017/12/18 02:25:15 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -58,7 +58,6 @@ int    key_to_blob(const Key *, u_char **, u_int *);
 
 int     key_sign(const Key *, u_char **, u_int *, const u_char *, u_int,
     const char *);
-int     key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
 
 /* authfile.c */
 Key    *key_load_cert(const char *);
index cb7f728..19c27e4 100644 (file)
@@ -14,7 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $OpenBSD: krl.c,v 1.40 2017/05/31 09:15:42 deraadt Exp $ */
+/* $OpenBSD: krl.c,v 1.41 2017/12/18 02:25:15 djm Exp $ */
 
 #include <sys/types.h>
 #include <sys/tree.h>
@@ -1012,7 +1012,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
                }
                /* Check signature over entire KRL up to this point */
                if ((r = sshkey_verify(key, blob, blen,
-                   sshbuf_ptr(buf), sig_off, 0)) != 0)
+                   sshbuf_ptr(buf), sig_off, NULL, 0)) != 0)
                        goto out;
                /* Check if this key has already signed this KRL */
                for (i = 0; i < nca_used; i++) {
index a6d5087..49c6237 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.175 2017/10/05 15:52:03 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.176 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -1048,12 +1048,14 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
 {
        struct sshkey *key;
        u_char *signature, *data, *blob;
+       char *sigalg;
        size_t signaturelen, datalen, bloblen;
        int r, ret, valid_data = 0, encoded_ret;
 
        if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 ||
            (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 ||
-           (r = sshbuf_get_string(m, &data, &datalen)) != 0)
+           (r = sshbuf_get_string(m, &data, &datalen)) != 0 ||
+           (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0)
                fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        if (hostbased_cuser == NULL || hostbased_chost == NULL ||
@@ -1082,7 +1084,7 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
                fatal("%s: bad signature data blob", __func__);
 
        ret = sshkey_verify(key, signature, signaturelen, data, datalen,
-           active_state->compat);
+           sigalg, active_state->compat);
        debug3("%s: %s %p signature %s", __func__, auth_method, key,
            (ret == 0) ? "verified" : "unverified");
        auth2_record_key(authctxt, ret == 0, key);
index c3ad9b0..8065488 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.95 2017/10/05 15:52:03 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.96 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -423,7 +423,7 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
 
 int
 mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
-    const u_char *data, size_t datalen, u_int compat)
+    const u_char *data, size_t datalen, const char *sigalg, u_int compat)
 {
        Buffer m;
        u_char *blob;
@@ -440,6 +440,7 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
        buffer_put_string(&m, blob, len);
        buffer_put_string(&m, sig, siglen);
        buffer_put_string(&m, data, datalen);
+       buffer_put_cstring(&m, sigalg);
        free(blob);
 
        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
index f484b37..6feb02e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.h,v 1.35 2017/05/31 08:09:45 markus Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.36 2017/12/18 02:25:15 djm Exp $ */
 
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -51,7 +51,7 @@ int mm_user_key_allowed(struct passwd *, struct sshkey *, int);
 int mm_hostbased_key_allowed(struct passwd *, const char *,
     const char *, struct sshkey *);
 int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,
-    const u_char *, size_t, u_int);
+    const u_char *, size_t, const char *, u_int);
 
 #ifdef GSSAPI
 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
index 309a256..853c0fc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.200 2017/12/10 05:55:29 dtucker Exp $ */
+/* $OpenBSD: serverloop.c,v 1.201 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -704,7 +704,8 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
                    ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
                    (r = sshkey_puts(key, sigbuf)) != 0 ||
                    (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
-                   sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), NULL, 0)) != 0 ||
+                   sshbuf_ptr(sigbuf), sshbuf_len(sigbuf),
+                   ssh->kex->hostkey_alg, 0)) != 0 ||
                    (r = sshbuf_put_string(resp, sig, slen)) != 0) {
                        error("%s: couldn't prepare signature: %s",
                            __func__, ssh_err(r));
index 282324f..aed5579 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.308 2017/11/03 05:14:04 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.309 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -529,7 +529,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
 
        /* try the key */
        if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 ||
-           sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) {
+           sshkey_verify(key, sig, slen, data, sizeof(data), NULL, 0) != 0) {
                sshkey_free(key);
                free(sig);
                return NULL;
index fa9d7f0..fb92657 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.62 2017/07/01 13:50:45 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.63 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
  *
@@ -193,9 +193,10 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
 
 int
 ssh_rsa_verify(const struct sshkey *key,
-    const u_char *sig, size_t siglen, const u_char *data, size_t datalen)
+    const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
+    const char *alg)
 {
-       char *ktype = NULL;
+       char *sigtype = NULL;
        int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
        size_t len, diff, modlen, dlen;
        struct sshbuf *b = NULL;
@@ -210,11 +211,17 @@ ssh_rsa_verify(const struct sshkey *key,
 
        if ((b = sshbuf_from(sig, siglen)) == NULL)
                return SSH_ERR_ALLOC_FAIL;
-       if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
+       if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) {
                ret = SSH_ERR_INVALID_FORMAT;
                goto out;
        }
-       if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) {
+       /* XXX djm: need cert types that reliably yield SHA-2 signatures */
+       if (alg != NULL && strcmp(alg, sigtype) != 0 &&
+           strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
+               ret = SSH_ERR_SIGNATURE_INVALID;
+               goto out;
+       }
+       if ((hash_alg = rsa_hash_alg_from_ident(sigtype)) == -1) {
                ret = SSH_ERR_KEY_TYPE_MISMATCH;
                goto out;
        }
@@ -258,7 +265,7 @@ ssh_rsa_verify(const struct sshkey *key,
                explicit_bzero(sigblob, len);
                free(sigblob);
        }
-       free(ktype);
+       free(sigtype);
        sshbuf_free(b);
        explicit_bzero(digest, sizeof(digest));
        return ret;
index 9e69a7e..0f8769f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.58 2017/12/18 02:22:29 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.59 2017/12/18 02:25:15 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -1778,7 +1778,7 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
                goto out;
        }
        if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
-           sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0)
+           sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
                goto out;
 
        /* Success */
@@ -2069,11 +2069,12 @@ sshkey_sign(const struct sshkey *key,
 
 /*
  * ssh_key_verify returns 0 for a correct signature  and < 0 on error.
+ * If "alg" specified, then the signature must use that algorithm.
  */
 int
 sshkey_verify(const struct sshkey *key,
     const u_char *sig, size_t siglen,
-    const u_char *data, size_t dlen, u_int compat)
+    const u_char *data, size_t dlen, const char *alg, u_int compat)
 {
        if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
                return SSH_ERR_INVALID_ARGUMENT;
@@ -2087,7 +2088,7 @@ sshkey_verify(const struct sshkey *key,
                return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
        case KEY_RSA_CERT:
        case KEY_RSA:
-               return ssh_rsa_verify(key, sig, siglen, data, dlen);
+               return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
 #endif /* WITH_OPENSSL */
        case KEY_ED25519:
        case KEY_ED25519_CERT:
index 814e22f..5057bc4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.22 2017/12/18 02:22:29 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.23 2017/12/18 02:25:15 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -172,7 +172,7 @@ int  sshkey_sigtype(const u_char *, size_t, char **);
 int     sshkey_sign(const struct sshkey *, u_char **, size_t *,
     const u_char *, size_t, const char *, u_int);
 int     sshkey_verify(const struct sshkey *, const u_char *, size_t,
-    const u_char *, size_t, u_int);
+    const u_char *, size_t, const char *, u_int);
 
 /* for debug */
 void   sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);
@@ -199,7 +199,8 @@ int ssh_rsa_sign(const struct sshkey *key,
     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
     const char *ident);
 int ssh_rsa_verify(const struct sshkey *key,
-    const u_char *sig, size_t siglen, const u_char *data, size_t datalen);
+    const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
+    const char *alg);
 int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
     const u_char *data, size_t datalen, u_int compat);
 int ssh_dss_verify(const struct sshkey *key,