summaryrefslogtreecommitdiff
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 b235906cf..2160154f4 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.85 2015/11/11 01:48:01 djm Exp $ */ 1/* $OpenBSD: auth.h,v 1.86 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -209,7 +209,7 @@ Key *get_hostkey_private_by_type(int, int, struct ssh *);
209int get_hostkey_index(Key *, int, struct ssh *); 209int get_hostkey_index(Key *, int, struct ssh *);
210int ssh1_session_key(BIGNUM *); 210int ssh1_session_key(BIGNUM *);
211int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, 211int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *,
212 const u_char *, size_t, u_int); 212 const u_char *, size_t, const char *, u_int);
213 213
214/* debug messages during authentication */ 214/* debug messages during authentication */
215void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); 215void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
diff --git a/authfd.c b/authfd.c
index 12bf1251f..a634bcb81 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfd.c,v 1.99 2015/09/02 07:51:12 jsg Exp $ */ 1/* $OpenBSD: authfd.c,v 1.100 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * 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,
426} 426}
427#endif 427#endif
428 428
429/* encode signature algoritm in flag bits, so we can keep the msg format */
430static u_int
431agent_encode_alg(struct sshkey *key, const char *alg)
432{
433 if (alg != NULL && key->type == KEY_RSA) {
434 if (strcmp(alg, "rsa-sha2-256") == 0)
435 return SSH_AGENT_RSA_SHA2_256;
436 else if (strcmp(alg, "rsa-sha2-512") == 0)
437 return SSH_AGENT_RSA_SHA2_512;
438 }
439 return 0;
440}
441
429/* ask agent to sign data, returns err.h code on error, 0 on success */ 442/* ask agent to sign data, returns err.h code on error, 0 on success */
430int 443int
431ssh_agent_sign(int sock, struct sshkey *key, 444ssh_agent_sign(int sock, struct sshkey *key,
432 u_char **sigp, size_t *lenp, 445 u_char **sigp, size_t *lenp,
433 const u_char *data, size_t datalen, u_int compat) 446 const u_char *data, size_t datalen, const char *alg, u_int compat)
434{ 447{
435 struct sshbuf *msg; 448 struct sshbuf *msg;
436 u_char *blob = NULL, type; 449 u_char *blob = NULL, type;
@@ -449,6 +462,7 @@ ssh_agent_sign(int sock, struct sshkey *key,
449 return SSH_ERR_ALLOC_FAIL; 462 return SSH_ERR_ALLOC_FAIL;
450 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) 463 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
451 goto out; 464 goto out;
465 flags |= agent_encode_alg(key, alg);
452 if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || 466 if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
453 (r = sshbuf_put_string(msg, blob, blen)) != 0 || 467 (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
454 (r = sshbuf_put_string(msg, data, datalen)) != 0 || 468 (r = sshbuf_put_string(msg, data, datalen)) != 0 ||
diff --git a/authfd.h b/authfd.h
index bea20c26b..4b417e3f4 100644
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfd.h,v 1.38 2015/01/14 20:05:27 djm Exp $ */ 1/* $OpenBSD: authfd.h,v 1.39 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -41,7 +41,7 @@ int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
41 u_char session_id[16], u_char response[16]); 41 u_char session_id[16], u_char response[16]);
42int ssh_agent_sign(int sock, struct sshkey *key, 42int ssh_agent_sign(int sock, struct sshkey *key,
43 u_char **sigp, size_t *lenp, 43 u_char **sigp, size_t *lenp,
44 const u_char *data, size_t datalen, u_int compat); 44 const u_char *data, size_t datalen, const char *alg, u_int compat);
45 45
46/* Messages for the authentication agent connection. */ 46/* Messages for the authentication agent connection. */
47#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 47#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
@@ -86,5 +86,7 @@ int ssh_agent_sign(int sock, struct sshkey *key,
86#define SSH_COM_AGENT2_FAILURE 102 86#define SSH_COM_AGENT2_FAILURE 102
87 87
88#define SSH_AGENT_OLD_SIGNATURE 0x01 88#define SSH_AGENT_OLD_SIGNATURE 0x01
89#define SSH_AGENT_RSA_SHA2_256 0x02
90#define SSH_AGENT_RSA_SHA2_512 0x04
89 91
90#endif /* AUTHFD_H */ 92#endif /* AUTHFD_H */
diff --git a/kex.c b/kex.c
index b409f276b..c1371c432 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.112 2015/11/13 04:39:35 djm Exp $ */ 1/* $OpenBSD: kex.c,v 1.113 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -334,6 +334,20 @@ kex_reset_dispatch(struct ssh *ssh)
334 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); 334 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
335} 335}
336 336
337static int
338kex_send_ext_info(struct ssh *ssh)
339{
340 int r;
341
342 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
343 (r = sshpkt_put_u32(ssh, 1)) != 0 ||
344 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
345 (r = sshpkt_put_cstring(ssh, "rsa-sha2-256,rsa-sha2-512")) != 0 ||
346 (r = sshpkt_send(ssh)) != 0)
347 return r;
348 return 0;
349}
350
337int 351int
338kex_send_newkeys(struct ssh *ssh) 352kex_send_newkeys(struct ssh *ssh)
339{ 353{
@@ -346,9 +360,51 @@ kex_send_newkeys(struct ssh *ssh)
346 debug("SSH2_MSG_NEWKEYS sent"); 360 debug("SSH2_MSG_NEWKEYS sent");
347 debug("expecting SSH2_MSG_NEWKEYS"); 361 debug("expecting SSH2_MSG_NEWKEYS");
348 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); 362 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
363 if (ssh->kex->ext_info_c)
364 if ((r = kex_send_ext_info(ssh)) != 0)
365 return r;
349 return 0; 366 return 0;
350} 367}
351 368
369int
370kex_input_ext_info(int type, u_int32_t seq, void *ctxt)
371{
372 struct ssh *ssh = ctxt;
373 struct kex *kex = ssh->kex;
374 u_int32_t i, ninfo;
375 char *name, *val, *found;
376 int r;
377
378 debug("SSH2_MSG_EXT_INFO received");
379 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
380 if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
381 return r;
382 for (i = 0; i < ninfo; i++) {
383 if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
384 return r;
385 if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) {
386 free(name);
387 return r;
388 }
389 debug("%s: %s=<%s>", __func__, name, val);
390 if (strcmp(name, "server-sig-algs") == 0) {
391 found = match_list("rsa-sha2-256", val, NULL);
392 if (found) {
393 kex->rsa_sha2 = 256;
394 free(found);
395 }
396 found = match_list("rsa-sha2-512", val, NULL);
397 if (found) {
398 kex->rsa_sha2 = 512;
399 free(found);
400 }
401 }
402 free(name);
403 free(val);
404 }
405 return sshpkt_get_end(ssh);
406}
407
352static int 408static int
353kex_input_newkeys(int type, u_int32_t seq, void *ctxt) 409kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
354{ 410{
@@ -531,6 +587,8 @@ kex_free(struct kex *kex)
531 free(kex->client_version_string); 587 free(kex->client_version_string);
532 free(kex->server_version_string); 588 free(kex->server_version_string);
533 free(kex->failed_choice); 589 free(kex->failed_choice);
590 free(kex->hostkey_alg);
591 free(kex->name);
534 free(kex); 592 free(kex);
535} 593}
536 594
@@ -627,17 +685,16 @@ choose_kex(struct kex *k, char *client, char *server)
627static int 685static int
628choose_hostkeyalg(struct kex *k, char *client, char *server) 686choose_hostkeyalg(struct kex *k, char *client, char *server)
629{ 687{
630 char *hostkeyalg = match_list(client, server, NULL); 688 k->hostkey_alg = match_list(client, server, NULL);
631 689
632 debug("kex: host key algorithm: %s", 690 debug("kex: host key algorithm: %s",
633 hostkeyalg ? hostkeyalg : "(no match)"); 691 k->hostkey_alg ? k->hostkey_alg : "(no match)");
634 if (hostkeyalg == NULL) 692 if (k->hostkey_alg == NULL)
635 return SSH_ERR_NO_HOSTKEY_ALG_MATCH; 693 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
636 k->hostkey_type = sshkey_type_from_name(hostkeyalg); 694 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
637 if (k->hostkey_type == KEY_UNSPEC) 695 if (k->hostkey_type == KEY_UNSPEC)
638 return SSH_ERR_INTERNAL_ERROR; 696 return SSH_ERR_INTERNAL_ERROR;
639 k->hostkey_nid = sshkey_ecdsa_nid_from_name(hostkeyalg); 697 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
640 free(hostkeyalg);
641 return 0; 698 return 0;
642} 699}
643 700
@@ -702,6 +759,17 @@ kex_choose_conf(struct ssh *ssh)
702 } 759 }
703 } 760 }
704 761
762 /* Check whether client supports ext_info_c */
763 if (kex->server) {
764 char *ext;
765
766 ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
767 if (ext) {
768 kex->ext_info_c = 1;
769 free(ext);
770 }
771 }
772
705 /* Algorithm Negotiation */ 773 /* Algorithm Negotiation */
706 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], 774 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
707 sprop[PROPOSAL_KEX_ALGS])) != 0) { 775 sprop[PROPOSAL_KEX_ALGS])) != 0) {
diff --git a/kex.h b/kex.h
index d71b53293..25ccf2e0e 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.73 2015/07/30 00:01:34 djm Exp $ */ 1/* $OpenBSD: kex.h,v 1.74 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -129,10 +129,13 @@ struct kex {
129 u_int dh_need; 129 u_int dh_need;
130 int server; 130 int server;
131 char *name; 131 char *name;
132 char *hostkey_alg;
132 int hostkey_type; 133 int hostkey_type;
133 int hostkey_nid; 134 int hostkey_nid;
134 u_int kex_type; 135 u_int kex_type;
135 int roaming; 136 int roaming;
137 int rsa_sha2;
138 int ext_info_c;
136 struct sshbuf *my; 139 struct sshbuf *my;
137 struct sshbuf *peer; 140 struct sshbuf *peer;
138 sig_atomic_t done; 141 sig_atomic_t done;
@@ -146,8 +149,8 @@ struct kex {
146 struct sshkey *(*load_host_public_key)(int, int, struct ssh *); 149 struct sshkey *(*load_host_public_key)(int, int, struct ssh *);
147 struct sshkey *(*load_host_private_key)(int, int, struct ssh *); 150 struct sshkey *(*load_host_private_key)(int, int, struct ssh *);
148 int (*host_key_index)(struct sshkey *, int, struct ssh *); 151 int (*host_key_index)(struct sshkey *, int, struct ssh *);
149 int (*sign)(struct sshkey *, struct sshkey *, 152 int (*sign)(struct sshkey *, struct sshkey *, u_char **, size_t *,
150 u_char **, size_t *, const u_char *, size_t, u_int); 153 const u_char *, size_t, const char *, u_int);
151 int (*kex[KEX_MAX])(struct ssh *); 154 int (*kex[KEX_MAX])(struct ssh *);
152 /* kex specific state */ 155 /* kex specific state */
153 DH *dh; /* DH */ 156 DH *dh; /* DH */
@@ -174,6 +177,7 @@ void kex_prop_free(char **);
174 177
175int kex_send_kexinit(struct ssh *); 178int kex_send_kexinit(struct ssh *);
176int kex_input_kexinit(int, u_int32_t, void *); 179int kex_input_kexinit(int, u_int32_t, void *);
180int kex_input_ext_info(int, u_int32_t, void *);
177int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); 181int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *);
178int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *); 182int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *);
179int kex_send_newkeys(struct ssh *); 183int kex_send_newkeys(struct ssh *);
diff --git a/kexc25519s.c b/kexc25519s.c
index 240272533..4e77622b0 100644
--- a/kexc25519s.c
+++ b/kexc25519s.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519s.c,v 1.9 2015/04/27 00:37:53 dtucker Exp $ */ 1/* $OpenBSD: kexc25519s.c,v 1.10 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -134,8 +134,8 @@ input_kex_c25519_init(int type, u_int32_t seq, void *ctxt)
134 } 134 }
135 135
136 /* sign H */ 136 /* sign H */
137 if ((r = kex->sign(server_host_private, server_host_public, 137 if ((r = kex->sign(server_host_private, server_host_public, &signature,
138 &signature, &slen, hash, hashlen, ssh->compat)) < 0) 138 &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
139 goto out; 139 goto out;
140 140
141 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ 141 /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
diff --git a/kexdhs.c b/kexdhs.c
index de7c05b17..bf933e4c9 100644
--- a/kexdhs.c
+++ b/kexdhs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexdhs.c,v 1.22 2015/01/26 06:10:03 djm Exp $ */ 1/* $OpenBSD: kexdhs.c,v 1.23 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -181,8 +181,8 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
181 } 181 }
182 182
183 /* sign H */ 183 /* sign H */
184 if ((r = kex->sign(server_host_private, server_host_public, 184 if ((r = kex->sign(server_host_private, server_host_public, &signature,
185 &signature, &slen, hash, hashlen, ssh->compat)) < 0) 185 &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
186 goto out; 186 goto out;
187 187
188 /* destroy_sensitive_data(); */ 188 /* destroy_sensitive_data(); */
diff --git a/kexecdhs.c b/kexecdhs.c
index 0adb80e6a..ccdbf70b1 100644
--- a/kexecdhs.c
+++ b/kexecdhs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexecdhs.c,v 1.14 2015/01/26 06:10:03 djm Exp $ */ 1/* $OpenBSD: kexecdhs.c,v 1.15 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -169,8 +169,8 @@ input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt)
169 } 169 }
170 170
171 /* sign H */ 171 /* sign H */
172 if ((r = kex->sign(server_host_private, server_host_public, 172 if ((r = kex->sign(server_host_private, server_host_public, &signature,
173 &signature, &slen, hash, hashlen, ssh->compat)) < 0) 173 &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
174 goto out; 174 goto out;
175 175
176 /* destroy_sensitive_data(); */ 176 /* destroy_sensitive_data(); */
diff --git a/kexgexs.c b/kexgexs.c
index ff6c6879e..8c5adf7e4 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexgexs.c,v 1.25 2015/04/13 02:04:08 djm Exp $ */ 1/* $OpenBSD: kexgexs.c,v 1.26 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * 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)
220 } 220 }
221 221
222 /* sign H */ 222 /* sign H */
223 if ((r = kex->sign(server_host_private, server_host_public, 223 if ((r = kex->sign(server_host_private, server_host_public, &signature,
224 &signature, &slen, hash, hashlen, ssh->compat)) < 0) 224 &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
225 goto out; 225 goto out;
226 226
227 /* destroy_sensitive_data(); */ 227 /* destroy_sensitive_data(); */
diff --git a/key.c b/key.c
index 0ba98b6f3..28d7c6207 100644
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.c,v 1.128 2015/07/03 03:43:18 djm Exp $ */ 1/* $OpenBSD: key.c,v 1.129 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * placed in the public domain 3 * placed in the public domain
4 */ 4 */
@@ -132,7 +132,7 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
132 132
133int 133int
134key_sign(const Key *key, u_char **sigp, u_int *lenp, 134key_sign(const Key *key, u_char **sigp, u_int *lenp,
135 const u_char *data, u_int datalen) 135 const u_char *data, u_int datalen, const char *alg)
136{ 136{
137 int r; 137 int r;
138 u_char *sig; 138 u_char *sig;
@@ -143,7 +143,7 @@ key_sign(const Key *key, u_char **sigp, u_int *lenp,
143 if (lenp != NULL) 143 if (lenp != NULL)
144 *lenp = 0; 144 *lenp = 0;
145 if ((r = sshkey_sign(key, &sig, &siglen, 145 if ((r = sshkey_sign(key, &sig, &siglen,
146 data, datalen, datafellows)) != 0) { 146 data, datalen, alg, datafellows)) != 0) {
147 fatal_on_fatal_errors(r, __func__, 0); 147 fatal_on_fatal_errors(r, __func__, 0);
148 error("%s: %s", __func__, ssh_err(r)); 148 error("%s: %s", __func__, ssh_err(r));
149 return -1; 149 return -1;
diff --git a/key.h b/key.h
index 903bdf673..34c992bd3 100644
--- a/key.h
+++ b/key.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.h,v 1.48 2015/07/03 03:43:18 djm Exp $ */ 1/* $OpenBSD: key.h,v 1.49 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -84,7 +84,8 @@ int key_ec_validate_private(const EC_KEY *);
84Key *key_from_blob(const u_char *, u_int); 84Key *key_from_blob(const u_char *, u_int);
85int key_to_blob(const Key *, u_char **, u_int *); 85int key_to_blob(const Key *, u_char **, u_int *);
86 86
87int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 87int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int,
88 const char *);
88int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 89int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
89 90
90void key_private_serialize(const Key *, struct sshbuf *); 91void key_private_serialize(const Key *, struct sshbuf *);
diff --git a/krl.c b/krl.c
index 570a4f747..0194f1c72 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.c,v 1.34 2015/09/02 07:51:12 jsg Exp $ */ 17/* $OpenBSD: krl.c,v 1.35 2015/12/04 16:41:28 markus Exp $ */
18 18
19#include "includes.h" 19#include "includes.h"
20 20
@@ -772,7 +772,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
772 goto out; 772 goto out;
773 773
774 if ((r = sshkey_sign(sign_keys[i], &sblob, &slen, 774 if ((r = sshkey_sign(sign_keys[i], &sblob, &slen,
775 sshbuf_ptr(buf), sshbuf_len(buf), 0)) != 0) 775 sshbuf_ptr(buf), sshbuf_len(buf), NULL, 0)) != 0)
776 goto out; 776 goto out;
777 KRL_DBG(("%s: signature sig len %zu", __func__, slen)); 777 KRL_DBG(("%s: signature sig len %zu", __func__, slen));
778 if ((r = sshbuf_put_string(buf, sblob, slen)) != 0) 778 if ((r = sshbuf_put_string(buf, sblob, slen)) != 0)
diff --git a/monitor.c b/monitor.c
index 4060a6ec9..b3edd648b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.154 2015/10/20 23:24:25 mmcc Exp $ */ 1/* $OpenBSD: monitor.c,v 1.155 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -688,14 +688,16 @@ mm_answer_sign(int sock, Buffer *m)
688 struct sshbuf *sigbuf; 688 struct sshbuf *sigbuf;
689 u_char *p; 689 u_char *p;
690 u_char *signature; 690 u_char *signature;
691 size_t datlen, siglen; 691 char *alg;
692 size_t datlen, siglen, alglen;
692 int r, keyid, is_proof = 0; 693 int r, keyid, is_proof = 0;
693 const char proof_req[] = "hostkeys-prove-00@openssh.com"; 694 const char proof_req[] = "hostkeys-prove-00@openssh.com";
694 695
695 debug3("%s", __func__); 696 debug3("%s", __func__);
696 697
697 if ((r = sshbuf_get_u32(m, &keyid)) != 0 || 698 if ((r = sshbuf_get_u32(m, &keyid)) != 0 ||
698 (r = sshbuf_get_string(m, &p, &datlen)) != 0) 699 (r = sshbuf_get_string(m, &p, &datlen)) != 0 ||
700 (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0)
699 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 701 fatal("%s: buffer error: %s", __func__, ssh_err(r));
700 702
701 /* 703 /*
@@ -742,14 +744,14 @@ mm_answer_sign(int sock, Buffer *m)
742 } 744 }
743 745
744 if ((key = get_hostkey_by_index(keyid)) != NULL) { 746 if ((key = get_hostkey_by_index(keyid)) != NULL) {
745 if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, 747 if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg,
746 datafellows)) != 0) 748 datafellows)) != 0)
747 fatal("%s: sshkey_sign failed: %s", 749 fatal("%s: sshkey_sign failed: %s",
748 __func__, ssh_err(r)); 750 __func__, ssh_err(r));
749 } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && 751 } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
750 auth_sock > 0) { 752 auth_sock > 0) {
751 if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, 753 if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
752 p, datlen, datafellows)) != 0) { 754 p, datlen, alg, datafellows)) != 0) {
753 fatal("%s: ssh_agent_sign failed: %s", 755 fatal("%s: ssh_agent_sign failed: %s",
754 __func__, ssh_err(r)); 756 __func__, ssh_err(r));
755 } 757 }
diff --git a/monitor_wrap.c b/monitor_wrap.c
index eac421ba1..d4bfaf372 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor_wrap.c,v 1.85 2015/05/01 03:23:51 djm Exp $ */ 1/* $OpenBSD: monitor_wrap.c,v 1.86 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -218,7 +218,7 @@ mm_choose_dh(int min, int nbits, int max)
218 218
219int 219int
220mm_key_sign(Key *key, u_char **sigp, u_int *lenp, 220mm_key_sign(Key *key, u_char **sigp, u_int *lenp,
221 const u_char *data, u_int datalen) 221 const u_char *data, u_int datalen, const char *hostkey_alg)
222{ 222{
223 struct kex *kex = *pmonitor->m_pkex; 223 struct kex *kex = *pmonitor->m_pkex;
224 Buffer m; 224 Buffer m;
@@ -228,6 +228,7 @@ mm_key_sign(Key *key, u_char **sigp, u_int *lenp,
228 buffer_init(&m); 228 buffer_init(&m);
229 buffer_put_int(&m, kex->host_key_index(key, 0, active_state)); 229 buffer_put_int(&m, kex->host_key_index(key, 0, active_state));
230 buffer_put_string(&m, data, datalen); 230 buffer_put_string(&m, data, datalen);
231 buffer_put_cstring(&m, hostkey_alg);
231 232
232 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); 233 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
233 234
diff --git a/monitor_wrap.h b/monitor_wrap.h
index 9a6aff684..eb820aeea 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor_wrap.h,v 1.28 2015/11/11 01:48:01 djm Exp $ */ 1/* $OpenBSD: monitor_wrap.h,v 1.29 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -40,7 +40,7 @@ struct Authctxt;
40void mm_log_handler(LogLevel, const char *, void *); 40void mm_log_handler(LogLevel, const char *, void *);
41int mm_is_monitor(void); 41int mm_is_monitor(void);
42DH *mm_choose_dh(int, int, int); 42DH *mm_choose_dh(int, int, int);
43int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int); 43int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int, const char *);
44void mm_inform_authserv(char *, char *); 44void mm_inform_authserv(char *, char *);
45struct passwd *mm_getpwnamallow(const char *); 45struct passwd *mm_getpwnamallow(const char *);
46char *mm_auth2_read_banner(void); 46char *mm_auth2_read_banner(void);
diff --git a/myproposal.h b/myproposal.h
index 46e5b988d..c6429588a 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: myproposal.h,v 1.47 2015/07/10 06:21:53 markus Exp $ */ 1/* $OpenBSD: myproposal.h,v 1.48 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -101,7 +101,9 @@
101 "ssh-rsa-cert-v01@openssh.com," \ 101 "ssh-rsa-cert-v01@openssh.com," \
102 HOSTKEY_ECDSA_METHODS \ 102 HOSTKEY_ECDSA_METHODS \
103 "ssh-ed25519," \ 103 "ssh-ed25519," \
104 "ssh-rsa" \ 104 "rsa-sha2-256," \
105 "rsa-sha2-512," \
106 "ssh-rsa"
105 107
106/* the actual algorithms */ 108/* the actual algorithms */
107 109
diff --git a/packet.c b/packet.c
index 4f6433b47..378906956 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.217 2015/11/08 21:59:11 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.218 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1215,7 +1215,8 @@ ssh_packet_send2(struct ssh *ssh)
1215 if ((type < SSH2_MSG_TRANSPORT_MIN) || 1215 if ((type < SSH2_MSG_TRANSPORT_MIN) ||
1216 (type > SSH2_MSG_TRANSPORT_MAX) || 1216 (type > SSH2_MSG_TRANSPORT_MAX) ||
1217 (type == SSH2_MSG_SERVICE_REQUEST) || 1217 (type == SSH2_MSG_SERVICE_REQUEST) ||
1218 (type == SSH2_MSG_SERVICE_ACCEPT)) { 1218 (type == SSH2_MSG_SERVICE_ACCEPT) ||
1219 (type == SSH2_MSG_EXT_INFO)) {
1219 debug("enqueue packet: %u", type); 1220 debug("enqueue packet: %u", type);
1220 p = calloc(1, sizeof(*p)); 1221 p = calloc(1, sizeof(*p));
1221 if (p == NULL) 1222 if (p == NULL)
diff --git a/serverloop.c b/serverloop.c
index 4d0c0edb1..85fc8d3af 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.179 2015/11/28 06:41:03 djm Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.180 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1201,7 +1201,7 @@ server_input_hostkeys_prove(struct sshbuf **respp)
1201 ssh->kex->session_id, ssh->kex->session_id_len)) != 0 || 1201 ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
1202 (r = sshkey_puts(key, sigbuf)) != 0 || 1202 (r = sshkey_puts(key, sigbuf)) != 0 ||
1203 (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen, 1203 (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
1204 sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), 0)) != 0 || 1204 sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), NULL, 0)) != 0 ||
1205 (r = sshbuf_put_string(resp, sig, slen)) != 0) { 1205 (r = sshbuf_put_string(resp, sig, slen)) != 0) {
1206 error("%s: couldn't prepare signature: %s", 1206 error("%s: couldn't prepare signature: %s",
1207 __func__, ssh_err(r)); 1207 __func__, ssh_err(r));
diff --git a/ssh-agent.c b/ssh-agent.c
index 2a7ae88f9..ed5dc571d 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.207 2015/12/02 08:30:50 doug Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.208 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -368,6 +368,18 @@ process_authentication_challenge1(SocketEntry *e)
368} 368}
369#endif 369#endif
370 370
371static char *
372agent_decode_alg(struct sshkey *key, u_int flags)
373{
374 if (key->type == KEY_RSA) {
375 if (flags & SSH_AGENT_RSA_SHA2_256)
376 return "rsa-sha2-256";
377 else if (flags & SSH_AGENT_RSA_SHA2_512)
378 return "rsa-sha2-512";
379 }
380 return NULL;
381}
382
371/* ssh2 only */ 383/* ssh2 only */
372static void 384static void
373process_sign_request2(SocketEntry *e) 385process_sign_request2(SocketEntry *e)
@@ -401,7 +413,7 @@ process_sign_request2(SocketEntry *e)
401 goto send; 413 goto send;
402 } 414 }
403 if ((r = sshkey_sign(id->key, &signature, &slen, 415 if ((r = sshkey_sign(id->key, &signature, &slen,
404 data, dlen, compat)) != 0) { 416 data, dlen, agent_decode_alg(key, flags), compat)) != 0) {
405 error("%s: sshkey_sign: %s", __func__, ssh_err(ok)); 417 error("%s: sshkey_sign: %s", __func__, ssh_err(ok));
406 goto send; 418 goto send;
407 } 419 }
diff --git a/ssh-keygen.c b/ssh-keygen.c
index f6a1c2847..6ac1fa603 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.284 2015/11/28 06:50:52 deraadt Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.285 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * 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)
523 sshbuf_free(b); 523 sshbuf_free(b);
524 524
525 /* try the key */ 525 /* try the key */
526 if (sshkey_sign(key, &sig, &slen, data, sizeof(data), 0) != 0 || 526 if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 ||
527 sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) { 527 sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) {
528 sshkey_free(key); 528 sshkey_free(key);
529 free(sig); 529 free(sig);
diff --git a/ssh-keysign.c b/ssh-keysign.c
index 4c99609b2..1d49861ae 100644
--- a/ssh-keysign.c
+++ b/ssh-keysign.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keysign.c,v 1.50 2015/11/29 22:18:37 djm Exp $ */ 1/* $OpenBSD: ssh-keysign.c,v 1.51 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2002 Markus Friedl. All rights reserved. 3 * Copyright (c) 2002 Markus Friedl. All rights reserved.
4 * 4 *
@@ -291,7 +291,8 @@ main(int argc, char **argv)
291 sshkey_type(key), fp ? fp : ""); 291 sshkey_type(key), fp ? fp : "");
292 } 292 }
293 293
294 if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, 0)) != 0) 294 if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, NULL, 0))
295 != 0)
295 fatal("sshkey_sign failed: %s", ssh_err(r)); 296 fatal("sshkey_sign failed: %s", ssh_err(r));
296 free(data); 297 free(data);
297 298
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 08090d14e..81dab05b3 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-rsa.c,v 1.54 2015/09/09 00:52:44 djm Exp $ */ 1/* $OpenBSD: ssh-rsa.c,v 1.55 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
4 * 4 *
@@ -36,16 +36,60 @@
36 36
37static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); 37static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
38 38
39static const char *
40rsa_hash_alg_ident(int hash_alg)
41{
42 switch (hash_alg) {
43 case SSH_DIGEST_SHA1:
44 return "ssh-rsa";
45 case SSH_DIGEST_SHA256:
46 return "rsa-sha2-256";
47 case SSH_DIGEST_SHA512:
48 return "rsa-sha2-512";
49 }
50 return NULL;
51}
52
53static int
54rsa_hash_alg_from_ident(const char *ident)
55{
56 if (ident == NULL || strlen(ident) == 0)
57 return SSH_DIGEST_SHA1;
58 if (strcmp(ident, "ssh-rsa") == 0)
59 return SSH_DIGEST_SHA1;
60 if (strcmp(ident, "rsa-sha2-256") == 0)
61 return SSH_DIGEST_SHA256;
62 if (strcmp(ident, "rsa-sha2-512") == 0)
63 return SSH_DIGEST_SHA512;
64 if (strncmp(ident, "ssh-rsa-cert", strlen("ssh-rsa-cert")) == 0)
65 return SSH_DIGEST_SHA1;
66 return -1;
67}
68
69static int
70rsa_hash_alg_nid(int type)
71{
72 switch (type) {
73 case SSH_DIGEST_SHA1:
74 return NID_sha1;
75 case SSH_DIGEST_SHA256:
76 return NID_sha256;
77 case SSH_DIGEST_SHA512:
78 return NID_sha512;
79 default:
80 return -1;
81 }
82}
83
39/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 84/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
40int 85int
41ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 86ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
42 const u_char *data, size_t datalen, u_int compat) 87 const u_char *data, size_t datalen, const char *alg_ident)
43{ 88{
44 int hash_alg;
45 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; 89 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
46 size_t slen; 90 size_t slen;
47 u_int dlen, len; 91 u_int dlen, len;
48 int nid, ret = SSH_ERR_INTERNAL_ERROR; 92 int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
49 struct sshbuf *b = NULL; 93 struct sshbuf *b = NULL;
50 94
51 if (lenp != NULL) 95 if (lenp != NULL)
@@ -53,16 +97,17 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
53 if (sigp != NULL) 97 if (sigp != NULL)
54 *sigp = NULL; 98 *sigp = NULL;
55 99
56 if (key == NULL || key->rsa == NULL || 100 hash_alg = rsa_hash_alg_from_ident(alg_ident);
57 sshkey_type_plain(key->type) != KEY_RSA) 101 if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
102 sshkey_type_plain(key->type) != KEY_RSA ||
103 BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
58 return SSH_ERR_INVALID_ARGUMENT; 104 return SSH_ERR_INVALID_ARGUMENT;
59 slen = RSA_size(key->rsa); 105 slen = RSA_size(key->rsa);
60 if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) 106 if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
61 return SSH_ERR_INVALID_ARGUMENT; 107 return SSH_ERR_INVALID_ARGUMENT;
62 108
63 /* hash the data */ 109 /* hash the data */
64 hash_alg = SSH_DIGEST_SHA1; 110 nid = rsa_hash_alg_nid(hash_alg);
65 nid = NID_sha1;
66 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) 111 if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
67 return SSH_ERR_INTERNAL_ERROR; 112 return SSH_ERR_INTERNAL_ERROR;
68 if ((ret = ssh_digest_memory(hash_alg, data, datalen, 113 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,
91 ret = SSH_ERR_ALLOC_FAIL; 136 ret = SSH_ERR_ALLOC_FAIL;
92 goto out; 137 goto out;
93 } 138 }
94 if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 || 139 if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
95 (ret = sshbuf_put_string(b, sig, slen)) != 0) 140 (ret = sshbuf_put_string(b, sig, slen)) != 0)
96 goto out; 141 goto out;
97 len = sshbuf_len(b); 142 len = sshbuf_len(b);
@@ -118,8 +163,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
118 163
119int 164int
120ssh_rsa_verify(const struct sshkey *key, 165ssh_rsa_verify(const struct sshkey *key,
121 const u_char *signature, size_t signaturelen, 166 const u_char *sig, size_t siglen, const u_char *data, size_t datalen)
122 const u_char *data, size_t datalen, u_int compat)
123{ 167{
124 char *ktype = NULL; 168 char *ktype = NULL;
125 int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 169 int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
@@ -132,13 +176,13 @@ ssh_rsa_verify(const struct sshkey *key,
132 BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 176 BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
133 return SSH_ERR_INVALID_ARGUMENT; 177 return SSH_ERR_INVALID_ARGUMENT;
134 178
135 if ((b = sshbuf_from(signature, signaturelen)) == NULL) 179 if ((b = sshbuf_from(sig, siglen)) == NULL)
136 return SSH_ERR_ALLOC_FAIL; 180 return SSH_ERR_ALLOC_FAIL;
137 if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { 181 if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
138 ret = SSH_ERR_INVALID_FORMAT; 182 ret = SSH_ERR_INVALID_FORMAT;
139 goto out; 183 goto out;
140 } 184 }
141 if (strcmp("ssh-rsa", ktype) != 0) { 185 if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) {
142 ret = SSH_ERR_KEY_TYPE_MISMATCH; 186 ret = SSH_ERR_KEY_TYPE_MISMATCH;
143 goto out; 187 goto out;
144 } 188 }
@@ -167,7 +211,6 @@ ssh_rsa_verify(const struct sshkey *key,
167 explicit_bzero(sigblob, diff); 211 explicit_bzero(sigblob, diff);
168 len = modlen; 212 len = modlen;
169 } 213 }
170 hash_alg = SSH_DIGEST_SHA1;
171 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 214 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
172 ret = SSH_ERR_INTERNAL_ERROR; 215 ret = SSH_ERR_INTERNAL_ERROR;
173 goto out; 216 goto out;
@@ -196,6 +239,7 @@ ssh_rsa_verify(const struct sshkey *key,
196 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ 239 * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
197 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn 240 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
198 */ 241 */
242
199/* 243/*
200 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) 244 * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
201 * oiw(14) secsig(3) algorithms(2) 26 } 245 * oiw(14) secsig(3) algorithms(2) 26 }
@@ -209,6 +253,58 @@ static const u_char id_sha1[] = {
209 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 253 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
210}; 254};
211 255
256/*
257 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
258 * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
259 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
260 * id-sha256(1) }
261 */
262static const u_char id_sha256[] = {
263 0x30, 0x31, /* type Sequence, length 0x31 (49) */
264 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
265 0x06, 0x09, /* type OID, length 0x09 */
266 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
267 0x05, 0x00, /* NULL */
268 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
269};
270
271/*
272 * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
273 * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
274 * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
275 * id-sha256(3) }
276 */
277static const u_char id_sha512[] = {
278 0x30, 0x51, /* type Sequence, length 0x51 (81) */
279 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
280 0x06, 0x09, /* type OID, length 0x09 */
281 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
282 0x05, 0x00, /* NULL */
283 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
284};
285
286static int
287rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
288{
289 switch (hash_alg) {
290 case SSH_DIGEST_SHA1:
291 *oidp = id_sha1;
292 *oidlenp = sizeof(id_sha1);
293 break;
294 case SSH_DIGEST_SHA256:
295 *oidp = id_sha256;
296 *oidlenp = sizeof(id_sha256);
297 break;
298 case SSH_DIGEST_SHA512:
299 *oidp = id_sha512;
300 *oidlenp = sizeof(id_sha512);
301 break;
302 default:
303 return SSH_ERR_INVALID_ARGUMENT;
304 }
305 return 0;
306}
307
212static int 308static int
213openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, 309openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
214 u_char *sigbuf, size_t siglen, RSA *rsa) 310 u_char *sigbuf, size_t siglen, RSA *rsa)
@@ -218,16 +314,10 @@ openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
218 const u_char *oid = NULL; 314 const u_char *oid = NULL;
219 u_char *decrypted = NULL; 315 u_char *decrypted = NULL;
220 316
317 if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
318 return ret;
221 ret = SSH_ERR_INTERNAL_ERROR; 319 ret = SSH_ERR_INTERNAL_ERROR;
222 switch (hash_alg) { 320 hlen = ssh_digest_bytes(hash_alg);
223 case SSH_DIGEST_SHA1:
224 oid = id_sha1;
225 oidlen = sizeof(id_sha1);
226 hlen = 20;
227 break;
228 default:
229 goto done;
230 }
231 if (hashlen != hlen) { 321 if (hashlen != hlen) {
232 ret = SSH_ERR_INVALID_ARGUMENT; 322 ret = SSH_ERR_INVALID_ARGUMENT;
233 goto done; 323 goto done;
diff --git a/ssh2.h b/ssh2.h
index 59417e612..bdff6c5bd 100644
--- a/ssh2.h
+++ b/ssh2.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh2.h,v 1.15 2014/01/29 06:18:35 djm Exp $ */ 1/* $OpenBSD: ssh2.h,v 1.16 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -80,6 +80,7 @@
80#define SSH2_MSG_DEBUG 4 80#define SSH2_MSG_DEBUG 4
81#define SSH2_MSG_SERVICE_REQUEST 5 81#define SSH2_MSG_SERVICE_REQUEST 5
82#define SSH2_MSG_SERVICE_ACCEPT 6 82#define SSH2_MSG_SERVICE_ACCEPT 6
83#define SSH2_MSG_EXT_INFO 7
83 84
84/* transport layer: alg negotiation */ 85/* transport layer: alg negotiation */
85 86
diff --git a/ssh_api.c b/ssh_api.c
index 6c712584f..f544f006b 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh_api.c,v 1.4 2015/02/16 22:13:32 djm Exp $ */ 1/* $OpenBSD: ssh_api.c,v 1.5 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2012 Markus Friedl. All rights reserved. 3 * Copyright (c) 2012 Markus Friedl. All rights reserved.
4 * 4 *
@@ -40,8 +40,8 @@ int _ssh_order_hostkeyalgs(struct ssh *);
40int _ssh_verify_host_key(struct sshkey *, struct ssh *); 40int _ssh_verify_host_key(struct sshkey *, struct ssh *);
41struct sshkey *_ssh_host_public_key(int, int, struct ssh *); 41struct sshkey *_ssh_host_public_key(int, int, struct ssh *);
42struct sshkey *_ssh_host_private_key(int, int, struct ssh *); 42struct sshkey *_ssh_host_private_key(int, int, struct ssh *);
43int _ssh_host_key_sign(struct sshkey *, struct sshkey *, u_char **, 43int _ssh_host_key_sign(struct sshkey *, struct sshkey *,
44 size_t *, const u_char *, size_t, u_int); 44 u_char **, size_t *, const u_char *, size_t, const char *, u_int);
45 45
46/* 46/*
47 * stubs for the server side implementation of kex. 47 * stubs for the server side implementation of kex.
@@ -49,7 +49,7 @@ int _ssh_host_key_sign(struct sshkey *, struct sshkey *, u_char **,
49 */ 49 */
50int use_privsep = 0; 50int use_privsep = 0;
51int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, 51int mm_sshkey_sign(struct sshkey *, u_char **, u_int *,
52 u_char *, u_int, u_int); 52 u_char *, u_int, char *, u_int);
53DH *mm_choose_dh(int, int, int); 53DH *mm_choose_dh(int, int, int);
54 54
55/* Define these two variables here so that they are part of the library */ 55/* Define these two variables here so that they are part of the library */
@@ -58,7 +58,7 @@ u_int session_id2_len = 0;
58 58
59int 59int
60mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp, 60mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp,
61 u_char *data, u_int datalen, u_int compat) 61 u_char *data, u_int datalen, char *alg, u_int compat)
62{ 62{
63 return (-1); 63 return (-1);
64} 64}
@@ -530,8 +530,8 @@ _ssh_order_hostkeyalgs(struct ssh *ssh)
530 530
531int 531int
532_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey, 532_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey,
533 u_char **signature, size_t *slen, 533 u_char **signature, size_t *slen, const u_char *data, size_t dlen,
534 const u_char *data, size_t dlen, u_int compat) 534 const char *alg, u_int compat)
535{ 535{
536 return sshkey_sign(privkey, signature, slen, data, dlen, compat); 536 return sshkey_sign(privkey, signature, slen, data, dlen, alg, compat);
537} 537}
diff --git a/sshconnect2.c b/sshconnect2.c
index d29f630f2..da1bd3847 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.230 2015/12/04 00:24:55 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.231 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -157,14 +157,16 @@ void
157ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 157ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
158{ 158{
159 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 159 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
160 char *s;
160 struct kex *kex; 161 struct kex *kex;
161 int r; 162 int r;
162 163
163 xxx_host = host; 164 xxx_host = host;
164 xxx_hostaddr = hostaddr; 165 xxx_hostaddr = hostaddr;
165 166
166 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( 167 if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
167 options.kex_algorithms); 168 fatal("%s: kex_names_cat", __func__);
169 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
168 myproposal[PROPOSAL_ENC_ALGS_CTOS] = 170 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
169 compat_cipher_proposal(options.ciphers); 171 compat_cipher_proposal(options.ciphers);
170 myproposal[PROPOSAL_ENC_ALGS_STOC] = 172 myproposal[PROPOSAL_ENC_ALGS_STOC] =
@@ -221,6 +223,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
221 debug("Roaming not allowed by server"); 223 debug("Roaming not allowed by server");
222 options.use_roaming = 0; 224 options.use_roaming = 0;
223 } 225 }
226 /* remove ext-info from the KEX proposals for rekeying */
227 myproposal[PROPOSAL_KEX_ALGS] =
228 compat_kex_proposal(options.kex_algorithms);
229 if ((r = kex_prop2buf(kex->my, myproposal)) != 0)
230 fatal("kex_prop2buf: %s", ssh_err(r));
224 231
225 session_id2 = kex->session_id; 232 session_id2 = kex->session_id;
226 session_id2_len = kex->session_id_len; 233 session_id2_len = kex->session_id_len;
@@ -284,6 +291,8 @@ struct cauthmethod {
284 int *batch_flag; /* flag in option struct that disables method */ 291 int *batch_flag; /* flag in option struct that disables method */
285}; 292};
286 293
294int input_userauth_service_accept(int, u_int32_t, void *);
295int input_userauth_ext_info(int, u_int32_t, void *);
287int input_userauth_success(int, u_int32_t, void *); 296int input_userauth_success(int, u_int32_t, void *);
288int input_userauth_success_unexpected(int, u_int32_t, void *); 297int input_userauth_success_unexpected(int, u_int32_t, void *);
289int input_userauth_failure(int, u_int32_t, void *); 298int input_userauth_failure(int, u_int32_t, void *);
@@ -359,30 +368,12 @@ void
359ssh_userauth2(const char *local_user, const char *server_user, char *host, 368ssh_userauth2(const char *local_user, const char *server_user, char *host,
360 Sensitive *sensitive) 369 Sensitive *sensitive)
361{ 370{
371 struct ssh *ssh = active_state;
362 Authctxt authctxt; 372 Authctxt authctxt;
363 int type; 373 int r;
364 374
365 if (options.challenge_response_authentication) 375 if (options.challenge_response_authentication)
366 options.kbd_interactive_authentication = 1; 376 options.kbd_interactive_authentication = 1;
367
368 packet_start(SSH2_MSG_SERVICE_REQUEST);
369 packet_put_cstring("ssh-userauth");
370 packet_send();
371 debug("SSH2_MSG_SERVICE_REQUEST sent");
372 packet_write_wait();
373 type = packet_read();
374 if (type != SSH2_MSG_SERVICE_ACCEPT)
375 fatal("Server denied authentication request: %d", type);
376 if (packet_remaining() > 0) {
377 char *reply = packet_get_string(NULL);
378 debug2("service_accept: %s", reply);
379 free(reply);
380 } else {
381 debug2("buggy server: service_accept w/o service");
382 }
383 packet_check_eom();
384 debug("SSH2_MSG_SERVICE_ACCEPT received");
385
386 if (options.preferred_authentications == NULL) 377 if (options.preferred_authentications == NULL)
387 options.preferred_authentications = authmethods_get(); 378 options.preferred_authentications = authmethods_get();
388 379
@@ -404,21 +395,63 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
404 if (authctxt.method == NULL) 395 if (authctxt.method == NULL)
405 fatal("ssh_userauth2: internal error: cannot send userauth none request"); 396 fatal("ssh_userauth2: internal error: cannot send userauth none request");
406 397
407 /* initial userauth request */ 398 if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 ||
408 userauth_none(&authctxt); 399 (r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 ||
400 (r = sshpkt_send(ssh)) != 0)
401 fatal("%s: %s", __func__, ssh_err(r));
409 402
410 dispatch_init(&input_userauth_error); 403 ssh_dispatch_init(ssh, &input_userauth_error);
411 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); 404 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info);
412 dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); 405 ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept);
413 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); 406 ssh_dispatch_run(ssh, DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
414 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
415 407
416 pubkey_cleanup(&authctxt); 408 pubkey_cleanup(&authctxt);
417 dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); 409 ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
418 410
419 debug("Authentication succeeded (%s).", authctxt.method->name); 411 debug("Authentication succeeded (%s).", authctxt.method->name);
420} 412}
421 413
414/* ARGSUSED */
415int
416input_userauth_service_accept(int type, u_int32_t seqnr, void *ctxt)
417{
418 Authctxt *authctxt = ctxt;
419 struct ssh *ssh = active_state;
420 int r;
421
422 if (ssh_packet_remaining(ssh) > 0) {
423 char *reply;
424
425 if ((r = sshpkt_get_cstring(ssh, &reply, NULL)) != 0)
426 goto out;
427 debug2("service_accept: %s", reply);
428 free(reply);
429 } else {
430 debug2("buggy server: service_accept w/o service");
431 }
432 if ((r = sshpkt_get_end(ssh)) != 0)
433 goto out;
434 debug("SSH2_MSG_SERVICE_ACCEPT received");
435
436 /* initial userauth request */
437 userauth_none(authctxt);
438
439 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_error);
440 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
441 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
442 ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
443 r = 0;
444 out:
445 return r;
446}
447
448/* ARGSUSED */
449int
450input_userauth_ext_info(int type, u_int32_t seqnr, void *ctxt)
451{
452 return kex_input_ext_info(type, seqnr, active_state);
453}
454
422void 455void
423userauth(Authctxt *authctxt, char *authlist) 456userauth(Authctxt *authctxt, char *authlist)
424{ 457{
@@ -970,29 +1003,48 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
970 return 0; 1003 return 0;
971} 1004}
972 1005
1006static const char *
1007identity_sign_encode(struct identity *id)
1008{
1009 struct ssh *ssh = active_state;
1010
1011 if (id->key->type == KEY_RSA) {
1012 switch (ssh->kex->rsa_sha2) {
1013 case 256:
1014 return "rsa-sha2-256";
1015 case 512:
1016 return "rsa-sha2-512";
1017 }
1018 }
1019 return key_ssh_name(id->key);
1020}
1021
973static int 1022static int
974identity_sign(struct identity *id, u_char **sigp, size_t *lenp, 1023identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
975 const u_char *data, size_t datalen, u_int compat) 1024 const u_char *data, size_t datalen, u_int compat)
976{ 1025{
977 Key *prv; 1026 Key *prv;
978 int ret; 1027 int ret;
1028 const char *alg;
1029
1030 alg = identity_sign_encode(id);
979 1031
980 /* the agent supports this key */ 1032 /* the agent supports this key */
981 if (id->agent_fd != -1) 1033 if (id->agent_fd != -1)
982 return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, 1034 return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
983 data, datalen, compat); 1035 data, datalen, alg, compat);
984 1036
985 /* 1037 /*
986 * we have already loaded the private key or 1038 * we have already loaded the private key or
987 * the private key is stored in external hardware 1039 * the private key is stored in external hardware
988 */ 1040 */
989 if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)) 1041 if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
990 return (sshkey_sign(id->key, sigp, lenp, data, datalen, 1042 return (sshkey_sign(id->key, sigp, lenp, data, datalen, alg,
991 compat)); 1043 compat));
992 /* load the private key from the file */ 1044 /* load the private key from the file */
993 if ((prv = load_identity_file(id)) == NULL) 1045 if ((prv = load_identity_file(id)) == NULL)
994 return (-1); /* XXX return decent error code */ 1046 return (-1); /* XXX return decent error code */
995 ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat); 1047 ret = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat);
996 sshkey_free(prv); 1048 sshkey_free(prv);
997 return (ret); 1049 return (ret);
998} 1050}
@@ -1039,7 +1091,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1039 } else { 1091 } else {
1040 buffer_put_cstring(&b, authctxt->method->name); 1092 buffer_put_cstring(&b, authctxt->method->name);
1041 buffer_put_char(&b, have_sig); 1093 buffer_put_char(&b, have_sig);
1042 buffer_put_cstring(&b, key_ssh_name(id->key)); 1094 buffer_put_cstring(&b, identity_sign_encode(id));
1043 } 1095 }
1044 buffer_put_string(&b, blob, bloblen); 1096 buffer_put_string(&b, blob, bloblen);
1045 1097
@@ -1139,7 +1191,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id)
1139 packet_put_cstring(authctxt->method->name); 1191 packet_put_cstring(authctxt->method->name);
1140 packet_put_char(have_sig); 1192 packet_put_char(have_sig);
1141 if (!(datafellows & SSH_BUG_PKAUTH)) 1193 if (!(datafellows & SSH_BUG_PKAUTH))
1142 packet_put_cstring(key_ssh_name(id->key)); 1194 packet_put_cstring(identity_sign_encode(id));
1143 packet_put_string(blob, bloblen); 1195 packet_put_string(blob, bloblen);
1144 free(blob); 1196 free(blob);
1145 packet_send(); 1197 packet_send();
@@ -1743,7 +1795,7 @@ userauth_hostbased(Authctxt *authctxt)
1743 r = ssh_keysign(private, &sig, &siglen, 1795 r = ssh_keysign(private, &sig, &siglen,
1744 sshbuf_ptr(b), sshbuf_len(b)); 1796 sshbuf_ptr(b), sshbuf_len(b));
1745 else if ((r = sshkey_sign(private, &sig, &siglen, 1797 else if ((r = sshkey_sign(private, &sig, &siglen,
1746 sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0) 1798 sshbuf_ptr(b), sshbuf_len(b), NULL, datafellows)) != 0)
1747 debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); 1799 debug("%s: sshkey_sign: %s", __func__, ssh_err(r));
1748 if (r != 0) { 1800 if (r != 0) {
1749 error("sign using hostkey %s %s failed", 1801 error("sign using hostkey %s %s failed",
diff --git a/sshd.c b/sshd.c
index a823999b3..2f3f5b551 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.460 2015/11/16 22:51:05 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.461 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -816,6 +816,12 @@ list_hostkey_types(void)
816 buffer_append(&b, ",", 1); 816 buffer_append(&b, ",", 1);
817 p = key_ssh_name(key); 817 p = key_ssh_name(key);
818 buffer_append(&b, p, strlen(p)); 818 buffer_append(&b, p, strlen(p));
819
820 /* for RSA we also support SHA2 signatures */
821 if (key->type == KEY_RSA) {
822 p = ",rsa-sha2-512,rsa-sha2-256";
823 buffer_append(&b, p, strlen(p));
824 }
819 break; 825 break;
820 } 826 }
821 /* If the private key has a cert peer, then list that too */ 827 /* If the private key has a cert peer, then list that too */
@@ -2507,24 +2513,26 @@ do_ssh1_kex(void)
2507 2513
2508int 2514int
2509sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen, 2515sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen,
2510 const u_char *data, size_t dlen, u_int flag) 2516 const u_char *data, size_t dlen, const char *alg, u_int flag)
2511{ 2517{
2512 int r; 2518 int r;
2513 u_int xxx_slen, xxx_dlen = dlen; 2519 u_int xxx_slen, xxx_dlen = dlen;
2514 2520
2515 if (privkey) { 2521 if (privkey) {
2516 if (PRIVSEP(key_sign(privkey, signature, &xxx_slen, data, xxx_dlen) < 0)) 2522 if (PRIVSEP(key_sign(privkey, signature, &xxx_slen, data, xxx_dlen,
2523 alg) < 0))
2517 fatal("%s: key_sign failed", __func__); 2524 fatal("%s: key_sign failed", __func__);
2518 if (slen) 2525 if (slen)
2519 *slen = xxx_slen; 2526 *slen = xxx_slen;
2520 } else if (use_privsep) { 2527 } else if (use_privsep) {
2521 if (mm_key_sign(pubkey, signature, &xxx_slen, data, xxx_dlen) < 0) 2528 if (mm_key_sign(pubkey, signature, &xxx_slen, data, xxx_dlen,
2529 alg) < 0)
2522 fatal("%s: pubkey_sign failed", __func__); 2530 fatal("%s: pubkey_sign failed", __func__);
2523 if (slen) 2531 if (slen)
2524 *slen = xxx_slen; 2532 *slen = xxx_slen;
2525 } else { 2533 } else {
2526 if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slen, 2534 if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slen,
2527 data, dlen, datafellows)) != 0) 2535 data, dlen, alg, datafellows)) != 0)
2528 fatal("%s: ssh_agent_sign failed: %s", 2536 fatal("%s: ssh_agent_sign failed: %s",
2529 __func__, ssh_err(r)); 2537 __func__, ssh_err(r));
2530 } 2538 }
diff --git a/sshkey.c b/sshkey.c
index dc16fe92c..587bf5b84 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.27 2015/11/19 01:08:55 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.28 2015/12/04 16:41:28 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved. 4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -83,36 +83,39 @@ struct keytype {
83 int type; 83 int type;
84 int nid; 84 int nid;
85 int cert; 85 int cert;
86 int sigonly;
86}; 87};
87static const struct keytype keytypes[] = { 88static const struct keytype keytypes[] = {
88 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 }, 89 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },
89 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", 90 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
90 KEY_ED25519_CERT, 0, 1 }, 91 KEY_ED25519_CERT, 0, 1, 0 },
91#ifdef WITH_OPENSSL 92#ifdef WITH_OPENSSL
92 { NULL, "RSA1", KEY_RSA1, 0, 0 }, 93 { NULL, "RSA1", KEY_RSA1, 0, 0, 0 },
93 { "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, 94 { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },
94 { "ssh-dss", "DSA", KEY_DSA, 0, 0 }, 95 { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },
96 { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 },
97 { "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 },
95# ifdef OPENSSL_HAS_ECC 98# ifdef OPENSSL_HAS_ECC
96 { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, 99 { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
97 { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, 100 { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 },
98# ifdef OPENSSL_HAS_NISTP521 101# ifdef OPENSSL_HAS_NISTP521
99 { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, 102 { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 },
100# endif /* OPENSSL_HAS_NISTP521 */ 103# endif /* OPENSSL_HAS_NISTP521 */
101# endif /* OPENSSL_HAS_ECC */ 104# endif /* OPENSSL_HAS_ECC */
102 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 }, 105 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 },
103 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 }, 106 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 },
104# ifdef OPENSSL_HAS_ECC 107# ifdef OPENSSL_HAS_ECC
105 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", 108 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
106 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 }, 109 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
107 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", 110 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
108 KEY_ECDSA_CERT, NID_secp384r1, 1 }, 111 KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
109# ifdef OPENSSL_HAS_NISTP521 112# ifdef OPENSSL_HAS_NISTP521
110 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", 113 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
111 KEY_ECDSA_CERT, NID_secp521r1, 1 }, 114 KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
112# endif /* OPENSSL_HAS_NISTP521 */ 115# endif /* OPENSSL_HAS_NISTP521 */
113# endif /* OPENSSL_HAS_ECC */ 116# endif /* OPENSSL_HAS_ECC */
114#endif /* WITH_OPENSSL */ 117#endif /* WITH_OPENSSL */
115 { NULL, NULL, -1, -1, 0 } 118 { NULL, NULL, -1, -1, 0, 0 }
116}; 119};
117 120
118const char * 121const char *
@@ -200,7 +203,7 @@ key_alg_list(int certs_only, int plain_only)
200 const struct keytype *kt; 203 const struct keytype *kt;
201 204
202 for (kt = keytypes; kt->type != -1; kt++) { 205 for (kt = keytypes; kt->type != -1; kt++) {
203 if (kt->name == NULL) 206 if (kt->name == NULL || kt->sigonly)
204 continue; 207 continue;
205 if ((certs_only && !kt->cert) || (plain_only && kt->cert)) 208 if ((certs_only && !kt->cert) || (plain_only && kt->cert))
206 continue; 209 continue;
@@ -2174,7 +2177,7 @@ sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2174int 2177int
2175sshkey_sign(const struct sshkey *key, 2178sshkey_sign(const struct sshkey *key,
2176 u_char **sigp, size_t *lenp, 2179 u_char **sigp, size_t *lenp,
2177 const u_char *data, size_t datalen, u_int compat) 2180 const u_char *data, size_t datalen, const char *alg, u_int compat)
2178{ 2181{
2179 if (sigp != NULL) 2182 if (sigp != NULL)
2180 *sigp = NULL; 2183 *sigp = NULL;
@@ -2194,7 +2197,7 @@ sshkey_sign(const struct sshkey *key,
2194# endif /* OPENSSL_HAS_ECC */ 2197# endif /* OPENSSL_HAS_ECC */
2195 case KEY_RSA_CERT: 2198 case KEY_RSA_CERT:
2196 case KEY_RSA: 2199 case KEY_RSA:
2197 return ssh_rsa_sign(key, sigp, lenp, data, datalen, compat); 2200 return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
2198#endif /* WITH_OPENSSL */ 2201#endif /* WITH_OPENSSL */
2199 case KEY_ED25519: 2202 case KEY_ED25519:
2200 case KEY_ED25519_CERT: 2203 case KEY_ED25519_CERT:
@@ -2226,7 +2229,7 @@ sshkey_verify(const struct sshkey *key,
2226# endif /* OPENSSL_HAS_ECC */ 2229# endif /* OPENSSL_HAS_ECC */
2227 case KEY_RSA_CERT: 2230 case KEY_RSA_CERT:
2228 case KEY_RSA: 2231 case KEY_RSA:
2229 return ssh_rsa_verify(key, sig, siglen, data, dlen, compat); 2232 return ssh_rsa_verify(key, sig, siglen, data, dlen);
2230#endif /* WITH_OPENSSL */ 2233#endif /* WITH_OPENSSL */
2231 case KEY_ED25519: 2234 case KEY_ED25519:
2232 case KEY_ED25519_CERT: 2235 case KEY_ED25519_CERT:
@@ -2460,7 +2463,7 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca)
2460 2463
2461 /* Sign the whole mess */ 2464 /* Sign the whole mess */
2462 if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), 2465 if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
2463 sshbuf_len(cert), 0)) != 0) 2466 sshbuf_len(cert), NULL, 0)) != 0)
2464 goto out; 2467 goto out;
2465 2468
2466 /* Append signature and we are done */ 2469 /* Append signature and we are done */
diff --git a/sshkey.h b/sshkey.h
index 5a8cccd42..a20a14f9e 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.h,v 1.11 2015/11/19 01:08:55 djm Exp $ */ 1/* $OpenBSD: sshkey.h,v 1.12 2015/12/04 16:41:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -169,7 +169,7 @@ int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
169int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); 169int sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
170 170
171int sshkey_sign(const struct sshkey *, u_char **, size_t *, 171int sshkey_sign(const struct sshkey *, u_char **, size_t *,
172 const u_char *, size_t, u_int); 172 const u_char *, size_t, const char *, u_int);
173int sshkey_verify(const struct sshkey *, const u_char *, size_t, 173int sshkey_verify(const struct sshkey *, const u_char *, size_t,
174 const u_char *, size_t, u_int); 174 const u_char *, size_t, u_int);
175 175
@@ -193,11 +193,11 @@ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
193 const char *passphrase, struct sshkey **keyp, char **commentp); 193 const char *passphrase, struct sshkey **keyp, char **commentp);
194 194
195#ifdef SSHKEY_INTERNAL 195#ifdef SSHKEY_INTERNAL
196int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 196int ssh_rsa_sign(const struct sshkey *key,
197 const u_char *data, size_t datalen, u_int compat); 197 u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
198 const char *ident);
198int ssh_rsa_verify(const struct sshkey *key, 199int ssh_rsa_verify(const struct sshkey *key,
199 const u_char *signature, size_t signaturelen, 200 const u_char *sig, size_t siglen, const u_char *data, size_t datalen);
200 const u_char *data, size_t datalen, u_int compat);
201int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 201int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
202 const u_char *data, size_t datalen, u_int compat); 202 const u_char *data, size_t datalen, u_int compat);
203int ssh_dss_verify(const struct sshkey *key, 203int ssh_dss_verify(const struct sshkey *key,