summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-07-03 11:39:54 +0000
committerDamien Miller <djm@mindrot.org>2018-07-03 23:26:36 +1000
commit4ba0d54794814ec0de1ec87987d0c3b89379b436 (patch)
treeb8d904880f8927374b377b2e4d5661213c1138b6
parent95344c257412b51199ead18d54eaed5bafb75617 (diff)
upstream: Improve strictness and control over RSA-SHA2 signature
In ssh, when an agent fails to return a RSA-SHA2 signature when requested and falls back to RSA-SHA1 instead, retry the signature to ensure that the public key algorithm sent in the SSH_MSG_USERAUTH matches the one in the signature itself. In sshd, strictly enforce that the public key algorithm sent in the SSH_MSG_USERAUTH message matches what appears in the signature. Make the sshd_config PubkeyAcceptedKeyTypes and HostbasedAcceptedKeyTypes options control accepted signature algorithms (previously they selected supported key types). This allows these options to ban RSA-SHA1 in favour of RSA-SHA2. Add new signature algorithms "rsa-sha2-256-cert-v01@openssh.com" and "rsa-sha2-512-cert-v01@openssh.com" to force use of RSA-SHA2 signatures with certificate keys. feedback and ok markus@ OpenBSD-Commit-ID: c6e9f6d45eed8962ad502d315d7eaef32c419dde
-rw-r--r--PROTOCOL.certkeys20
-rw-r--r--auth2-hostbased.c5
-rw-r--r--auth2-pubkey.c13
-rw-r--r--authfd.c24
-rw-r--r--compat.c27
-rw-r--r--compat.h4
-rw-r--r--kex.c17
-rw-r--r--kex.h4
-rw-r--r--myproposal.h4
-rw-r--r--ssh-rsa.c60
-rw-r--r--ssh_config.513
-rw-r--r--sshconnect2.c345
-rw-r--r--sshd.c63
-rw-r--r--sshd_config.511
-rw-r--r--ssherr.c4
-rw-r--r--ssherr.h3
-rw-r--r--sshkey.c104
-rw-r--r--sshkey.h4
18 files changed, 469 insertions, 256 deletions
diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys
index 65f11f538..11363fdc3 100644
--- a/PROTOCOL.certkeys
+++ b/PROTOCOL.certkeys
@@ -25,6 +25,10 @@ raw user keys. The ssh client will support automatic verification of
25acceptance of certified host keys, by adding a similar ability to 25acceptance of certified host keys, by adding a similar ability to
26specify CA keys in ~/.ssh/known_hosts. 26specify CA keys in ~/.ssh/known_hosts.
27 27
28All certificate types include certification information along with the
29public key that is used to sign challenges. In OpenSSH, ssh-keygen
30performs the CA signing operation.
31
28Certified keys are represented using new key types: 32Certified keys are represented using new key types:
29 33
30 ssh-rsa-cert-v01@openssh.com 34 ssh-rsa-cert-v01@openssh.com
@@ -33,9 +37,17 @@ Certified keys are represented using new key types:
33 ecdsa-sha2-nistp384-cert-v01@openssh.com 37 ecdsa-sha2-nistp384-cert-v01@openssh.com
34 ecdsa-sha2-nistp521-cert-v01@openssh.com 38 ecdsa-sha2-nistp521-cert-v01@openssh.com
35 39
36These include certification information along with the public key 40Two additional types exist for RSA certificates to force use of
37that is used to sign challenges. ssh-keygen performs the CA signing 41SHA-2 signatures (SHA-256 and SHA-512 respectively):
38operation. 42
43 rsa-sha2-256-cert-v01@openssh.com
44 rsa-sha2-512-cert-v01@openssh.com
45
46These RSA/SHA-2 types should not appear in keys at rest or transmitted
47on their wire, but do appear in a SSH_MSG_KEXINIT's host-key algorithms
48field or in the "public key algorithm name" field of a "publickey"
49SSH_USERAUTH_REQUEST to indicate that the signature will use the
50specified algorithm.
39 51
40Protocol extensions 52Protocol extensions
41------------------- 53-------------------
@@ -291,4 +303,4 @@ permit-user-rc empty Flag indicating that execution of
291 of this script will not be permitted if 303 of this script will not be permitted if
292 this option is not present. 304 this option is not present.
293 305
294$OpenBSD: PROTOCOL.certkeys,v 1.14 2018/04/10 00:10:49 djm Exp $ 306$OpenBSD: PROTOCOL.certkeys,v 1.15 2018/07/03 11:39:54 djm Exp $
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 8996f7e05..f70609cb0 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-hostbased.c,v 1.33 2018/01/23 05:27:21 djm Exp $ */ 1/* $OpenBSD: auth2-hostbased.c,v 1.34 2018/07/03 11:39:54 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -111,8 +111,7 @@ userauth_hostbased(struct ssh *ssh)
111 "signature format"); 111 "signature format");
112 goto done; 112 goto done;
113 } 113 }
114 if (match_pattern_list(sshkey_ssh_name(key), 114 if (match_pattern_list(pkalg, options.hostbased_key_types, 0) != 1) {
115 options.hostbased_key_types, 0) != 1) {
116 logit("%s: key type %s not in HostbasedAcceptedKeyTypes", 115 logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
117 __func__, sshkey_type(key)); 116 __func__, sshkey_type(key));
118 goto done; 117 goto done;
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 3ccc3a213..4feeae3e2 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.79 2018/06/06 18:29:18 markus Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.80 2018/07/03 11:39:54 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -109,7 +109,7 @@ userauth_pubkey(struct ssh *ssh)
109 pktype = sshkey_type_from_name(pkalg); 109 pktype = sshkey_type_from_name(pkalg);
110 if (pktype == KEY_UNSPEC) { 110 if (pktype == KEY_UNSPEC) {
111 /* this is perfectly legal */ 111 /* this is perfectly legal */
112 logit("%s: unsupported public key algorithm: %s", 112 verbose("%s: unsupported public key algorithm: %s",
113 __func__, pkalg); 113 __func__, pkalg);
114 goto done; 114 goto done;
115 } 115 }
@@ -136,8 +136,7 @@ userauth_pubkey(struct ssh *ssh)
136 logit("refusing previously-used %s key", sshkey_type(key)); 136 logit("refusing previously-used %s key", sshkey_type(key));
137 goto done; 137 goto done;
138 } 138 }
139 if (match_pattern_list(sshkey_ssh_name(key), 139 if (match_pattern_list(pkalg, options.pubkey_key_types, 0) != 1) {
140 options.pubkey_key_types, 0) != 1) {
141 logit("%s: key type %s not in PubkeyAcceptedKeyTypes", 140 logit("%s: key type %s not in PubkeyAcceptedKeyTypes",
142 __func__, sshkey_ssh_name(key)); 141 __func__, sshkey_ssh_name(key));
143 goto done; 142 goto done;
@@ -188,8 +187,10 @@ userauth_pubkey(struct ssh *ssh)
188 /* test for correct signature */ 187 /* test for correct signature */
189 authenticated = 0; 188 authenticated = 0;
190 if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) && 189 if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
191 PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), 190 PRIVSEP(sshkey_verify(key, sig, slen,
192 sshbuf_len(b), NULL, ssh->compat)) == 0) { 191 sshbuf_ptr(b), sshbuf_len(b),
192 (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL,
193 ssh->compat)) == 0) {
193 authenticated = 1; 194 authenticated = 1;
194 } 195 }
195 sshbuf_free(b); 196 sshbuf_free(b);
diff --git a/authfd.c b/authfd.c
index 3ee7dffa5..f24230b7c 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfd.c,v 1.109 2018/04/10 00:10:49 djm Exp $ */ 1/* $OpenBSD: authfd.c,v 1.110 2018/07/03 11:39:54 djm 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
@@ -343,8 +343,8 @@ ssh_agent_sign(int sock, const struct sshkey *key,
343 const u_char *data, size_t datalen, const char *alg, u_int compat) 343 const u_char *data, size_t datalen, const char *alg, u_int compat)
344{ 344{
345 struct sshbuf *msg; 345 struct sshbuf *msg;
346 u_char *blob = NULL, type; 346 u_char *sig = NULL, type = 0;
347 size_t blen = 0, len = 0; 347 size_t len = 0;
348 u_int flags = 0; 348 u_int flags = 0;
349 int r = SSH_ERR_INTERNAL_ERROR; 349 int r = SSH_ERR_INTERNAL_ERROR;
350 350
@@ -355,11 +355,9 @@ ssh_agent_sign(int sock, const struct sshkey *key,
355 return SSH_ERR_INVALID_ARGUMENT; 355 return SSH_ERR_INVALID_ARGUMENT;
356 if ((msg = sshbuf_new()) == NULL) 356 if ((msg = sshbuf_new()) == NULL)
357 return SSH_ERR_ALLOC_FAIL; 357 return SSH_ERR_ALLOC_FAIL;
358 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
359 goto out;
360 flags |= agent_encode_alg(key, alg); 358 flags |= agent_encode_alg(key, alg);
361 if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || 359 if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
362 (r = sshbuf_put_string(msg, blob, blen)) != 0 || 360 (r = sshkey_puts(key, msg)) != 0 ||
363 (r = sshbuf_put_string(msg, data, datalen)) != 0 || 361 (r = sshbuf_put_string(msg, data, datalen)) != 0 ||
364 (r = sshbuf_put_u32(msg, flags)) != 0) 362 (r = sshbuf_put_u32(msg, flags)) != 0)
365 goto out; 363 goto out;
@@ -374,15 +372,19 @@ ssh_agent_sign(int sock, const struct sshkey *key,
374 r = SSH_ERR_INVALID_FORMAT; 372 r = SSH_ERR_INVALID_FORMAT;
375 goto out; 373 goto out;
376 } 374 }
377 if ((r = sshbuf_get_string(msg, sigp, &len)) != 0) 375 if ((r = sshbuf_get_string(msg, &sig, &len)) != 0)
376 goto out;
377 /* Check what we actually got back from the agent. */
378 if ((r = sshkey_check_sigtype(sig, len, alg)) != 0)
378 goto out; 379 goto out;
380 /* success */
381 *sigp = sig;
379 *lenp = len; 382 *lenp = len;
383 sig = NULL;
384 len = 0;
380 r = 0; 385 r = 0;
381 out: 386 out:
382 if (blob != NULL) { 387 freezero(sig, len);
383 explicit_bzero(blob, blen);
384 free(blob);
385 }
386 sshbuf_free(msg); 388 sshbuf_free(msg);
387 return r; 389 return r;
388} 390}
diff --git a/compat.c b/compat.c
index 1c0e08732..1c9890aa8 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: compat.c,v 1.107 2018/04/16 22:50:44 djm Exp $ */ 1/* $OpenBSD: compat.c,v 1.108 2018/07/03 11:39:54 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. 3 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
4 * 4 *
@@ -52,16 +52,27 @@ compat_datafellows(const char *version)
52 } check[] = { 52 } check[] = {
53 { "OpenSSH_2.*," 53 { "OpenSSH_2.*,"
54 "OpenSSH_3.0*," 54 "OpenSSH_3.0*,"
55 "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR}, 55 "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR|
56 { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR }, 56 SSH_BUG_SIGTYPE},
57 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, 57 { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR|SSH_BUG_SIGTYPE },
58 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
59 SSH_BUG_SIGTYPE},
58 { "OpenSSH_2*," 60 { "OpenSSH_2*,"
59 "OpenSSH_3*," 61 "OpenSSH_3*,"
60 "OpenSSH_4*", 0 }, 62 "OpenSSH_4*", SSH_BUG_SIGTYPE },
61 { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT}, 63 { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT|
62 { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH}, 64 SSH_BUG_SIGTYPE},
65 { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
63 { "OpenSSH_6.5*," 66 { "OpenSSH_6.5*,"
64 "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD}, 67 "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD|
68 SSH_BUG_SIGTYPE},
69 { "OpenSSH_7.0*,"
70 "OpenSSH_7.1*,"
71 "OpenSSH_7.2*,"
72 "OpenSSH_7.3*,"
73 "OpenSSH_7.4*,"
74 "OpenSSH_7.5*,"
75 "OpenSSH_7.6*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
65 { "OpenSSH*", SSH_NEW_OPENSSH }, 76 { "OpenSSH*", SSH_NEW_OPENSSH },
66 { "*MindTerm*", 0 }, 77 { "*MindTerm*", 0 },
67 { "3.0.*", SSH_BUG_DEBUG }, 78 { "3.0.*", SSH_BUG_DEBUG },
diff --git a/compat.h b/compat.h
index 4fee3495a..28d2c8135 100644
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: compat.h,v 1.51 2018/02/16 04:43:11 dtucker Exp $ */ 1/* $OpenBSD: compat.h,v 1.52 2018/07/03 11:39:54 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -33,7 +33,7 @@
33#define SSH_PROTO_2 0x04 33#define SSH_PROTO_2 0x04
34 34
35#define SSH_BUG_UTF8TTYMODE 0x00000001 35#define SSH_BUG_UTF8TTYMODE 0x00000001
36/* #define unused 0x00000002 */ 36#define SSH_BUG_SIGTYPE 0x00000002
37/* #define unused 0x00000004 */ 37/* #define unused 0x00000004 */
38/* #define unused 0x00000008 */ 38/* #define unused 0x00000008 */
39#define SSH_OLD_SESSIONID 0x00000010 39#define SSH_OLD_SESSIONID 0x00000010
diff --git a/kex.c b/kex.c
index 15ea28b07..d0a5f1b66 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.136 2018/02/07 02:06:50 jsing Exp $ */ 1/* $OpenBSD: kex.c,v 1.137 2018/07/03 11:39:54 djm 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 *
@@ -342,6 +342,7 @@ kex_send_ext_info(struct ssh *ssh)
342 342
343 if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) 343 if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
344 return SSH_ERR_ALLOC_FAIL; 344 return SSH_ERR_ALLOC_FAIL;
345 /* XXX filter algs list by allowed pubkey/hostbased types */
345 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || 346 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
346 (r = sshpkt_put_u32(ssh, 1)) != 0 || 347 (r = sshpkt_put_u32(ssh, 1)) != 0 ||
347 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || 348 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
@@ -378,7 +379,7 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
378{ 379{
379 struct kex *kex = ssh->kex; 380 struct kex *kex = ssh->kex;
380 u_int32_t i, ninfo; 381 u_int32_t i, ninfo;
381 char *name, *found; 382 char *name;
382 u_char *val; 383 u_char *val;
383 size_t vlen; 384 size_t vlen;
384 int r; 385 int r;
@@ -401,16 +402,8 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
401 return SSH_ERR_INVALID_FORMAT; 402 return SSH_ERR_INVALID_FORMAT;
402 } 403 }
403 debug("%s: %s=<%s>", __func__, name, val); 404 debug("%s: %s=<%s>", __func__, name, val);
404 found = match_list("rsa-sha2-256", val, NULL); 405 kex->server_sig_algs = val;
405 if (found) { 406 val = NULL;
406 kex->rsa_sha2 = 256;
407 free(found);
408 }
409 found = match_list("rsa-sha2-512", val, NULL);
410 if (found) {
411 kex->rsa_sha2 = 512;
412 free(found);
413 }
414 } else 407 } else
415 debug("%s: %s (unrecognised)", __func__, name); 408 debug("%s: %s (unrecognised)", __func__, name);
416 free(name); 409 free(name);
diff --git a/kex.h b/kex.h
index 01bb3986a..6210630df 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.83 2017/05/30 14:23:52 markus Exp $ */ 1/* $OpenBSD: kex.h,v 1.84 2018/07/03 11:39:54 djm 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.
@@ -139,7 +139,7 @@ struct kex {
139 int hostkey_type; 139 int hostkey_type;
140 int hostkey_nid; 140 int hostkey_nid;
141 u_int kex_type; 141 u_int kex_type;
142 int rsa_sha2; 142 char *server_sig_algs;
143 int ext_info_c; 143 int ext_info_c;
144 struct sshbuf *my; 144 struct sshbuf *my;
145 struct sshbuf *peer; 145 struct sshbuf *peer;
diff --git a/myproposal.h b/myproposal.h
index c255147aa..08782dd30 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: myproposal.h,v 1.55 2017/05/07 23:13:42 djm Exp $ */ 1/* $OpenBSD: myproposal.h,v 1.56 2018/07/03 11:39:54 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -107,6 +107,8 @@
107#define KEX_DEFAULT_PK_ALG \ 107#define KEX_DEFAULT_PK_ALG \
108 HOSTKEY_ECDSA_CERT_METHODS \ 108 HOSTKEY_ECDSA_CERT_METHODS \
109 "ssh-ed25519-cert-v01@openssh.com," \ 109 "ssh-ed25519-cert-v01@openssh.com," \
110 "rsa-sha2-512-cert-v01@openssh.com," \
111 "rsa-sha2-256-cert-v01@openssh.com," \
110 "ssh-rsa-cert-v01@openssh.com," \ 112 "ssh-rsa-cert-v01@openssh.com," \
111 HOSTKEY_ECDSA_METHODS \ 113 HOSTKEY_ECDSA_METHODS \
112 "ssh-ed25519," \ 114 "ssh-ed25519," \
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 49e71c87f..1756315b9 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-rsa.c,v 1.66 2018/02/14 16:27:24 jsing Exp $ */ 1/* $OpenBSD: ssh-rsa.c,v 1.67 2018/07/03 11:39:54 djm 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 *
@@ -51,11 +51,14 @@ rsa_hash_alg_ident(int hash_alg)
51 return NULL; 51 return NULL;
52} 52}
53 53
54/*
55 * Returns the hash algorithm ID for a given algorithm identifier as used
56 * inside the signature blob,
57 */
54static int 58static int
55rsa_hash_alg_from_ident(const char *ident) 59rsa_hash_id_from_ident(const char *ident)
56{ 60{
57 if (strcmp(ident, "ssh-rsa") == 0 || 61 if (strcmp(ident, "ssh-rsa") == 0)
58 strcmp(ident, "ssh-rsa-cert-v01@openssh.com") == 0)
59 return SSH_DIGEST_SHA1; 62 return SSH_DIGEST_SHA1;
60 if (strcmp(ident, "rsa-sha2-256") == 0) 63 if (strcmp(ident, "rsa-sha2-256") == 0)
61 return SSH_DIGEST_SHA256; 64 return SSH_DIGEST_SHA256;
@@ -64,6 +67,27 @@ rsa_hash_alg_from_ident(const char *ident)
64 return -1; 67 return -1;
65} 68}
66 69
70/*
71 * Return the hash algorithm ID for the specified key name. This includes
72 * all the cases of rsa_hash_id_from_ident() but also the certificate key
73 * types.
74 */
75static int
76rsa_hash_id_from_keyname(const char *alg)
77{
78 int r;
79
80 if ((r = rsa_hash_id_from_ident(alg)) != -1)
81 return r;
82 if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
83 return SSH_DIGEST_SHA1;
84 if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
85 return SSH_DIGEST_SHA256;
86 if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
87 return SSH_DIGEST_SHA512;
88 return -1;
89}
90
67static int 91static int
68rsa_hash_alg_nid(int type) 92rsa_hash_alg_nid(int type)
69{ 93{
@@ -135,7 +159,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
135 if (alg_ident == NULL || strlen(alg_ident) == 0) 159 if (alg_ident == NULL || strlen(alg_ident) == 0)
136 hash_alg = SSH_DIGEST_SHA1; 160 hash_alg = SSH_DIGEST_SHA1;
137 else 161 else
138 hash_alg = rsa_hash_alg_from_ident(alg_ident); 162 hash_alg = rsa_hash_id_from_keyname(alg_ident);
139 if (key == NULL || key->rsa == NULL || hash_alg == -1 || 163 if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
140 sshkey_type_plain(key->type) != KEY_RSA) 164 sshkey_type_plain(key->type) != KEY_RSA)
141 return SSH_ERR_INVALID_ARGUMENT; 165 return SSH_ERR_INVALID_ARGUMENT;
@@ -202,7 +226,7 @@ ssh_rsa_verify(const struct sshkey *key,
202 const char *alg) 226 const char *alg)
203{ 227{
204 char *sigtype = NULL; 228 char *sigtype = NULL;
205 int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 229 int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
206 size_t len = 0, diff, modlen, dlen; 230 size_t len = 0, diff, modlen, dlen;
207 struct sshbuf *b = NULL; 231 struct sshbuf *b = NULL;
208 u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; 232 u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
@@ -220,18 +244,24 @@ ssh_rsa_verify(const struct sshkey *key,
220 ret = SSH_ERR_INVALID_FORMAT; 244 ret = SSH_ERR_INVALID_FORMAT;
221 goto out; 245 goto out;
222 } 246 }
223 /* XXX djm: need cert types that reliably yield SHA-2 signatures */ 247 if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
224 if (alg != NULL && strcmp(alg, sigtype) != 0 &&
225 strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
226 error("%s: RSA signature type mismatch: "
227 "expected %s received %s", __func__, alg, sigtype);
228 ret = SSH_ERR_SIGNATURE_INVALID;
229 goto out;
230 }
231 if ((hash_alg = rsa_hash_alg_from_ident(sigtype)) == -1) {
232 ret = SSH_ERR_KEY_TYPE_MISMATCH; 248 ret = SSH_ERR_KEY_TYPE_MISMATCH;
233 goto out; 249 goto out;
234 } 250 }
251 /*
252 * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
253 * legacy reasons, but otherwise the signature type should match.
254 */
255 if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
256 if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
257 ret = SSH_ERR_INVALID_ARGUMENT;
258 goto out;
259 }
260 if (hash_alg != want_alg) {
261 ret = SSH_ERR_SIGNATURE_INVALID;
262 goto out;
263 }
264 }
235 if (sshbuf_get_string(b, &sigblob, &len) != 0) { 265 if (sshbuf_get_string(b, &sigblob, &len) != 0) {
236 ret = SSH_ERR_INVALID_FORMAT; 266 ret = SSH_ERR_INVALID_FORMAT;
237 goto out; 267 goto out;
diff --git a/ssh_config.5 b/ssh_config.5
index e5eadcaaf..eff9c5e61 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh_config.5,v 1.277 2018/06/09 06:36:31 jmc Exp $ 36.\" $OpenBSD: ssh_config.5,v 1.278 2018/07/03 11:39:54 djm Exp $
37.Dd $Mdocdate: June 9 2018 $ 37.Dd $Mdocdate: July 3 2018 $
38.Dt SSH_CONFIG 5 38.Dt SSH_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -772,9 +772,10 @@ ecdsa-sha2-nistp256-cert-v01@openssh.com,
772ecdsa-sha2-nistp384-cert-v01@openssh.com, 772ecdsa-sha2-nistp384-cert-v01@openssh.com,
773ecdsa-sha2-nistp521-cert-v01@openssh.com, 773ecdsa-sha2-nistp521-cert-v01@openssh.com,
774ssh-ed25519-cert-v01@openssh.com, 774ssh-ed25519-cert-v01@openssh.com,
775rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
775ssh-rsa-cert-v01@openssh.com, 776ssh-rsa-cert-v01@openssh.com,
776ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, 777ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
777ssh-ed25519,ssh-rsa 778ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
778.Ed 779.Ed
779.Pp 780.Pp
780The 781The
@@ -799,9 +800,10 @@ ecdsa-sha2-nistp256-cert-v01@openssh.com,
799ecdsa-sha2-nistp384-cert-v01@openssh.com, 800ecdsa-sha2-nistp384-cert-v01@openssh.com,
800ecdsa-sha2-nistp521-cert-v01@openssh.com, 801ecdsa-sha2-nistp521-cert-v01@openssh.com,
801ssh-ed25519-cert-v01@openssh.com, 802ssh-ed25519-cert-v01@openssh.com,
803rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
802ssh-rsa-cert-v01@openssh.com, 804ssh-rsa-cert-v01@openssh.com,
803ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, 805ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
804ssh-ed25519,ssh-rsa 806ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
805.Ed 807.Ed
806.Pp 808.Pp
807If hostkeys are known for the destination host then this default is modified 809If hostkeys are known for the destination host then this default is modified
@@ -1255,9 +1257,10 @@ ecdsa-sha2-nistp256-cert-v01@openssh.com,
1255ecdsa-sha2-nistp384-cert-v01@openssh.com, 1257ecdsa-sha2-nistp384-cert-v01@openssh.com,
1256ecdsa-sha2-nistp521-cert-v01@openssh.com, 1258ecdsa-sha2-nistp521-cert-v01@openssh.com,
1257ssh-ed25519-cert-v01@openssh.com, 1259ssh-ed25519-cert-v01@openssh.com,
1260rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
1258ssh-rsa-cert-v01@openssh.com, 1261ssh-rsa-cert-v01@openssh.com,
1259ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, 1262ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
1260ssh-ed25519,ssh-rsa 1263ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
1261.Ed 1264.Ed
1262.Pp 1265.Pp
1263The list of available key types may also be obtained using 1266The list of available key types may also be obtained using
diff --git a/sshconnect2.c b/sshconnect2.c
index d8ae6eb3a..920376408 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.271 2018/06/26 02:02:36 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.272 2018/07/03 11:39:54 djm 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.
@@ -315,7 +315,7 @@ int input_gssapi_errtok(int, u_int32_t, struct ssh *);
315 315
316void userauth(Authctxt *, char *); 316void userauth(Authctxt *, char *);
317 317
318static int sign_and_send_pubkey(Authctxt *, Identity *); 318static int sign_and_send_pubkey(struct ssh *ssh, Authctxt *, Identity *);
319static void pubkey_prepare(Authctxt *); 319static void pubkey_prepare(Authctxt *);
320static void pubkey_cleanup(Authctxt *); 320static void pubkey_cleanup(Authctxt *);
321static void pubkey_reset(Authctxt *); 321static void pubkey_reset(Authctxt *);
@@ -619,7 +619,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh)
619 */ 619 */
620 TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) { 620 TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) {
621 if (key_equal(key, id->key)) { 621 if (key_equal(key, id->key)) {
622 sent = sign_and_send_pubkey(authctxt, id); 622 sent = sign_and_send_pubkey(ssh, authctxt, id);
623 break; 623 break;
624 } 624 }
625 } 625 }
@@ -986,73 +986,80 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh)
986 return 0; 986 return 0;
987} 987}
988 988
989static const char *
990key_sign_encode(const struct sshkey *key)
991{
992 struct ssh *ssh = active_state;
993
994 if (key->type == KEY_RSA) {
995 switch (ssh->kex->rsa_sha2) {
996 case 256:
997 return "rsa-sha2-256";
998 case 512:
999 return "rsa-sha2-512";
1000 }
1001 }
1002 return key_ssh_name(key);
1003}
1004
1005/* 989/*
1006 * Some agents will return ssh-rsa signatures when asked to make a 990 * Select an algorithm for publickey signatures.
1007 * rsa-sha2-* signature. Check what they actually gave back and warn the 991 * Returns algorithm (caller must free) or NULL if no mutual algorithm found.
1008 * user if the agent has returned an unexpected type. 992 *
993 * Call with ssh==NULL to ignore server-sig-algs extension list and
994 * only attempt with the key's base signature type.
1009 */ 995 */
1010static int 996static char *
1011check_sigtype(const struct sshkey *key, const u_char *sig, size_t len) 997key_sig_algorithm(struct ssh *ssh, const struct sshkey *key)
1012{ 998{
1013 int r; 999 char *allowed, *oallowed, *cp, *alg = NULL;
1014 char *sigtype = NULL;
1015 const char *alg = key_sign_encode(key);
1016 1000
1017 if (sshkey_is_cert(key)) 1001 /*
1018 return 0; 1002 * The signature algorithm will only differ from the key algorithm
1019 if ((r = sshkey_sigtype(sig, len, &sigtype)) != 0) 1003 * for RSA keys/certs and when the server advertises support for
1020 return r; 1004 * newer (SHA2) algorithms.
1021 if (strcmp(sigtype, alg) != 0) { 1005 */
1022 logit("warning: agent returned different signature type %s " 1006 if (ssh == NULL || ssh->kex->server_sig_algs == NULL ||
1023 "(expected %s)", sigtype, alg); 1007 (key->type != KEY_RSA && key->type != KEY_RSA_CERT)) {
1024 } 1008 /* Filter base key signature alg against our configuration */
1025 free(sigtype); 1009 return match_list(key_ssh_name(key),
1026 /* Incorrect signature types aren't an error ... yet */ 1010 options.pubkey_key_types, NULL);
1027 return 0; 1011 }
1012
1013 /*
1014 * For RSA keys/certs, since these might have a different sig type:
1015 * find the first entry in PubkeyAcceptedKeyTypes of the right type
1016 * that also appears in the supported signature algorithms list from
1017 * the server.
1018 */
1019 oallowed = allowed = xstrdup(options.pubkey_key_types);
1020 while ((cp = strsep(&allowed, ",")) != NULL) {
1021 if (sshkey_type_from_name(cp) != key->type)
1022 continue;
1023 alg = match_list(cp, ssh->kex->server_sig_algs, NULL);
1024 if (alg != NULL)
1025 break;
1026 }
1027 free(oallowed);
1028 return alg;
1028} 1029}
1029 1030
1030static int 1031static int
1031identity_sign(struct identity *id, u_char **sigp, size_t *lenp, 1032identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
1032 const u_char *data, size_t datalen, u_int compat) 1033 const u_char *data, size_t datalen, u_int compat, const char *alg)
1033{ 1034{
1034 struct sshkey *prv; 1035 struct sshkey *prv;
1035 int r; 1036 int r;
1036 1037
1037 /* the agent supports this key */ 1038 /* The agent supports this key. */
1038 if (id->key != NULL && id->agent_fd != -1) { 1039 if (id->key != NULL && id->agent_fd != -1) {
1039 if ((r = ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, 1040 return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
1040 data, datalen, key_sign_encode(id->key), compat)) != 0 || 1041 data, datalen, alg, compat);
1041 (r = check_sigtype(id->key, *sigp, *lenp)) != 0)
1042 return r;
1043 return 0;
1044 } 1042 }
1045 1043
1046 /* 1044 /*
1047 * we have already loaded the private key or 1045 * We have already loaded the private key or the private key is
1048 * the private key is stored in external hardware 1046 * stored in external hardware.
1049 */ 1047 */
1050 if (id->key != NULL && 1048 if (id->key != NULL &&
1051 (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) 1049 (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) {
1052 return (sshkey_sign(id->key, sigp, lenp, data, datalen, 1050 if ((r = sshkey_sign(id->key, sigp, lenp, data, datalen,
1053 key_sign_encode(id->key), compat)); 1051 alg, compat)) != 0)
1052 return r;
1053 /*
1054 * PKCS#11 tokens may not support all signature algorithms,
1055 * so check what we get back.
1056 */
1057 if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0)
1058 return r;
1059 return 0;
1060 }
1054 1061
1055 /* load the private key from the file */ 1062 /* Load the private key from the file. */
1056 if ((prv = load_identity_file(id)) == NULL) 1063 if ((prv = load_identity_file(id)) == NULL)
1057 return SSH_ERR_KEY_NOT_FOUND; 1064 return SSH_ERR_KEY_NOT_FOUND;
1058 if (id->key != NULL && !sshkey_equal_public(prv, id->key)) { 1065 if (id->key != NULL && !sshkey_equal_public(prv, id->key)) {
@@ -1060,8 +1067,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
1060 __func__, id->filename); 1067 __func__, id->filename);
1061 return SSH_ERR_KEY_NOT_FOUND; 1068 return SSH_ERR_KEY_NOT_FOUND;
1062 } 1069 }
1063 r = sshkey_sign(prv, sigp, lenp, data, datalen, 1070 r = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat);
1064 key_sign_encode(prv), compat);
1065 sshkey_free(prv); 1071 sshkey_free(prv);
1066 return r; 1072 return r;
1067} 1073}
@@ -1086,57 +1092,35 @@ id_filename_matches(Identity *id, Identity *private_id)
1086} 1092}
1087 1093
1088static int 1094static int
1089sign_and_send_pubkey(Authctxt *authctxt, Identity *id) 1095sign_and_send_pubkey(struct ssh *ssh, Authctxt *authctxt, Identity *id)
1090{ 1096{
1091 Buffer b; 1097 struct sshbuf *b = NULL;
1092 Identity *private_id; 1098 Identity *private_id, *sign_id = NULL;
1093 u_char *blob, *signature; 1099 u_char *signature = NULL;
1094 size_t slen; 1100 size_t slen = 0, skip = 0;
1095 u_int bloblen, skip = 0; 1101 int r, fallback_sigtype, sent = 0;
1096 int matched, ret = -1, have_sig = 1; 1102 char *alg = NULL, *fp = NULL;
1097 char *fp; 1103 const char *loc = "";
1098 1104
1099 if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, 1105 if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
1100 SSH_FP_DEFAULT)) == NULL) 1106 SSH_FP_DEFAULT)) == NULL)
1101 return 0; 1107 return 0;
1102 debug3("%s: %s %s", __func__, key_type(id->key), fp);
1103 free(fp);
1104 1108
1105 if (key_to_blob(id->key, &blob, &bloblen) == 0) { 1109 debug3("%s: %s %s", __func__, sshkey_type(id->key), fp);
1106 /* we cannot handle this key */
1107 debug3("sign_and_send_pubkey: cannot handle key");
1108 return 0;
1109 }
1110 /* data to be signed */
1111 buffer_init(&b);
1112 if (datafellows & SSH_OLD_SESSIONID) {
1113 buffer_append(&b, session_id2, session_id2_len);
1114 skip = session_id2_len;
1115 } else {
1116 buffer_put_string(&b, session_id2, session_id2_len);
1117 skip = buffer_len(&b);
1118 }
1119 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1120 buffer_put_cstring(&b, authctxt->server_user);
1121 buffer_put_cstring(&b, authctxt->service);
1122 buffer_put_cstring(&b, authctxt->method->name);
1123 buffer_put_char(&b, have_sig);
1124 buffer_put_cstring(&b, key_sign_encode(id->key));
1125 buffer_put_string(&b, blob, bloblen);
1126 1110
1127 /* 1111 /*
1128 * If the key is an certificate, try to find a matching private key 1112 * If the key is an certificate, try to find a matching private key
1129 * and use it to complete the signature. 1113 * and use it to complete the signature.
1130 * If no such private key exists, fall back to trying the certificate 1114 * If no such private key exists, fall back to trying the certificate
1131 * key itself in case it has a private half already loaded. 1115 * key itself in case it has a private half already loaded.
1116 * This will try to set sign_id to the private key that will perform
1117 * the signature.
1132 */ 1118 */
1133 if (key_is_cert(id->key)) { 1119 if (sshkey_is_cert(id->key)) {
1134 matched = 0;
1135 TAILQ_FOREACH(private_id, &authctxt->keys, next) { 1120 TAILQ_FOREACH(private_id, &authctxt->keys, next) {
1136 if (sshkey_equal_public(id->key, private_id->key) && 1121 if (sshkey_equal_public(id->key, private_id->key) &&
1137 id->key->type != private_id->key->type) { 1122 id->key->type != private_id->key->type) {
1138 id = private_id; 1123 sign_id = private_id;
1139 matched = 1;
1140 break; 1124 break;
1141 } 1125 }
1142 } 1126 }
@@ -1147,18 +1131,18 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1147 * of keeping just a private key file and public 1131 * of keeping just a private key file and public
1148 * certificate on disk. 1132 * certificate on disk.
1149 */ 1133 */
1150 if (!matched && !id->isprivate && id->agent_fd == -1 && 1134 if (sign_id == NULL &&
1135 !id->isprivate && id->agent_fd == -1 &&
1151 (id->key->flags & SSHKEY_FLAG_EXT) == 0) { 1136 (id->key->flags & SSHKEY_FLAG_EXT) == 0) {
1152 TAILQ_FOREACH(private_id, &authctxt->keys, next) { 1137 TAILQ_FOREACH(private_id, &authctxt->keys, next) {
1153 if (private_id->key == NULL && 1138 if (private_id->key == NULL &&
1154 id_filename_matches(id, private_id)) { 1139 id_filename_matches(id, private_id)) {
1155 id = private_id; 1140 sign_id = private_id;
1156 matched = 1;
1157 break; 1141 break;
1158 } 1142 }
1159 } 1143 }
1160 } 1144 }
1161 if (matched) { 1145 if (sign_id != NULL) {
1162 debug2("%s: using private key \"%s\"%s for " 1146 debug2("%s: using private key \"%s\"%s for "
1163 "certificate", __func__, id->filename, 1147 "certificate", __func__, id->filename,
1164 id->agent_fd != -1 ? " from agent" : ""); 1148 id->agent_fd != -1 ? " from agent" : "");
@@ -1168,51 +1152,121 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1168 } 1152 }
1169 } 1153 }
1170 1154
1171 /* generate signature */ 1155 /*
1172 ret = identity_sign(id, &signature, &slen, 1156 * If the above didn't select another identity to do the signing
1173 buffer_ptr(&b), buffer_len(&b), datafellows); 1157 * then default to the one we started with.
1174 if (ret != 0) { 1158 */
1175 if (ret != SSH_ERR_KEY_NOT_FOUND) 1159 if (sign_id == NULL)
1176 error("%s: signing failed: %s", __func__, ssh_err(ret)); 1160 sign_id = id;
1177 free(blob); 1161
1178 buffer_free(&b); 1162 /* assemble and sign data */
1179 return 0; 1163 for (fallback_sigtype = 0; fallback_sigtype <= 1; fallback_sigtype++) {
1164 free(alg);
1165 slen = 0;
1166 signature = NULL;
1167 if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh,
1168 id->key)) == NULL) {
1169 error("%s: no mutual signature supported", __func__);
1170 goto out;
1171 }
1172 debug3("%s: signing using %s", __func__, alg);
1173
1174 sshbuf_free(b);
1175 if ((b = sshbuf_new()) == NULL)
1176 fatal("%s: sshbuf_new failed", __func__);
1177 if (datafellows & SSH_OLD_SESSIONID) {
1178 if ((r = sshbuf_put(b, session_id2,
1179 session_id2_len)) != 0) {
1180 fatal("%s: sshbuf_put: %s",
1181 __func__, ssh_err(r));
1182 }
1183 } else {
1184 if ((r = sshbuf_put_string(b, session_id2,
1185 session_id2_len)) != 0) {
1186 fatal("%s: sshbuf_put_string: %s",
1187 __func__, ssh_err(r));
1188 }
1189 }
1190 skip = buffer_len(b);
1191 if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1192 (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
1193 (r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
1194 (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
1195 (r = sshbuf_put_u8(b, 1)) != 0 ||
1196 (r = sshbuf_put_cstring(b, alg)) != 0 ||
1197 (r = sshkey_puts(id->key, b)) != 0) {
1198 fatal("%s: assemble signed data: %s",
1199 __func__, ssh_err(r));
1200 }
1201
1202 /* generate signature */
1203 r = identity_sign(sign_id, &signature, &slen,
1204 sshbuf_ptr(b), sshbuf_len(b), datafellows, alg);
1205 if (r == 0)
1206 break;
1207 else if (r == SSH_ERR_KEY_NOT_FOUND)
1208 goto out; /* soft failure */
1209 else if (r == SSH_ERR_SIGN_ALG_UNSUPPORTED &&
1210 !fallback_sigtype) {
1211 if (sign_id->agent_fd != -1)
1212 loc = "agent ";
1213 else if ((sign_id->key->flags & SSHKEY_FLAG_EXT) != 0)
1214 loc = "token ";
1215 logit("%skey %s %s returned incorrect signature type",
1216 loc, sshkey_type(id->key), fp);
1217 continue;
1218 }
1219 error("%s: signing failed: %s", __func__, ssh_err(r));
1220 goto out;
1180 } 1221 }
1181#ifdef DEBUG_PK 1222 if (slen == 0 || signature == NULL) /* shouldn't happen */
1182 buffer_dump(&b); 1223 fatal("%s: no signature", __func__);
1183#endif
1184 free(blob);
1185 1224
1186 /* append signature */ 1225 /* append signature */
1187 buffer_put_string(&b, signature, slen); 1226 if ((r = sshbuf_put_string(b, signature, slen)) != 0)
1188 free(signature); 1227 fatal("%s: append signature: %s", __func__, ssh_err(r));
1189 1228
1229#ifdef DEBUG_PK
1230 sshbuf_dump(b, stderr);
1231#endif
1190 /* skip session id and packet type */ 1232 /* skip session id and packet type */
1191 if (buffer_len(&b) < skip + 1) 1233 if ((r = sshbuf_consume(b, skip + 1)) != 0)
1192 fatal("userauth_pubkey: internal error"); 1234 fatal("%s: consume: %s", __func__, ssh_err(r));
1193 buffer_consume(&b, skip + 1);
1194 1235
1195 /* put remaining data from buffer into packet */ 1236 /* put remaining data from buffer into packet */
1196 packet_start(SSH2_MSG_USERAUTH_REQUEST); 1237 if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1197 packet_put_raw(buffer_ptr(&b), buffer_len(&b)); 1238 (r = sshpkt_putb(ssh, b)) != 0 ||
1198 buffer_free(&b); 1239 (r = sshpkt_send(ssh)) != 0)
1199 packet_send(); 1240 fatal("%s: enqueue request: %s", __func__, ssh_err(r));
1200 1241
1201 return 1; 1242 /* success */
1243 sent = 1;
1244
1245 out:
1246 free(fp);
1247 free(alg);
1248 sshbuf_free(b);
1249 freezero(signature, slen);
1250 return sent;
1202} 1251}
1203 1252
1204static int 1253static int
1205send_pubkey_test(Authctxt *authctxt, Identity *id) 1254send_pubkey_test(struct ssh *ssh, Authctxt *authctxt, Identity *id)
1206{ 1255{
1207 u_char *blob; 1256 u_char *blob = NULL;
1208 u_int bloblen, have_sig = 0; 1257 u_int bloblen, have_sig = 0;
1258 char *alg = NULL;
1259 int sent = 0;
1209 1260
1210 debug3("send_pubkey_test"); 1261 if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) {
1262 debug("%s: no mutual signature algorithm", __func__);
1263 goto out;
1264 }
1211 1265
1212 if (key_to_blob(id->key, &blob, &bloblen) == 0) { 1266 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
1213 /* we cannot handle this key */ 1267 /* we cannot handle this key */
1214 debug3("send_pubkey_test: cannot handle key"); 1268 debug3("%s: cannot handle key", __func__);
1215 return 0; 1269 goto out;
1216 } 1270 }
1217 /* register callback for USERAUTH_PK_OK message */ 1271 /* register callback for USERAUTH_PK_OK message */
1218 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); 1272 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
@@ -1222,11 +1276,15 @@ send_pubkey_test(Authctxt *authctxt, Identity *id)
1222 packet_put_cstring(authctxt->service); 1276 packet_put_cstring(authctxt->service);
1223 packet_put_cstring(authctxt->method->name); 1277 packet_put_cstring(authctxt->method->name);
1224 packet_put_char(have_sig); 1278 packet_put_char(have_sig);
1225 packet_put_cstring(key_sign_encode(id->key)); 1279 packet_put_cstring(alg);
1226 packet_put_string(blob, bloblen); 1280 packet_put_string(blob, bloblen);
1227 free(blob);
1228 packet_send(); 1281 packet_send();
1229 return 1; 1282 /* success */
1283 sent = 1;
1284out:
1285 free(alg);
1286 free(blob);
1287 return sent;
1230} 1288}
1231 1289
1232static struct sshkey * 1290static struct sshkey *
@@ -1295,6 +1353,36 @@ load_identity_file(Identity *id)
1295 return private; 1353 return private;
1296} 1354}
1297 1355
1356static int
1357key_type_allowed_by_config(struct sshkey *key)
1358{
1359 if (match_pattern_list(sshkey_ssh_name(key),
1360 options.pubkey_key_types, 0) == 1)
1361 return 1;
1362
1363 /* RSA keys/certs might be allowed by alternate signature types */
1364 switch (key->type) {
1365 case KEY_RSA:
1366 if (match_pattern_list("rsa-sha2-512",
1367 options.pubkey_key_types, 0) == 1)
1368 return 1;
1369 if (match_pattern_list("rsa-sha2-256",
1370 options.pubkey_key_types, 0) == 1)
1371 return 1;
1372 break;
1373 case KEY_RSA_CERT:
1374 if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com",
1375 options.pubkey_key_types, 0) == 1)
1376 return 1;
1377 if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com",
1378 options.pubkey_key_types, 0) == 1)
1379 return 1;
1380 break;
1381 }
1382 return 0;
1383}
1384
1385
1298/* 1386/*
1299 * try keys in the following order: 1387 * try keys in the following order:
1300 * 1. certificates listed in the config file 1388 * 1. certificates listed in the config file
@@ -1419,9 +1507,7 @@ pubkey_prepare(Authctxt *authctxt)
1419 } 1507 }
1420 /* finally, filter by PubkeyAcceptedKeyTypes */ 1508 /* finally, filter by PubkeyAcceptedKeyTypes */
1421 TAILQ_FOREACH_SAFE(id, preferred, next, id2) { 1509 TAILQ_FOREACH_SAFE(id, preferred, next, id2) {
1422 if (id->key != NULL && 1510 if (id->key != NULL && !key_type_allowed_by_config(key)) {
1423 match_pattern_list(sshkey_ssh_name(id->key),
1424 options.pubkey_key_types, 0) != 1) {
1425 debug("Skipping %s key %s - " 1511 debug("Skipping %s key %s - "
1426 "not in PubkeyAcceptedKeyTypes", 1512 "not in PubkeyAcceptedKeyTypes",
1427 sshkey_ssh_name(id->key), id->filename); 1513 sshkey_ssh_name(id->key), id->filename);
@@ -1479,6 +1565,7 @@ try_identity(Identity *id)
1479int 1565int
1480userauth_pubkey(Authctxt *authctxt) 1566userauth_pubkey(Authctxt *authctxt)
1481{ 1567{
1568 struct ssh *ssh = active_state; /* XXX */
1482 Identity *id; 1569 Identity *id;
1483 int sent = 0; 1570 int sent = 0;
1484 char *fp; 1571 char *fp;
@@ -1506,7 +1593,7 @@ userauth_pubkey(Authctxt *authctxt)
1506 debug("Offering public key: %s %s %s", 1593 debug("Offering public key: %s %s %s",
1507 sshkey_type(id->key), fp, id->filename); 1594 sshkey_type(id->key), fp, id->filename);
1508 free(fp); 1595 free(fp);
1509 sent = send_pubkey_test(authctxt, id); 1596 sent = send_pubkey_test(ssh, authctxt, id);
1510 } 1597 }
1511 } else { 1598 } else {
1512 debug("Trying private key: %s", id->filename); 1599 debug("Trying private key: %s", id->filename);
@@ -1514,7 +1601,7 @@ userauth_pubkey(Authctxt *authctxt)
1514 if (id->key != NULL) { 1601 if (id->key != NULL) {
1515 if (try_identity(id)) { 1602 if (try_identity(id)) {
1516 id->isprivate = 1; 1603 id->isprivate = 1;
1517 sent = sign_and_send_pubkey( 1604 sent = sign_and_send_pubkey(ssh,
1518 authctxt, id); 1605 authctxt, id);
1519 } 1606 }
1520 key_free(id->key); 1607 key_free(id->key);
@@ -1735,7 +1822,7 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
1735int 1822int
1736userauth_hostbased(Authctxt *authctxt) 1823userauth_hostbased(Authctxt *authctxt)
1737{ 1824{
1738 struct ssh *ssh = active_state; 1825 struct ssh *ssh = active_state; /* XXX */
1739 struct sshkey *private = NULL; 1826 struct sshkey *private = NULL;
1740 struct sshbuf *b = NULL; 1827 struct sshbuf *b = NULL;
1741 u_char *sig = NULL, *keyblob = NULL; 1828 u_char *sig = NULL, *keyblob = NULL;
diff --git a/sshd.c b/sshd.c
index edbe815c5..4cfb72dd3 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.508 2018/04/13 03:57:26 dtucker Exp $ */ 1/* $OpenBSD: sshd.c,v 1.509 2018/07/03 11:39:54 djm 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
@@ -681,45 +681,47 @@ privsep_postauth(Authctxt *authctxt)
681 packet_set_authenticated(); 681 packet_set_authenticated();
682} 682}
683 683
684static void
685append_hostkey_type(struct sshbuf *b, const char *s)
686{
687 int r;
688
689 if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) {
690 debug3("%s: %s key not permitted by HostkeyAlgorithms",
691 __func__, s);
692 return;
693 }
694 if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0)
695 fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r));
696}
697
684static char * 698static char *
685list_hostkey_types(void) 699list_hostkey_types(void)
686{ 700{
687 Buffer b; 701 struct sshbuf *b;
688 const char *p; 702 struct sshkey *key;
689 char *ret; 703 char *ret;
690 u_int i; 704 u_int i;
691 struct sshkey *key;
692 705
693 buffer_init(&b); 706 if ((b = sshbuf_new()) == NULL)
707 fatal("%s: sshbuf_new failed", __func__);
694 for (i = 0; i < options.num_host_key_files; i++) { 708 for (i = 0; i < options.num_host_key_files; i++) {
695 key = sensitive_data.host_keys[i]; 709 key = sensitive_data.host_keys[i];
696 if (key == NULL) 710 if (key == NULL)
697 key = sensitive_data.host_pubkeys[i]; 711 key = sensitive_data.host_pubkeys[i];
698 if (key == NULL) 712 if (key == NULL)
699 continue; 713 continue;
700 /* Check that the key is accepted in HostkeyAlgorithms */
701 if (match_pattern_list(sshkey_ssh_name(key),
702 options.hostkeyalgorithms, 0) != 1) {
703 debug3("%s: %s key not permitted by HostkeyAlgorithms",
704 __func__, sshkey_ssh_name(key));
705 continue;
706 }
707 switch (key->type) { 714 switch (key->type) {
708 case KEY_RSA: 715 case KEY_RSA:
716 /* for RSA we also support SHA2 signatures */
717 append_hostkey_type(b, "rsa-sha2-512");
718 append_hostkey_type(b, "rsa-sha2-256");
719 /* FALLTHROUGH */
709 case KEY_DSA: 720 case KEY_DSA:
710 case KEY_ECDSA: 721 case KEY_ECDSA:
711 case KEY_ED25519: 722 case KEY_ED25519:
712 case KEY_XMSS: 723 case KEY_XMSS:
713 if (buffer_len(&b) > 0) 724 append_hostkey_type(b, sshkey_ssh_name(key));
714 buffer_append(&b, ",", 1);
715 p = key_ssh_name(key);
716 buffer_append(&b, p, strlen(p));
717
718 /* for RSA we also support SHA2 signatures */
719 if (key->type == KEY_RSA) {
720 p = ",rsa-sha2-512,rsa-sha2-256";
721 buffer_append(&b, p, strlen(p));
722 }
723 break; 725 break;
724 } 726 }
725 /* If the private key has a cert peer, then list that too */ 727 /* If the private key has a cert peer, then list that too */
@@ -728,21 +730,24 @@ list_hostkey_types(void)
728 continue; 730 continue;
729 switch (key->type) { 731 switch (key->type) {
730 case KEY_RSA_CERT: 732 case KEY_RSA_CERT:
733 /* for RSA we also support SHA2 signatures */
734 append_hostkey_type(b,
735 "rsa-sha2-512-cert-v01@openssh.com");
736 append_hostkey_type(b,
737 "rsa-sha2-256-cert-v01@openssh.com");
738 /* FALLTHROUGH */
731 case KEY_DSA_CERT: 739 case KEY_DSA_CERT:
732 case KEY_ECDSA_CERT: 740 case KEY_ECDSA_CERT:
733 case KEY_ED25519_CERT: 741 case KEY_ED25519_CERT:
734 case KEY_XMSS_CERT: 742 case KEY_XMSS_CERT:
735 if (buffer_len(&b) > 0) 743 append_hostkey_type(b, sshkey_ssh_name(key));
736 buffer_append(&b, ",", 1);
737 p = key_ssh_name(key);
738 buffer_append(&b, p, strlen(p));
739 break; 744 break;
740 } 745 }
741 } 746 }
742 if ((ret = sshbuf_dup_string(&b)) == NULL) 747 if ((ret = sshbuf_dup_string(b)) == NULL)
743 fatal("%s: sshbuf_dup_string failed", __func__); 748 fatal("%s: sshbuf_dup_string failed", __func__);
744 buffer_free(&b); 749 sshbuf_free(b);
745 debug("list_hostkey_types: %s", ret); 750 debug("%s: %s", __func__, ret);
746 return ret; 751 return ret;
747} 752}
748 753
diff --git a/sshd_config.5 b/sshd_config.5
index 60c5f4bd3..cc019ec7d 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,7 +33,7 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd_config.5,v 1.278 2018/07/03 10:59:35 djm Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.279 2018/07/03 11:39:54 djm Exp $
37.Dd $Mdocdate: July 3 2018 $ 37.Dd $Mdocdate: July 3 2018 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
@@ -674,9 +674,10 @@ ecdsa-sha2-nistp256-cert-v01@openssh.com,
674ecdsa-sha2-nistp384-cert-v01@openssh.com, 674ecdsa-sha2-nistp384-cert-v01@openssh.com,
675ecdsa-sha2-nistp521-cert-v01@openssh.com, 675ecdsa-sha2-nistp521-cert-v01@openssh.com,
676ssh-ed25519-cert-v01@openssh.com, 676ssh-ed25519-cert-v01@openssh.com,
677rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
677ssh-rsa-cert-v01@openssh.com, 678ssh-rsa-cert-v01@openssh.com,
678ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, 679ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
679ssh-ed25519,ssh-rsa 680ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
680.Ed 681.Ed
681.Pp 682.Pp
682The list of available key types may also be obtained using 683The list of available key types may also be obtained using
@@ -751,9 +752,10 @@ ecdsa-sha2-nistp256-cert-v01@openssh.com,
751ecdsa-sha2-nistp384-cert-v01@openssh.com, 752ecdsa-sha2-nistp384-cert-v01@openssh.com,
752ecdsa-sha2-nistp521-cert-v01@openssh.com, 753ecdsa-sha2-nistp521-cert-v01@openssh.com,
753ssh-ed25519-cert-v01@openssh.com, 754ssh-ed25519-cert-v01@openssh.com,
755rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
754ssh-rsa-cert-v01@openssh.com, 756ssh-rsa-cert-v01@openssh.com,
755ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, 757ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
756ssh-ed25519,ssh-rsa 758ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
757.Ed 759.Ed
758.Pp 760.Pp
759The list of available key types may also be obtained using 761The list of available key types may also be obtained using
@@ -1399,9 +1401,10 @@ ecdsa-sha2-nistp256-cert-v01@openssh.com,
1399ecdsa-sha2-nistp384-cert-v01@openssh.com, 1401ecdsa-sha2-nistp384-cert-v01@openssh.com,
1400ecdsa-sha2-nistp521-cert-v01@openssh.com, 1402ecdsa-sha2-nistp521-cert-v01@openssh.com,
1401ssh-ed25519-cert-v01@openssh.com, 1403ssh-ed25519-cert-v01@openssh.com,
1404rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
1402ssh-rsa-cert-v01@openssh.com, 1405ssh-rsa-cert-v01@openssh.com,
1403ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, 1406ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
1404ssh-ed25519,ssh-rsa 1407ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
1405.Ed 1408.Ed
1406.Pp 1409.Pp
1407The list of available key types may also be obtained using 1410The list of available key types may also be obtained using
diff --git a/ssherr.c b/ssherr.c
index 3c0009d69..8ad3d5750 100644
--- a/ssherr.c
+++ b/ssherr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssherr.c,v 1.7 2017/09/12 06:32:08 djm Exp $ */ 1/* $OpenBSD: ssherr.c,v 1.8 2018/07/03 11:39:54 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller 3 * Copyright (c) 2011 Damien Miller
4 * 4 *
@@ -139,6 +139,8 @@ ssh_err(int n)
139 return "Invalid key length"; 139 return "Invalid key length";
140 case SSH_ERR_NUMBER_TOO_LARGE: 140 case SSH_ERR_NUMBER_TOO_LARGE:
141 return "number is too large"; 141 return "number is too large";
142 case SSH_ERR_SIGN_ALG_UNSUPPORTED:
143 return "signature algorithm not supported";
142 default: 144 default:
143 return "unknown error"; 145 return "unknown error";
144 } 146 }
diff --git a/ssherr.h b/ssherr.h
index c0b59211e..348da5a20 100644
--- a/ssherr.h
+++ b/ssherr.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssherr.h,v 1.5 2017/09/12 06:32:08 djm Exp $ */ 1/* $OpenBSD: ssherr.h,v 1.6 2018/07/03 11:39:54 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller 3 * Copyright (c) 2011 Damien Miller
4 * 4 *
@@ -79,6 +79,7 @@
79#define SSH_ERR_PROTOCOL_ERROR -55 79#define SSH_ERR_PROTOCOL_ERROR -55
80#define SSH_ERR_KEY_LENGTH -56 80#define SSH_ERR_KEY_LENGTH -56
81#define SSH_ERR_NUMBER_TOO_LARGE -57 81#define SSH_ERR_NUMBER_TOO_LARGE -57
82#define SSH_ERR_SIGN_ALG_UNSUPPORTED -58
82 83
83/* Translate a numeric error code to a human-readable error string */ 84/* Translate a numeric error code to a human-readable error string */
84const char *ssh_err(int n); 85const char *ssh_err(int n);
diff --git a/sshkey.c b/sshkey.c
index 7712fba23..455cf3d67 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.64 2018/03/22 07:05:48 markus Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.65 2018/07/03 11:39:54 djm 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,46 +83,64 @@ static int sshkey_from_blob_internal(struct sshbuf *buf,
83struct keytype { 83struct keytype {
84 const char *name; 84 const char *name;
85 const char *shortname; 85 const char *shortname;
86 const char *sigalg;
86 int type; 87 int type;
87 int nid; 88 int nid;
88 int cert; 89 int cert;
89 int sigonly; 90 int sigonly;
90}; 91};
91static const struct keytype keytypes[] = { 92static const struct keytype keytypes[] = {
92 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 }, 93 { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
93 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", 94 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
94 KEY_ED25519_CERT, 0, 1, 0 }, 95 KEY_ED25519_CERT, 0, 1, 0 },
95#ifdef WITH_XMSS 96#ifdef WITH_XMSS
96 { "ssh-xmss@openssh.com", "XMSS", KEY_XMSS, 0, 0, 0 }, 97 { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
97 { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", 98 { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
98 KEY_XMSS_CERT, 0, 1, 0 }, 99 KEY_XMSS_CERT, 0, 1, 0 },
99#endif /* WITH_XMSS */ 100#endif /* WITH_XMSS */
100#ifdef WITH_OPENSSL 101#ifdef WITH_OPENSSL
101 { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, 102 { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
102 { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, 103 { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
103 { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, 104 { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
104 { "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 }, 105 { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
105# ifdef OPENSSL_HAS_ECC 106# ifdef OPENSSL_HAS_ECC
106 { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 }, 107 { "ecdsa-sha2-nistp256", "ECDSA", NULL,
107 { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 }, 108 KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
109 { "ecdsa-sha2-nistp384", "ECDSA", NULL,
110 KEY_ECDSA, NID_secp384r1, 0, 0 },
108# ifdef OPENSSL_HAS_NISTP521 111# ifdef OPENSSL_HAS_NISTP521
109 { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 }, 112 { "ecdsa-sha2-nistp521", "ECDSA", NULL,
113 KEY_ECDSA, NID_secp521r1, 0, 0 },
110# endif /* OPENSSL_HAS_NISTP521 */ 114# endif /* OPENSSL_HAS_NISTP521 */
111# endif /* OPENSSL_HAS_ECC */ 115# endif /* OPENSSL_HAS_ECC */
112 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 }, 116 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
113 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 }, 117 KEY_RSA_CERT, 0, 1, 0 },
118 { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
119 "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
120 { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
121 "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
122 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
123 KEY_DSA_CERT, 0, 1, 0 },
124 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
125 KEY_RSA_CERT, 0, 1, 0 },
126 { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
127 "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
128 { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
129 "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
130 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
131 KEY_DSA_CERT, 0, 1, 0 },
114# ifdef OPENSSL_HAS_ECC 132# ifdef OPENSSL_HAS_ECC
115 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", 133 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
116 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 }, 134 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
117 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", 135 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
118 KEY_ECDSA_CERT, NID_secp384r1, 1, 0 }, 136 KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
119# ifdef OPENSSL_HAS_NISTP521 137# ifdef OPENSSL_HAS_NISTP521
120 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", 138 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
121 KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, 139 KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
122# endif /* OPENSSL_HAS_NISTP521 */ 140# endif /* OPENSSL_HAS_NISTP521 */
123# endif /* OPENSSL_HAS_ECC */ 141# endif /* OPENSSL_HAS_ECC */
124#endif /* WITH_OPENSSL */ 142#endif /* WITH_OPENSSL */
125 { NULL, NULL, -1, -1, 0, 0 } 143 { NULL, NULL, NULL, -1, -1, 0, 0 }
126}; 144};
127 145
128const char * 146const char *
@@ -2198,8 +2216,8 @@ sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2198 return r; 2216 return r;
2199} 2217}
2200 2218
2201int 2219static int
2202sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep) 2220get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
2203{ 2221{
2204 int r; 2222 int r;
2205 struct sshbuf *b = NULL; 2223 struct sshbuf *b = NULL;
@@ -2223,6 +2241,50 @@ sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
2223 return r; 2241 return r;
2224} 2242}
2225 2243
2244/*
2245 * Returns the expected signature algorithm for a given public key algorithm.
2246 */
2247static const char *
2248sigalg_by_name(const char *name)
2249{
2250 const struct keytype *kt;
2251
2252 for (kt = keytypes; kt->type != -1; kt++) {
2253 if (strcmp(kt->name, name) != 0)
2254 continue;
2255 if (kt->sigalg != NULL)
2256 return kt->sigalg;
2257 if (!kt->cert)
2258 return kt->name;
2259 return sshkey_ssh_name_from_type_nid(
2260 sshkey_type_plain(kt->type), kt->nid);
2261 }
2262 return NULL;
2263}
2264
2265/*
2266 * Verifies that the signature algorithm appearing inside the signature blob
2267 * matches that which was requested.
2268 */
2269int
2270sshkey_check_sigtype(const u_char *sig, size_t siglen,
2271 const char *requested_alg)
2272{
2273 const char *expected_alg;
2274 char *sigtype = NULL;
2275 int r;
2276
2277 if (requested_alg == NULL)
2278 return 0;
2279 if ((expected_alg = sigalg_by_name(requested_alg)) == NULL)
2280 return SSH_ERR_INVALID_ARGUMENT;
2281 if ((r = get_sigtype(sig, siglen, &sigtype)) != 0)
2282 return r;
2283 r = strcmp(expected_alg, sigtype) == 0;
2284 free(sigtype);
2285 return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
2286}
2287
2226int 2288int
2227sshkey_sign(const struct sshkey *key, 2289sshkey_sign(const struct sshkey *key,
2228 u_char **sigp, size_t *lenp, 2290 u_char **sigp, size_t *lenp,
diff --git a/sshkey.h b/sshkey.h
index 155cd45ae..0baf989f3 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.h,v 1.24 2018/02/23 15:58:38 markus Exp $ */ 1/* $OpenBSD: sshkey.h,v 1.25 2018/07/03 11:39:54 djm 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.
@@ -191,11 +191,11 @@ int sshkey_puts_opts(const struct sshkey *, struct sshbuf *,
191int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); 191int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
192int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); 192int sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
193 193
194int sshkey_sigtype(const u_char *, size_t, char **);
195int sshkey_sign(const struct sshkey *, u_char **, size_t *, 194int sshkey_sign(const struct sshkey *, u_char **, size_t *,
196 const u_char *, size_t, const char *, u_int); 195 const u_char *, size_t, const char *, u_int);
197int sshkey_verify(const struct sshkey *, const u_char *, size_t, 196int sshkey_verify(const struct sshkey *, const u_char *, size_t,
198 const u_char *, size_t, const char *, u_int); 197 const u_char *, size_t, const char *, u_int);
198int sshkey_check_sigtype(const u_char *, size_t, const char *);
199 199
200/* for debug */ 200/* for debug */
201void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *); 201void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);