diff options
author | markus@openbsd.org <markus@openbsd.org> | 2015-12-04 16:41:28 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-12-07 12:38:58 +1100 |
commit | 76c9fbbe35aabc1db977fb78e827644345e9442e (patch) | |
tree | e7c85e7e1471f1bd00b3a50a58e315c055f40b86 | |
parent | 6064a8b8295cb5a17b5ebcfade53053377714f40 (diff) |
upstream commit
implement SHA2-{256,512} for RSASSA-PKCS1-v1_5 signatures
(user and host auth) based on draft-rsa-dsa-sha2-256-03.txt and
draft-ssh-ext-info-04.txt; with & ok djm@
Upstream-ID: cf82ce532b2733e5c4b34bb7b7c94835632db309
-rw-r--r-- | auth.h | 4 | ||||
-rw-r--r-- | authfd.c | 18 | ||||
-rw-r--r-- | authfd.h | 6 | ||||
-rw-r--r-- | kex.c | 82 | ||||
-rw-r--r-- | kex.h | 10 | ||||
-rw-r--r-- | kexc25519s.c | 6 | ||||
-rw-r--r-- | kexdhs.c | 6 | ||||
-rw-r--r-- | kexecdhs.c | 6 | ||||
-rw-r--r-- | kexgexs.c | 6 | ||||
-rw-r--r-- | key.c | 6 | ||||
-rw-r--r-- | key.h | 5 | ||||
-rw-r--r-- | krl.c | 4 | ||||
-rw-r--r-- | monitor.c | 12 | ||||
-rw-r--r-- | monitor_wrap.c | 5 | ||||
-rw-r--r-- | monitor_wrap.h | 4 | ||||
-rw-r--r-- | myproposal.h | 6 | ||||
-rw-r--r-- | packet.c | 5 | ||||
-rw-r--r-- | serverloop.c | 4 | ||||
-rw-r--r-- | ssh-agent.c | 16 | ||||
-rw-r--r-- | ssh-keygen.c | 4 | ||||
-rw-r--r-- | ssh-keysign.c | 5 | ||||
-rw-r--r-- | ssh-rsa.c | 136 | ||||
-rw-r--r-- | ssh2.h | 3 | ||||
-rw-r--r-- | ssh_api.c | 16 | ||||
-rw-r--r-- | sshconnect2.c | 126 | ||||
-rw-r--r-- | sshd.c | 18 | ||||
-rw-r--r-- | sshkey.c | 43 | ||||
-rw-r--r-- | sshkey.h | 12 |
28 files changed, 418 insertions, 156 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.85 2015/11/11 01:48:01 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.86 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -209,7 +209,7 @@ Key *get_hostkey_private_by_type(int, int, struct ssh *); int get_hostkey_index(Key *, int, struct ssh *); int ssh1_session_key(BIGNUM *); int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, - const u_char *, size_t, u_int); + const u_char *, size_t, const char *, u_int); /* debug messages during authentication */ void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.99 2015/09/02 07:51:12 jsg Exp $ */ +/* $OpenBSD: authfd.c,v 1.100 2015/12/04 16:41:28 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -426,11 +426,24 @@ ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, } #endif +/* encode signature algoritm in flag bits, so we can keep the msg format */ +static u_int +agent_encode_alg(struct sshkey *key, const char *alg) +{ + if (alg != NULL && key->type == KEY_RSA) { + if (strcmp(alg, "rsa-sha2-256") == 0) + return SSH_AGENT_RSA_SHA2_256; + else if (strcmp(alg, "rsa-sha2-512") == 0) + return SSH_AGENT_RSA_SHA2_512; + } + return 0; +} + /* ask agent to sign data, returns err.h code on error, 0 on success */ int ssh_agent_sign(int sock, struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) + const u_char *data, size_t datalen, const char *alg, u_int compat) { struct sshbuf *msg; u_char *blob = NULL, type; @@ -449,6 +462,7 @@ ssh_agent_sign(int sock, struct sshkey *key, return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) goto out; + flags |= agent_encode_alg(key, alg); if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0 || (r = sshbuf_put_string(msg, data, datalen)) != 0 || @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.h,v 1.38 2015/01/14 20:05:27 djm Exp $ */ +/* $OpenBSD: authfd.h,v 1.39 2015/12/04 16:41:28 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -41,7 +41,7 @@ int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, u_char session_id[16], u_char response[16]); int ssh_agent_sign(int sock, struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat); + const u_char *data, size_t datalen, const char *alg, u_int compat); /* Messages for the authentication agent connection. */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 @@ -86,5 +86,7 @@ int ssh_agent_sign(int sock, struct sshkey *key, #define SSH_COM_AGENT2_FAILURE 102 #define SSH_AGENT_OLD_SIGNATURE 0x01 +#define SSH_AGENT_RSA_SHA2_256 0x02 +#define SSH_AGENT_RSA_SHA2_512 0x04 #endif /* AUTHFD_H */ @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.112 2015/11/13 04:39:35 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.113 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -334,6 +334,20 @@ kex_reset_dispatch(struct ssh *ssh) ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); } +static int +kex_send_ext_info(struct ssh *ssh) +{ + int r; + + if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || + (r = sshpkt_put_u32(ssh, 1)) != 0 || + (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || + (r = sshpkt_put_cstring(ssh, "rsa-sha2-256,rsa-sha2-512")) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; + return 0; +} + int kex_send_newkeys(struct ssh *ssh) { @@ -346,9 +360,51 @@ kex_send_newkeys(struct ssh *ssh) debug("SSH2_MSG_NEWKEYS sent"); debug("expecting SSH2_MSG_NEWKEYS"); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); + if (ssh->kex->ext_info_c) + if ((r = kex_send_ext_info(ssh)) != 0) + return r; return 0; } +int +kex_input_ext_info(int type, u_int32_t seq, void *ctxt) +{ + struct ssh *ssh = ctxt; + struct kex *kex = ssh->kex; + u_int32_t i, ninfo; + char *name, *val, *found; + int r; + + debug("SSH2_MSG_EXT_INFO received"); + ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); + if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) + return r; + for (i = 0; i < ninfo; i++) { + if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) + return r; + if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) { + free(name); + return r; + } + debug("%s: %s=<%s>", __func__, name, val); + if (strcmp(name, "server-sig-algs") == 0) { + found = match_list("rsa-sha2-256", val, NULL); + if (found) { + kex->rsa_sha2 = 256; + free(found); + } + found = match_list("rsa-sha2-512", val, NULL); + if (found) { + kex->rsa_sha2 = 512; + free(found); + } + } + free(name); + free(val); + } + return sshpkt_get_end(ssh); +} + static int kex_input_newkeys(int type, u_int32_t seq, void *ctxt) { @@ -531,6 +587,8 @@ kex_free(struct kex *kex) free(kex->client_version_string); free(kex->server_version_string); free(kex->failed_choice); + free(kex->hostkey_alg); + free(kex->name); free(kex); } @@ -627,17 +685,16 @@ choose_kex(struct kex *k, char *client, char *server) static int choose_hostkeyalg(struct kex *k, char *client, char *server) { - char *hostkeyalg = match_list(client, server, NULL); + k->hostkey_alg = match_list(client, server, NULL); debug("kex: host key algorithm: %s", - hostkeyalg ? hostkeyalg : "(no match)"); - if (hostkeyalg == NULL) + k->hostkey_alg ? k->hostkey_alg : "(no match)"); + if (k->hostkey_alg == NULL) return SSH_ERR_NO_HOSTKEY_ALG_MATCH; - k->hostkey_type = sshkey_type_from_name(hostkeyalg); + k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); if (k->hostkey_type == KEY_UNSPEC) return SSH_ERR_INTERNAL_ERROR; - k->hostkey_nid = sshkey_ecdsa_nid_from_name(hostkeyalg); - free(hostkeyalg); + k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); return 0; } @@ -702,6 +759,17 @@ kex_choose_conf(struct ssh *ssh) } } + /* Check whether client supports ext_info_c */ + if (kex->server) { + char *ext; + + ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); + if (ext) { + kex->ext_info_c = 1; + free(ext); + } + } + /* Algorithm Negotiation */ if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS])) != 0) { @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.73 2015/07/30 00:01:34 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.74 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -129,10 +129,13 @@ struct kex { u_int dh_need; int server; char *name; + char *hostkey_alg; int hostkey_type; int hostkey_nid; u_int kex_type; int roaming; + int rsa_sha2; + int ext_info_c; struct sshbuf *my; struct sshbuf *peer; sig_atomic_t done; @@ -146,8 +149,8 @@ struct kex { struct sshkey *(*load_host_public_key)(int, int, struct ssh *); struct sshkey *(*load_host_private_key)(int, int, struct ssh *); int (*host_key_index)(struct sshkey *, int, struct ssh *); - int (*sign)(struct sshkey *, struct sshkey *, - u_char **, size_t *, const u_char *, size_t, u_int); + int (*sign)(struct sshkey *, struct sshkey *, u_char **, size_t *, + const u_char *, size_t, const char *, u_int); int (*kex[KEX_MAX])(struct ssh *); /* kex specific state */ DH *dh; /* DH */ @@ -174,6 +177,7 @@ void kex_prop_free(char **); int kex_send_kexinit(struct ssh *); int kex_input_kexinit(int, u_int32_t, void *); +int kex_input_ext_info(int, u_int32_t, void *); int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *); int kex_send_newkeys(struct ssh *); diff --git a/kexc25519s.c b/kexc25519s.c index 24027253..4e77622b 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519s.c,v 1.9 2015/04/27 00:37:53 dtucker Exp $ */ +/* $OpenBSD: kexc25519s.c,v 1.10 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -134,8 +134,8 @@ input_kex_c25519_init(int type, u_int32_t seq, void *ctxt) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, - &signature, &slen, hash, hashlen, ssh->compat)) < 0) + if ((r = kex->sign(server_host_private, server_host_public, &signature, + &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) goto out; /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.22 2015/01/26 06:10:03 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.23 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -181,8 +181,8 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, - &signature, &slen, hash, hashlen, ssh->compat)) < 0) + if ((r = kex->sign(server_host_private, server_host_public, &signature, + &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) goto out; /* destroy_sensitive_data(); */ @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.14 2015/01/26 06:10:03 djm Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.15 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -169,8 +169,8 @@ input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, - &signature, &slen, hash, hashlen, ssh->compat)) < 0) + if ((r = kex->sign(server_host_private, server_host_public, &signature, + &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) goto out; /* destroy_sensitive_data(); */ @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.25 2015/04/13 02:04:08 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.26 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -220,8 +220,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) } /* sign H */ - if ((r = kex->sign(server_host_private, server_host_public, - &signature, &slen, hash, hashlen, ssh->compat)) < 0) + if ((r = kex->sign(server_host_private, server_host_public, &signature, + &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) goto out; /* destroy_sensitive_data(); */ @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.128 2015/07/03 03:43:18 djm Exp $ */ +/* $OpenBSD: key.c,v 1.129 2015/12/04 16:41:28 markus Exp $ */ /* * placed in the public domain */ @@ -132,7 +132,7 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp) int key_sign(const Key *key, u_char **sigp, u_int *lenp, - const u_char *data, u_int datalen) + const u_char *data, u_int datalen, const char *alg) { int r; u_char *sig; @@ -143,7 +143,7 @@ key_sign(const Key *key, u_char **sigp, u_int *lenp, if (lenp != NULL) *lenp = 0; if ((r = sshkey_sign(key, &sig, &siglen, - data, datalen, datafellows)) != 0) { + data, datalen, alg, datafellows)) != 0) { fatal_on_fatal_errors(r, __func__, 0); error("%s: %s", __func__, ssh_err(r)); return -1; @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.48 2015/07/03 03:43:18 djm Exp $ */ +/* $OpenBSD: key.h,v 1.49 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -84,7 +84,8 @@ int key_ec_validate_private(const EC_KEY *); Key *key_from_blob(const u_char *, u_int); int key_to_blob(const Key *, u_char **, u_int *); -int key_sign(const Key *, u_char **, u_int *, const 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); void key_private_serialize(const Key *, struct sshbuf *); @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.34 2015/09/02 07:51:12 jsg Exp $ */ +/* $OpenBSD: krl.c,v 1.35 2015/12/04 16:41:28 markus Exp $ */ #include "includes.h" @@ -772,7 +772,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, goto out; if ((r = sshkey_sign(sign_keys[i], &sblob, &slen, - sshbuf_ptr(buf), sshbuf_len(buf), 0)) != 0) + sshbuf_ptr(buf), sshbuf_len(buf), NULL, 0)) != 0) goto out; KRL_DBG(("%s: signature sig len %zu", __func__, slen)); if ((r = sshbuf_put_string(buf, sblob, slen)) != 0) @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.154 2015/10/20 23:24:25 mmcc Exp $ */ +/* $OpenBSD: monitor.c,v 1.155 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -688,14 +688,16 @@ mm_answer_sign(int sock, Buffer *m) struct sshbuf *sigbuf; u_char *p; u_char *signature; - size_t datlen, siglen; + char *alg; + size_t datlen, siglen, alglen; int r, keyid, is_proof = 0; const char proof_req[] = "hostkeys-prove-00@openssh.com"; debug3("%s", __func__); if ((r = sshbuf_get_u32(m, &keyid)) != 0 || - (r = sshbuf_get_string(m, &p, &datlen)) != 0) + (r = sshbuf_get_string(m, &p, &datlen)) != 0 || + (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* @@ -742,14 +744,14 @@ mm_answer_sign(int sock, Buffer *m) } if ((key = get_hostkey_by_index(keyid)) != NULL) { - if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, + if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, datafellows)) != 0) fatal("%s: sshkey_sign failed: %s", __func__, ssh_err(r)); } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && auth_sock > 0) { if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, - p, datlen, datafellows)) != 0) { + p, datlen, alg, datafellows)) != 0) { fatal("%s: ssh_agent_sign failed: %s", __func__, ssh_err(r)); } diff --git a/monitor_wrap.c b/monitor_wrap.c index eac421ba..d4bfaf37 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.85 2015/05/01 03:23:51 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.86 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -218,7 +218,7 @@ mm_choose_dh(int min, int nbits, int max) int mm_key_sign(Key *key, u_char **sigp, u_int *lenp, - const u_char *data, u_int datalen) + const u_char *data, u_int datalen, const char *hostkey_alg) { struct kex *kex = *pmonitor->m_pkex; Buffer m; @@ -228,6 +228,7 @@ mm_key_sign(Key *key, u_char **sigp, u_int *lenp, buffer_init(&m); buffer_put_int(&m, kex->host_key_index(key, 0, active_state)); buffer_put_string(&m, data, datalen); + buffer_put_cstring(&m, hostkey_alg); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); diff --git a/monitor_wrap.h b/monitor_wrap.h index 9a6aff68..eb820aee 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.28 2015/11/11 01:48:01 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.29 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> @@ -40,7 +40,7 @@ struct Authctxt; void mm_log_handler(LogLevel, const char *, void *); int mm_is_monitor(void); DH *mm_choose_dh(int, int, int); -int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int); +int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int, const char *); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(const char *); char *mm_auth2_read_banner(void); diff --git a/myproposal.h b/myproposal.h index 46e5b988..c6429588 100644 --- a/myproposal.h +++ b/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.47 2015/07/10 06:21:53 markus Exp $ */ +/* $OpenBSD: myproposal.h,v 1.48 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -101,7 +101,9 @@ "ssh-rsa-cert-v01@openssh.com," \ HOSTKEY_ECDSA_METHODS \ "ssh-ed25519," \ - "ssh-rsa" \ + "rsa-sha2-256," \ + "rsa-sha2-512," \ + "ssh-rsa" /* the actual algorithms */ @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.217 2015/11/08 21:59:11 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.218 2015/12/04 16:41:28 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -1215,7 +1215,8 @@ ssh_packet_send2(struct ssh *ssh) if ((type < SSH2_MSG_TRANSPORT_MIN) || (type > SSH2_MSG_TRANSPORT_MAX) || (type == SSH2_MSG_SERVICE_REQUEST) || - (type == SSH2_MSG_SERVICE_ACCEPT)) { + (type == SSH2_MSG_SERVICE_ACCEPT) || + (type == SSH2_MSG_EXT_INFO)) { debug("enqueue packet: %u", type); p = calloc(1, sizeof(*p)); if (p == NULL) diff --git a/serverloop.c b/serverloop.c index 4d0c0edb..85fc8d3a 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.179 2015/11/28 06:41:03 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.180 2015/12/04 16:41:28 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -1201,7 +1201,7 @@ server_input_hostkeys_prove(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), 0)) != 0 || + sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), NULL, 0)) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error("%s: couldn't prepare signature: %s", __func__, ssh_err(r)); diff --git a/ssh-agent.c b/ssh-agent.c index 2a7ae88f..ed5dc571 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.207 2015/12/02 08:30:50 doug Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.208 2015/12/04 16:41:28 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -368,6 +368,18 @@ process_authentication_challenge1(SocketEntry *e) } #endif +static char * +agent_decode_alg(struct sshkey *key, u_int flags) +{ + if (key->type == KEY_RSA) { + if (flags & SSH_AGENT_RSA_SHA2_256) + return "rsa-sha2-256"; + else if (flags & SSH_AGENT_RSA_SHA2_512) + return "rsa-sha2-512"; + } + return NULL; +} + /* ssh2 only */ static void process_sign_request2(SocketEntry *e) @@ -401,7 +413,7 @@ process_sign_request2(SocketEntry *e) goto send; } if ((r = sshkey_sign(id->key, &signature, &slen, - data, dlen, compat)) != 0) { + data, dlen, agent_decode_alg(key, flags), compat)) != 0) { error("%s: sshkey_sign: %s", __func__, ssh_err(ok)); goto send; } diff --git a/ssh-keygen.c b/ssh-keygen.c index f6a1c284..6ac1fa60 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.284 2015/11/28 06:50:52 deraadt Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.285 2015/12/04 16:41:28 markus Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -523,7 +523,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) sshbuf_free(b); /* try the key */ - if (sshkey_sign(key, &sig, &slen, data, sizeof(data), 0) != 0 || + if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 || sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) { sshkey_free(key); free(sig); diff --git a/ssh-keysign.c b/ssh-keysign.c index 4c99609b..1d49861a 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.50 2015/11/29 22:18:37 djm Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.51 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -291,7 +291,8 @@ main(int argc, char **argv) sshkey_type(key), fp ? fp : ""); } - if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, 0)) != 0) + if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, NULL, 0)) + != 0) fatal("sshkey_sign failed: %s", ssh_err(r)); free(data); @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.54 2015/09/09 00:52:44 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.55 2015/12/04 16:41:28 markus Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> * @@ -36,16 +36,60 @@ static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); +static const char * +rsa_hash_alg_ident(int hash_alg) +{ + switch (hash_alg) { + case SSH_DIGEST_SHA1: + return "ssh-rsa"; + case SSH_DIGEST_SHA256: + return "rsa-sha2-256"; + case SSH_DIGEST_SHA512: + return "rsa-sha2-512"; + } + return NULL; +} + +static int +rsa_hash_alg_from_ident(const char *ident) +{ + if (ident == NULL || strlen(ident) == 0) + return SSH_DIGEST_SHA1; + if (strcmp(ident, "ssh-rsa") == 0) + return SSH_DIGEST_SHA1; + if (strcmp(ident, "rsa-sha2-256") == 0) + return SSH_DIGEST_SHA256; + if (strcmp(ident, "rsa-sha2-512") == 0) + return SSH_DIGEST_SHA512; + if (strncmp(ident, "ssh-rsa-cert", strlen("ssh-rsa-cert")) == 0) + return SSH_DIGEST_SHA1; + return -1; +} + +static int +rsa_hash_alg_nid(int type) +{ + switch (type) { + case SSH_DIGEST_SHA1: + return NID_sha1; + case SSH_DIGEST_SHA256: + return NID_sha256; + case SSH_DIGEST_SHA512: + return NID_sha512; + default: + return -1; + } +} + /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) + const u_char *data, size_t datalen, const char *alg_ident) { - int hash_alg; u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; size_t slen; u_int dlen, len; - int nid, ret = SSH_ERR_INTERNAL_ERROR; + int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; if (lenp != NULL) @@ -53,16 +97,17 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, if (sigp != NULL) *sigp = NULL; - if (key == NULL || key->rsa == NULL || - sshkey_type_plain(key->type) != KEY_RSA) + hash_alg = rsa_hash_alg_from_ident(alg_ident); + if (key == NULL || key->rsa == NULL || hash_alg == -1 || + sshkey_type_plain(key->type) != KEY_RSA || + BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) return SSH_ERR_INVALID_ARGUMENT; slen = RSA_size(key->rsa); if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) return SSH_ERR_INVALID_ARGUMENT; /* hash the data */ - hash_alg = SSH_DIGEST_SHA1; - nid = NID_sha1; + nid = rsa_hash_alg_nid(hash_alg); if ((dlen = ssh_digest_bytes(hash_alg)) == 0) return SSH_ERR_INTERNAL_ERROR; if ((ret = ssh_digest_memory(hash_alg, data, datalen, @@ -91,7 +136,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ret = SSH_ERR_ALLOC_FAIL; goto out; } - if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 || + if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || (ret = sshbuf_put_string(b, sig, slen)) != 0) goto out; len = sshbuf_len(b); @@ -118,8 +163,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, int ssh_rsa_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat) + const u_char *sig, size_t siglen, const u_char *data, size_t datalen) { char *ktype = NULL; int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; @@ -132,13 +176,13 @@ ssh_rsa_verify(const struct sshkey *key, BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_from(signature, signaturelen)) == NULL) + if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto |