diff options
Diffstat (limited to 'ssh-rsa.c')
-rw-r--r-- | ssh-rsa.c | 60 |
1 files changed, 45 insertions, 15 deletions
@@ -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 | */ | ||
54 | static int | 58 | static int |
55 | rsa_hash_alg_from_ident(const char *ident) | 59 | rsa_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 | */ | ||
75 | static int | ||
76 | rsa_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 | |||
67 | static int | 91 | static int |
68 | rsa_hash_alg_nid(int type) | 92 | rsa_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; |