diff options
author | Damien Miller <djm@cvs.openbsd.org> | 2017-12-18 23:16:25 +0000 |
---|---|---|
committer | Damien Miller <djm@cvs.openbsd.org> | 2017-12-18 23:16:25 +0000 |
commit | 34f7e2be544b8f49fddff164a8a4db53501ce206 (patch) | |
tree | f7f34a33d4c27887ed0c1c3a4d7b4ae6d4d3806d /usr.bin | |
parent | 91561c7a4edb4276bd99536f070eca3d4764b4ac (diff) |
unbreak hostkey rotation; attempting to sign with a desired signature
algorithm of kex->hostkey_alg is incorrect when the key type isn't
capable of making those signatures. ok markus@
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/ssh/clientloop.c | 15 | ||||
-rw-r--r-- | usr.bin/ssh/serverloop.c | 14 |
2 files changed, 23 insertions, 6 deletions
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index c7b9ff234ec..a4c056077a0 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.308 2017/12/18 02:25:15 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.309 2017/12/18 23:16:23 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -1878,7 +1878,7 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type, struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i, ndone; struct sshbuf *signdata; - int r; + int r, kexsigtype, use_kexsigtype; const u_char *sig; size_t siglen; @@ -1890,6 +1890,9 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type, hostkeys_update_ctx_free(ctx); return; } + kexsigtype = sshkey_type_plain( + sshkey_type_from_name(ssh->kex->hostkey_alg)); + if ((signdata = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); /* Don't want to accidentally accept an unbound signature */ @@ -1918,9 +1921,15 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type, __func__, ssh_err(r)); goto out; } + /* + * For RSA keys, prefer to use the signature type negotiated + * during KEX to the default (SHA1). + */ + use_kexsigtype = kexsigtype == KEY_RSA && + sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA; if ((r = sshkey_verify(ctx->keys[i], sig, siglen, sshbuf_ptr(signdata), sshbuf_len(signdata), - ssh->kex->hostkey_alg, 0)) != 0) { + use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0) { error("%s: server gave bad signature for %s key %zu", __func__, sshkey_type(ctx->keys[i]), i); goto out; diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c index 853c0fc5eaa..887ffaee312 100644 --- a/usr.bin/ssh/serverloop.c +++ b/usr.bin/ssh/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.201 2017/12/18 02:25:15 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.202 2017/12/18 23:16:24 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -660,7 +660,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) struct sshbuf *resp = NULL; struct sshbuf *sigbuf = NULL; struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; - int r, ndx, success = 0; + int r, ndx, kexsigtype, use_kexsigtype, success = 0; const u_char *blob; u_char *sig = 0; size_t blen, slen; @@ -668,6 +668,8 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) fatal("%s: sshbuf_new", __func__); + kexsigtype = sshkey_type_plain( + sshkey_type_from_name(ssh->kex->hostkey_alg)); while (ssh_packet_remaining(ssh) > 0) { sshkey_free(key); key = NULL; @@ -698,6 +700,12 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) sshbuf_reset(sigbuf); free(sig); sig = NULL; + /* + * For RSA keys, prefer to use the signature type negotiated + * during KEX to the default (SHA1). + */ + use_kexsigtype = kexsigtype == KEY_RSA && + sshkey_type_plain(key->type) == KEY_RSA; if ((r = sshbuf_put_cstring(sigbuf, "hostkeys-prove-00@openssh.com")) != 0 || (r = sshbuf_put_string(sigbuf, @@ -705,7 +713,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) (r = sshkey_puts(key, sigbuf)) != 0 || (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), - ssh->kex->hostkey_alg, 0)) != 0 || + use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error("%s: couldn't prepare signature: %s", __func__, ssh_err(r)); |