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 49e71c87..1756315b 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.66 2018/02/14 16:27:24 jsing Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.67 2018/07/03 11:39:54 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
@@ -51,11 +51,14 @@ rsa_hash_alg_ident(int hash_alg)
return NULL;
}
+/*
+ * Returns the hash algorithm ID for a given algorithm identifier as used
+ * inside the signature blob,
+ */
static int
-rsa_hash_alg_from_ident(const char *ident)
+rsa_hash_id_from_ident(const char *ident)
{
- if (strcmp(ident, "ssh-rsa") == 0 ||
- strcmp(ident, "ssh-rsa-cert-v01@openssh.com") == 0)
+ if (strcmp(ident, "ssh-rsa") == 0)
return SSH_DIGEST_SHA1;
if (strcmp(ident, "rsa-sha2-256") == 0)
return SSH_DIGEST_SHA256;
@@ -64,6 +67,27 @@ rsa_hash_alg_from_ident(const char *ident)
return -1;
}
+/*
+ * Return the hash algorithm ID for the specified key name. This includes
+ * all the cases of rsa_hash_id_from_ident() but also the certificate key
+ * types.
+ */
+static int
+rsa_hash_id_from_keyname(const char *alg)
+{
+ int r;
+
+ if ((r = rsa_hash_id_from_ident(alg)) != -1)
+ return r;
+ if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
+ return SSH_DIGEST_SHA1;
+ if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
+ return SSH_DIGEST_SHA256;
+ if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
+ return SSH_DIGEST_SHA512;
+ return -1;
+}
+
static int
rsa_hash_alg_nid(int type)
{
@@ -135,7 +159,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
if (alg_ident == NULL || strlen(alg_ident) == 0)
hash_alg = SSH_DIGEST_SHA1;
else
- hash_alg = rsa_hash_alg_from_ident(alg_ident);
+ hash_alg = rsa_hash_id_from_keyname(alg_ident);
if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
sshkey_type_plain(key->type) != KEY_RSA)
return SSH_ERR_INVALID_ARGUMENT;
@@ -202,7 +226,7 @@ ssh_rsa_verify(const struct sshkey *key,
const char *alg)
{
char *sigtype = NULL;
- int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
+ int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
size_t len = 0, diff, modlen, dlen;
struct sshbuf *b = NULL;
u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
@@ -220,18 +244,24 @@ ssh_rsa_verify(const struct sshkey *key,
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
- /* XXX djm: need cert types that reliably yield SHA-2 signatures */
- if (alg != NULL && strcmp(alg, sigtype) != 0 &&
- strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
- error("%s: RSA signature type mismatch: "
- "expected %s received %s", __func__, alg, sigtype);
- ret = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
- if ((hash_alg = rsa_hash_alg_from_ident(sigtype)) == -1) {
+ if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
ret = SSH_ERR_KEY_TYPE_MISMATCH;
goto out;
}
+ /*
+ * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
+ * legacy reasons, but otherwise the signature type should match.
+ */
+ if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
+ if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
+ ret = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ if (hash_alg != want_alg) {
+ ret = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ }
if (sshbuf_get_string(b, &sigblob, &len) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;