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
diff --git a/sshkey.c b/sshkey.c
index 7712fba..455cf3d 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.64 2018/03/22 07:05:48 markus Exp $ */
+/* $OpenBSD: sshkey.c,v 1.65 2018/07/03 11:39:54 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -83,46 +83,64 @@
struct keytype {
const char *name;
const char *shortname;
+ const char *sigalg;
int type;
int nid;
int cert;
int sigonly;
};
static const struct keytype keytypes[] = {
- { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },
- { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
+ { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
+ { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
KEY_ED25519_CERT, 0, 1, 0 },
#ifdef WITH_XMSS
- { "ssh-xmss@openssh.com", "XMSS", KEY_XMSS, 0, 0, 0 },
- { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT",
+ { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
+ { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
KEY_XMSS_CERT, 0, 1, 0 },
#endif /* WITH_XMSS */
#ifdef WITH_OPENSSL
- { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },
- { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },
- { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 },
- { "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 },
+ { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
+ { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
+ { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
+ { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
# ifdef OPENSSL_HAS_ECC
- { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
- { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 },
+ { "ecdsa-sha2-nistp256", "ECDSA", NULL,
+ KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
+ { "ecdsa-sha2-nistp384", "ECDSA", NULL,
+ KEY_ECDSA, NID_secp384r1, 0, 0 },
# ifdef OPENSSL_HAS_NISTP521
- { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 },
+ { "ecdsa-sha2-nistp521", "ECDSA", NULL,
+ KEY_ECDSA, NID_secp521r1, 0, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
# endif /* OPENSSL_HAS_ECC */
- { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 },
- { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 },
+ { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
+ KEY_RSA_CERT, 0, 1, 0 },
+ { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
+ "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
+ { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
+ "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
+ { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
+ KEY_DSA_CERT, 0, 1, 0 },
+ { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
+ KEY_RSA_CERT, 0, 1, 0 },
+ { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
+ "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
+ { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
+ "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
+ { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
+ KEY_DSA_CERT, 0, 1, 0 },
# ifdef OPENSSL_HAS_ECC
- { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
+ { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
- { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
+ { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
# ifdef OPENSSL_HAS_NISTP521
- { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
- KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
+ { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
+ KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
- { NULL, NULL, -1, -1, 0, 0 }
+ { NULL, NULL, NULL, -1, -1, 0, 0 }
};
const char *
@@ -2198,8 +2216,8 @@
return r;
}
-int
-sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
+static int
+get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
{
int r;
struct sshbuf *b = NULL;
@@ -2223,6 +2241,50 @@
return r;
}
+/*
+ * Returns the expected signature algorithm for a given public key algorithm.
+ */
+static const char *
+sigalg_by_name(const char *name)
+{
+ const struct keytype *kt;
+
+ for (kt = keytypes; kt->type != -1; kt++) {
+ if (strcmp(kt->name, name) != 0)
+ continue;
+ if (kt->sigalg != NULL)
+ return kt->sigalg;
+ if (!kt->cert)
+ return kt->name;
+ return sshkey_ssh_name_from_type_nid(
+ sshkey_type_plain(kt->type), kt->nid);
+ }
+ return NULL;
+}
+
+/*
+ * Verifies that the signature algorithm appearing inside the signature blob
+ * matches that which was requested.
+ */
+int
+sshkey_check_sigtype(const u_char *sig, size_t siglen,
+ const char *requested_alg)
+{
+ const char *expected_alg;
+ char *sigtype = NULL;
+ int r;
+
+ if (requested_alg == NULL)
+ return 0;
+ if ((expected_alg = sigalg_by_name(requested_alg)) == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((r = get_sigtype(sig, siglen, &sigtype)) != 0)
+ return r;
+ r = strcmp(expected_alg, sigtype) == 0;
+ free(sigtype);
+ return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
+}
+
int
sshkey_sign(const struct sshkey *key,
u_char **sigp, size_t *lenp,