summaryrefslogtreecommitdiff
path: root/ssh-rsa.c
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 /ssh-rsa.c
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
Diffstat (limited to 'ssh-rsa.c')
-rw-r--r--ssh-rsa.c60
1 files changed, 45 insertions, 15 deletions
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;