summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2015-12-04 16:41:28 +0000
committerDamien Miller <djm@mindrot.org>2015-12-07 12:38:58 +1100
commit76c9fbbe35aabc1db977fb78e827644345e9442e (patch)
treee7c85e7e1471f1bd00b3a50a58e315c055f40b86
parent6064a8b8295cb5a17b5ebcfade53053377714f40 (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.h4
-rw-r--r--authfd.c18
-rw-r--r--authfd.h6
-rw-r--r--kex.c82
-rw-r--r--kex.h10
-rw-r--r--kexc25519s.c6
-rw-r--r--kexdhs.c6
-rw-r--r--kexecdhs.c6
-rw-r--r--kexgexs.c6
-rw-r--r--key.c6
-rw-r--r--key.h5
-rw-r--r--krl.c4
-rw-r--r--monitor.c12
-rw-r--r--monitor_wrap.c5
-rw-r--r--monitor_wrap.h4
-rw-r--r--myproposal.h6
-rw-r--r--packet.c5
-rw-r--r--serverloop.c4
-rw-r--r--ssh-agent.c16
-rw-r--r--ssh-keygen.c4
-rw-r--r--ssh-keysign.c5
-rw-r--r--ssh-rsa.c136
-rw-r--r--ssh2.h3
-rw-r--r--ssh_api.c16
-rw-r--r--sshconnect2.c126
-rw-r--r--sshd.c18
-rw-r--r--sshkey.c43
-rw-r--r--sshkey.h12
28 files changed, 418 insertions, 156 deletions
diff --git a/auth.h b/auth.h
index b235906c..2160154f 100644
--- a/auth.h
+++ b/auth.h
@@ -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)));
diff --git a/authfd.c b/authfd.c
index 12bf1251..a634bcb8 100644
--- a/authfd.c
+++ b/authfd.c
@@ -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 ||
diff --git a/authfd.h b/authfd.h
index bea20c26..4b417e3f 100644
--- a/authfd.h
+++ b/authfd.h
@@ -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 */
diff --git a/kex.c b/kex.c
index b409f276..c1371c43 100644
--- a/kex.c
+++ b/kex.c
@@ -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) {
diff --git a/kex.h b/kex.h
index d71b5329..25ccf2e0 100644
--- a/kex.h
+++ b/kex.h
@@ -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 */
diff --git a/kexdhs.c b/kexdhs.c
index de7c05b1..bf933e4c 100644
--- a/kexdhs.c
+++ b/kexdhs.c
@@ -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(); */
diff --git a/kexecdhs.c b/kexecdhs.c
index 0adb80e6..ccdbf70b 100644
--- a/kexecdhs.c
+++ b/kexecdhs.c
@@ -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(); */
diff --git a/kexgexs.c b/kexgexs.c
index ff6c6879..8c5adf7e 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -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(); */
diff --git a/key.c b/key.c
index 0ba98b6f..28d7c620 100644
--- a/key.c
+++ b/key.c
@@ -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;
diff --git a/key.h b/key.h
index 903bdf67..34c992bd 100644
--- a/key.h
+++ b/key.h
@@ -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 *);
diff --git a/krl.c b/krl.c
index 570a4f74..0194f1c7 100644
--- a/krl.c
+++ b/krl.c
@@ -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)
diff --git a/monitor.c b/monitor.c
index 4060a6ec..b3edd648 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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 */
diff --git a/packet.c b/packet.c
index 4f6433b4..37890695 100644
--- a/packet.c
+++ b/packet.c
@@ -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);
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 08090d14..81dab05b 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -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 out;
}
- if (strcmp("ssh-rsa", ktype) != 0) {
+ if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) {
ret = SSH_ERR_KEY_TYPE_MISMATCH;
goto out;
}
@@ -167,7 +211,6 @@ ssh_rsa_verify(const struct sshkey *key,
explicit_bzero(sigblob, diff);
len = modlen;
}
- hash_alg = SSH_DIGEST_SHA1;
if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
ret = SSH_ERR_INTERNAL_ERROR;
goto out;
@@ -196,6 +239,7 @@ ssh_rsa_verify(const struct sshkey *key,
* http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
* ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
*/
+
/*
* id-sha1 OBJECT IDENTIFIER ::= { iso(1)