From 28eeb9e1cbb72b5800aa282450ba52b6aed39e31 Mon Sep 17 00:00:00 2001 From: djm Date: Mon, 18 Dec 2017 02:25:15 +0000 Subject: [PATCH] pass negotiated signing algorithm though to sshkey_verify() and check that the negotiated algorithm matches the type in the signature (only matters for RSA SHA1/SHA2 sigs). ok markus@ --- usr.bin/ssh/auth2-hostbased.c | 4 ++-- usr.bin/ssh/auth2-pubkey.c | 4 ++-- usr.bin/ssh/clientloop.c | 5 +++-- usr.bin/ssh/kexc25519c.c | 4 ++-- usr.bin/ssh/kexdhc.c | 4 ++-- usr.bin/ssh/kexecdhc.c | 4 ++-- usr.bin/ssh/kexgexc.c | 4 ++-- usr.bin/ssh/key.c | 17 +---------------- usr.bin/ssh/key.h | 3 +-- usr.bin/ssh/krl.c | 4 ++-- usr.bin/ssh/monitor.c | 8 +++++--- usr.bin/ssh/monitor_wrap.c | 5 +++-- usr.bin/ssh/monitor_wrap.h | 4 ++-- usr.bin/ssh/serverloop.c | 5 +++-- usr.bin/ssh/ssh-keygen.c | 4 ++-- usr.bin/ssh/ssh-rsa.c | 19 +++++++++++++------ usr.bin/ssh/sshkey.c | 9 +++++---- usr.bin/ssh/sshkey.h | 7 ++++--- 18 files changed, 56 insertions(+), 58 deletions(-) diff --git a/usr.bin/ssh/auth2-hostbased.c b/usr.bin/ssh/auth2-hostbased.c index 3ea8311524e..70c31772db7 100644 --- a/usr.bin/ssh/auth2-hostbased.c +++ b/usr.bin/ssh/auth2-hostbased.c @@ -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); diff --git a/usr.bin/ssh/auth2-pubkey.c b/usr.bin/ssh/auth2-pubkey.c index 73cc2edb802..c23a3d5e7ea 100644 --- a/usr.bin/ssh/auth2-pubkey.c +++ b/usr.bin/ssh/auth2-pubkey.c @@ -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); diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index be133219e24..c7b9ff234ec 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -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 * Copyright (c) 1995 Tatu Ylonen , 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; diff --git a/usr.bin/ssh/kexc25519c.c b/usr.bin/ssh/kexc25519c.c index 5661d216820..0d72f8f6777 100644 --- a/usr.bin/ssh/kexc25519c.c +++ b/usr.bin/ssh/kexc25519c.c @@ -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 */ diff --git a/usr.bin/ssh/kexdhc.c b/usr.bin/ssh/kexdhc.c index efc2772f700..6b60f59da31 100644 --- a/usr.bin/ssh/kexdhc.c +++ b/usr.bin/ssh/kexdhc.c @@ -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 */ diff --git a/usr.bin/ssh/kexecdhc.c b/usr.bin/ssh/kexecdhc.c index 32228032bfd..ee6f848cb27 100644 --- a/usr.bin/ssh/kexecdhc.c +++ b/usr.bin/ssh/kexecdhc.c @@ -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 */ diff --git a/usr.bin/ssh/kexgexc.c b/usr.bin/ssh/kexgexc.c index 6107486caea..45a56827a74 100644 --- a/usr.bin/ssh/kexgexc.c +++ b/usr.bin/ssh/kexgexc.c @@ -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 */ diff --git a/usr.bin/ssh/key.c b/usr.bin/ssh/key.c index 921a9b54677..9fae701c450 100644 --- a/usr.bin/ssh/key.c +++ b/usr.bin/ssh/key.c @@ -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) { diff --git a/usr.bin/ssh/key.h b/usr.bin/ssh/key.h index a14f370376c..fd59cbf544d 100644 --- a/usr.bin/ssh/key.h +++ b/usr.bin/ssh/key.h @@ -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 *); diff --git a/usr.bin/ssh/krl.c b/usr.bin/ssh/krl.c index cb7f728f3a5..19c27e49767 100644 --- a/usr.bin/ssh/krl.c +++ b/usr.bin/ssh/krl.c @@ -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 #include @@ -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++) { diff --git a/usr.bin/ssh/monitor.c b/usr.bin/ssh/monitor.c index a6d5087656b..49c6237b558 100644 --- a/usr.bin/ssh/monitor.c +++ b/usr.bin/ssh/monitor.c @@ -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 * Copyright 2002 Markus Friedl @@ -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); diff --git a/usr.bin/ssh/monitor_wrap.c b/usr.bin/ssh/monitor_wrap.c index c3ad9b0c96d..806548877d7 100644 --- a/usr.bin/ssh/monitor_wrap.c +++ b/usr.bin/ssh/monitor_wrap.c @@ -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 * Copyright 2002 Markus Friedl @@ -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); diff --git a/usr.bin/ssh/monitor_wrap.h b/usr.bin/ssh/monitor_wrap.h index f484b3781ec..6feb02ed087 100644 --- a/usr.bin/ssh/monitor_wrap.h +++ b/usr.bin/ssh/monitor_wrap.h @@ -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 @@ -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); diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c index 309a2567fc2..853c0fc5eaa 100644 --- a/usr.bin/ssh/serverloop.c +++ b/usr.bin/ssh/serverloop.c @@ -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 * Copyright (c) 1995 Tatu Ylonen , 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)); diff --git a/usr.bin/ssh/ssh-keygen.c b/usr.bin/ssh/ssh-keygen.c index 282324f7f59..aed5579b5ca 100644 --- a/usr.bin/ssh/ssh-keygen.c +++ b/usr.bin/ssh/ssh-keygen.c @@ -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 * Copyright (c) 1994 Tatu Ylonen , 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; diff --git a/usr.bin/ssh/ssh-rsa.c b/usr.bin/ssh/ssh-rsa.c index fa9d7f0f182..fb9265709e7 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.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 * @@ -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; diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c index 9e69a7e75f0..0f8769f2943 100644 --- a/usr.bin/ssh/sshkey.c +++ b/usr.bin/ssh/sshkey.c @@ -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: diff --git a/usr.bin/ssh/sshkey.h b/usr.bin/ssh/sshkey.h index 814e22f81c2..5057bc40631 100644 --- a/usr.bin/ssh/sshkey.h +++ b/usr.bin/ssh/sshkey.h @@ -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, -- 2.20.1