forked from rpms/openssh
1506e0825c
SHA1 is insecure now, and is forbidden in RHEL and will be forbidden in several crypto-policies in Fedora in some future. This patch adds detection of SHA1 signatures availability and, if not available, enforces fallback to SHA2.
427 lines
17 KiB
Diff
427 lines
17 KiB
Diff
diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c
|
|
--- openssh-8.7p1/compat.c.sshrsacheck 2023-01-12 13:29:06.338710923 +0100
|
|
+++ openssh-8.7p1/compat.c 2023-01-12 13:29:06.357711165 +0100
|
|
@@ -43,6 +43,7 @@ void
|
|
compat_banner(struct ssh *ssh, const char *version)
|
|
{
|
|
int i;
|
|
+ int forbid_ssh_rsa = 0;
|
|
static struct {
|
|
char *pat;
|
|
int bugs;
|
|
@@ -145,16 +146,21 @@ compat_banner(struct ssh *ssh, const cha
|
|
};
|
|
|
|
/* process table, return first match */
|
|
+ forbid_ssh_rsa = (ssh->compat & SSH_RH_RSASIGSHA);
|
|
ssh->compat = 0;
|
|
for (i = 0; check[i].pat; i++) {
|
|
if (match_pattern_list(version, check[i].pat, 0) == 1) {
|
|
debug_f("match: %s pat %s compat 0x%08x",
|
|
version, check[i].pat, check[i].bugs);
|
|
ssh->compat = check[i].bugs;
|
|
+ if (forbid_ssh_rsa)
|
|
+ ssh->compat |= SSH_RH_RSASIGSHA;
|
|
return;
|
|
}
|
|
}
|
|
debug_f("no match: %s", version);
|
|
+ if (forbid_ssh_rsa)
|
|
+ ssh->compat |= SSH_RH_RSASIGSHA;
|
|
}
|
|
|
|
/* Always returns pointer to allocated memory, caller must free. */
|
|
diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h
|
|
--- openssh-8.7p1/compat.h.sshrsacheck 2021-08-20 06:03:49.000000000 +0200
|
|
+++ openssh-8.7p1/compat.h 2023-01-12 13:29:06.358711178 +0100
|
|
@@ -30,7 +30,7 @@
|
|
#define SSH_BUG_UTF8TTYMODE 0x00000001
|
|
#define SSH_BUG_SIGTYPE 0x00000002
|
|
#define SSH_BUG_SIGTYPE74 0x00000004
|
|
-/* #define unused 0x00000008 */
|
|
+#define SSH_RH_RSASIGSHA 0x00000008
|
|
#define SSH_OLD_SESSIONID 0x00000010
|
|
/* #define unused 0x00000020 */
|
|
#define SSH_BUG_DEBUG 0x00000040
|
|
diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c
|
|
--- openssh-8.7p1/monitor.c.sshrsacheck 2023-01-20 13:07:54.279676981 +0100
|
|
+++ openssh-8.7p1/monitor.c 2023-01-20 15:01:07.007821379 +0100
|
|
@@ -660,11 +660,12 @@ mm_answer_sign(struct ssh *ssh, int sock
|
|
struct sshkey *key;
|
|
struct sshbuf *sigbuf = NULL;
|
|
u_char *p = NULL, *signature = NULL;
|
|
- char *alg = NULL;
|
|
+ char *alg = NULL, *effective_alg;
|
|
size_t datlen, siglen, alglen;
|
|
int r, is_proof = 0;
|
|
u_int keyid, compat;
|
|
const char proof_req[] = "hostkeys-prove-00@openssh.com";
|
|
+ const char safe_rsa[] = "rsa-sha2-256";
|
|
|
|
debug3_f("entering");
|
|
|
|
@@ -719,18 +720,30 @@ mm_answer_sign(struct ssh *ssh, int sock
|
|
}
|
|
|
|
if ((key = get_hostkey_by_index(keyid)) != NULL) {
|
|
- if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg,
|
|
+ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0
|
|
+ && (sshkey_type_plain(key->type) == KEY_RSA)) {
|
|
+ effective_alg = safe_rsa;
|
|
+ } else {
|
|
+ effective_alg = alg;
|
|
+ }
|
|
+ if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, effective_alg,
|
|
options.sk_provider, NULL, compat)) != 0)
|
|
fatal_fr(r, "sign");
|
|
} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
|
|
auth_sock > 0) {
|
|
+ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0
|
|
+ && (sshkey_type_plain(key->type) == KEY_RSA)) {
|
|
+ effective_alg = safe_rsa;
|
|
+ } else {
|
|
+ effective_alg = alg;
|
|
+ }
|
|
if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
|
|
- p, datlen, alg, compat)) != 0)
|
|
+ p, datlen, effective_alg, compat)) != 0)
|
|
fatal_fr(r, "agent sign");
|
|
} else
|
|
fatal_f("no hostkey from index %d", keyid);
|
|
|
|
- debug3_f("%s %s signature len=%zu", alg,
|
|
+ debug3_f("%s (effective: %s) %s signature len=%zu", alg, effective_alg,
|
|
is_proof ? "hostkey proof" : "KEX", siglen);
|
|
|
|
sshbuf_reset(m);
|
|
diff -up openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck openssh-8.7p1/regress/cert-userkey.sh
|
|
--- openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck 2023-01-25 14:26:52.885963113 +0100
|
|
+++ openssh-8.7p1/regress/cert-userkey.sh 2023-01-25 14:27:25.757219800 +0100
|
|
@@ -7,7 +7,8 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us
|
|
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
|
|
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
|
|
|
|
-PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
|
|
+#ssh-dss keys are incompatible with DEFAULT crypto policy
|
|
+PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss' | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
|
|
EXTRA_TYPES=""
|
|
rsa=""
|
|
|
|
diff -up openssh-8.7p1/regress/Makefile.sshrsacheck openssh-8.7p1/regress/Makefile
|
|
--- openssh-8.7p1/regress/Makefile.sshrsacheck 2023-01-20 13:07:54.169676051 +0100
|
|
+++ openssh-8.7p1/regress/Makefile 2023-01-20 13:07:54.290677074 +0100
|
|
@@ -2,7 +2,8 @@
|
|
|
|
tests: prep file-tests t-exec unit
|
|
|
|
-REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12
|
|
+#ssh-dss tests will not pass on DEFAULT crypto-policy because of SHA1, skipping
|
|
+REGRESS_TARGETS= t1 t2 t3 t4 t5 t7 t8 t9 t10 t11 t12
|
|
|
|
# File based tests
|
|
file-tests: $(REGRESS_TARGETS)
|
|
diff -up openssh-8.7p1/regress/test-exec.sh.sshrsacheck openssh-8.7p1/regress/test-exec.sh
|
|
--- openssh-8.7p1/regress/test-exec.sh.sshrsacheck 2023-01-25 14:24:54.778040819 +0100
|
|
+++ openssh-8.7p1/regress/test-exec.sh 2023-01-25 14:26:39.500858590 +0100
|
|
@@ -581,8 +581,9 @@ maybe_filter_sk() {
|
|
fi
|
|
}
|
|
|
|
-SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk`
|
|
-SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk`
|
|
+#ssh-dss keys are incompatible with DEFAULT crypto policy
|
|
+SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'`
|
|
+SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'`
|
|
|
|
for t in ${SSH_KEYTYPES}; do
|
|
# generate user key
|
|
diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p1/regress/unittests/kex/test_kex.c
|
|
--- openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck 2023-01-26 13:34:52.645743677 +0100
|
|
+++ openssh-8.7p1/regress/unittests/kex/test_kex.c 2023-01-26 13:36:56.220745823 +0100
|
|
@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype,
|
|
memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
|
|
if (kex != NULL)
|
|
kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
|
|
- keyname = strdup(sshkey_ssh_name(private));
|
|
+ keyname = (strcmp(sshkey_ssh_name(private), "ssh-rsa")) ?
|
|
+ strdup(sshkey_ssh_name(private)) : strdup("rsa-sha2-256");
|
|
ASSERT_PTR_NE(keyname, NULL);
|
|
kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
|
|
ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
|
|
@@ -180,7 +181,7 @@ do_kex(char *kex)
|
|
{
|
|
#ifdef WITH_OPENSSL
|
|
do_kex_with_key(kex, KEY_RSA, 2048);
|
|
- do_kex_with_key(kex, KEY_DSA, 1024);
|
|
+ /* do_kex_with_key(kex, KEY_DSA, 1024); */
|
|
#ifdef OPENSSL_HAS_ECC
|
|
do_kex_with_key(kex, KEY_ECDSA, 256);
|
|
#endif /* OPENSSL_HAS_ECC */
|
|
diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_file.c
|
|
--- openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100
|
|
+++ openssh-8.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100
|
|
@@ -110,6 +110,7 @@ sshkey_file_tests(void)
|
|
sshkey_free(k2);
|
|
TEST_DONE();
|
|
|
|
+ /* Skip this test, SHA1 signatures are not supported
|
|
TEST_START("load RSA cert with SHA1 signature");
|
|
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0);
|
|
ASSERT_PTR_NE(k2, NULL);
|
|
@@ -117,7 +118,7 @@ sshkey_file_tests(void)
|
|
ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
|
|
ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa");
|
|
sshkey_free(k2);
|
|
- TEST_DONE();
|
|
+ TEST_DONE(); */
|
|
|
|
TEST_START("load RSA cert with SHA512 signature");
|
|
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0);
|
|
diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c
|
|
--- openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck 2023-01-26 12:10:37.533168013 +0100
|
|
+++ openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c 2023-01-26 12:15:35.637631860 +0100
|
|
@@ -333,13 +333,14 @@ sshkey_fuzz_tests(void)
|
|
TEST_DONE();
|
|
|
|
#ifdef WITH_OPENSSL
|
|
+ /* Skip this test, SHA1 signatures are not supported
|
|
TEST_START("fuzz RSA sig");
|
|
buf = load_file("rsa_1");
|
|
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
|
|
sshbuf_free(buf);
|
|
sig_fuzz(k1, "ssh-rsa");
|
|
sshkey_free(k1);
|
|
- TEST_DONE();
|
|
+ TEST_DONE();*/
|
|
|
|
TEST_START("fuzz RSA SHA256 sig");
|
|
buf = load_file("rsa_1");
|
|
@@ -357,6 +358,7 @@ sshkey_fuzz_tests(void)
|
|
sshkey_free(k1);
|
|
TEST_DONE();
|
|
|
|
+ /* Skip this test, SHA1 signatures are not supported
|
|
TEST_START("fuzz DSA sig");
|
|
buf = load_file("dsa_1");
|
|
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
|
|
@@ -364,6 +366,7 @@ sshkey_fuzz_tests(void)
|
|
sig_fuzz(k1, NULL);
|
|
sshkey_free(k1);
|
|
TEST_DONE();
|
|
+ */
|
|
|
|
#ifdef OPENSSL_HAS_ECC
|
|
TEST_START("fuzz ECDSA sig");
|
|
diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c
|
|
--- openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100
|
|
+++ openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100
|
|
@@ -60,6 +60,9 @@ build_cert(struct sshbuf *b, struct sshk
|
|
u_char *sigblob;
|
|
size_t siglen;
|
|
|
|
+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */
|
|
+ int expected = (sig_alg == NULL || strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0;
|
|
+
|
|
ca_buf = sshbuf_new();
|
|
ASSERT_PTR_NE(ca_buf, NULL);
|
|
ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0);
|
|
@@ -101,8 +104,9 @@ build_cert(struct sshbuf *b, struct sshk
|
|
ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */
|
|
ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */
|
|
ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen,
|
|
- sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0);
|
|
- ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */
|
|
+ sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), expected);
|
|
+ if (expected == 0)
|
|
+ ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */
|
|
|
|
free(sigblob);
|
|
sshbuf_free(ca_buf);
|
|
@@ -119,16 +123,22 @@ signature_test(struct sshkey *k, struct
|
|
{
|
|
size_t len;
|
|
u_char *sig;
|
|
+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */
|
|
+ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0;
|
|
+ if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT))
|
|
+ expected = SSH_ERR_LIBCRYPTO_ERROR;
|
|
|
|
ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg,
|
|
- NULL, NULL, 0), 0);
|
|
- ASSERT_SIZE_T_GT(len, 8);
|
|
- ASSERT_PTR_NE(sig, NULL);
|
|
- ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
|
|
- ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0);
|
|
- /* Fuzz test is more comprehensive, this is just a smoke test */
|
|
- sig[len - 5] ^= 0x10;
|
|
- ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
|
|
+ NULL, NULL, 0), expected);
|
|
+ if (expected == 0) {
|
|
+ ASSERT_SIZE_T_GT(len, 8);
|
|
+ ASSERT_PTR_NE(sig, NULL);
|
|
+ ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
|
|
+ ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0);
|
|
+ /* Fuzz test is more comprehensive, this is just a smoke test */
|
|
+ sig[len - 5] ^= 0x10;
|
|
+ ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
|
|
+ }
|
|
free(sig);
|
|
}
|
|
|
|
@@ -514,7 +524,7 @@ sshkey_tests(void)
|
|
ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
|
|
NULL), 0);
|
|
k3 = get_private("rsa_1");
|
|
- build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, NULL);
|
|
+ build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, "rsa-sha2-256");
|
|
ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
|
|
SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
|
|
ASSERT_PTR_EQ(k4, NULL);
|
|
diff -up openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck openssh-8.7p1/regress/unittests/sshsig/tests.c
|
|
--- openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck 2023-01-26 12:19:23.659513651 +0100
|
|
+++ openssh-8.7p1/regress/unittests/sshsig/tests.c 2023-01-26 12:20:28.021044803 +0100
|
|
@@ -102,9 +102,11 @@ tests(void)
|
|
check_sig("rsa.pub", "rsa.sig", msg, namespace);
|
|
TEST_DONE();
|
|
|
|
+ /* Skip this test, SHA1 signatures are not supported
|
|
TEST_START("check DSA signature");
|
|
check_sig("dsa.pub", "dsa.sig", msg, namespace);
|
|
TEST_DONE();
|
|
+ */
|
|
|
|
#ifdef OPENSSL_HAS_ECC
|
|
TEST_START("check ECDSA signature");
|
|
diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c
|
|
--- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100
|
|
+++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100
|
|
@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh *
|
|
else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED)
|
|
sigalg = "rsa-sha2-256";
|
|
}
|
|
+ if (ssh->compat & SSH_RH_RSASIGSHA && sigalg == NULL) {
|
|
+ sigalg = "rsa-sha2-512";
|
|
+ debug3_f("SHA1 signature is not supported, falling back to %s", sigalg);
|
|
+ }
|
|
debug3_f("sign %s key (index %d) using sigalg %s",
|
|
sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg);
|
|
if ((r = sshbuf_put_cstring(sigbuf,
|
|
diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c
|
|
--- openssh-8.7p1/sshconnect2.c.sshrsacheck 2023-01-25 15:33:29.140353651 +0100
|
|
+++ openssh-8.7p1/sshconnect2.c 2023-01-25 15:59:34.225364883 +0100
|
|
@@ -1461,6 +1464,14 @@ identity_sign(struct identity *id, u_cha
|
|
retried = 1;
|
|
goto retry_pin;
|
|
}
|
|
+ if ((r == SSH_ERR_LIBCRYPTO_ERROR) && strcmp("ssh-rsa", alg)) {
|
|
+ char rsa_safe_alg[] = "rsa-sha2-512";
|
|
+ debug3_f("trying to fallback to algorithm %s", rsa_safe_alg);
|
|
+
|
|
+ if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen,
|
|
+ rsa_safe_alg, options.sk_provider, pin, compat)) != 0)
|
|
+ debug_fr(r, "sshkey_sign - RSA fallback");
|
|
+ }
|
|
goto out;
|
|
}
|
|
|
|
diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c
|
|
--- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100
|
|
+++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100
|
|
@@ -1640,6 +1651,7 @@ main(int ac, char **av)
|
|
int keytype;
|
|
Authctxt *authctxt;
|
|
struct connection_info *connection_info = NULL;
|
|
+ int forbid_ssh_rsa = 0;
|
|
|
|
#ifdef HAVE_SECUREWARE
|
|
(void)set_auth_parameters(ac, av);
|
|
@@ -1938,6 +1950,33 @@ main(int ac, char **av)
|
|
key = NULL;
|
|
continue;
|
|
}
|
|
+ if (key && (sshkey_type_plain(key->type) == KEY_RSA || sshkey_type_plain(key->type) == KEY_RSA_CERT)) {
|
|
+ size_t sign_size = 0;
|
|
+ u_char *tmp = NULL;
|
|
+ u_char data[] = "Test SHA1 vector";
|
|
+ int res;
|
|
+
|
|
+ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0);
|
|
+ free(tmp);
|
|
+ if (res == SSH_ERR_LIBCRYPTO_ERROR) {
|
|
+ verbose_f("sshd: SHA1 in signatures is disabled for RSA keys");
|
|
+ forbid_ssh_rsa = 1;
|
|
+ }
|
|
+ }
|
|
+ if (key && (sshkey_type_plain(key->type) == KEY_DSA || sshkey_type_plain(key->type) == KEY_DSA_CERT)) {
|
|
+ size_t sign_size = 0;
|
|
+ u_char *tmp = NULL;
|
|
+ u_char data[] = "Test SHA1 vector";
|
|
+ int res;
|
|
+
|
|
+ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0);
|
|
+ free(tmp);
|
|
+ if (res == SSH_ERR_LIBCRYPTO_ERROR) {
|
|
+ logit_f("sshd: ssh-dss is disabled, skipping key file %s", options.host_key_files[i]);
|
|
+ key = NULL;
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
if (sshkey_is_sk(key) &&
|
|
key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
|
|
debug("host key %s requires user presence, ignoring",
|
|
@@ -2275,6 +2306,9 @@ main(int ac, char **av)
|
|
|
|
check_ip_options(ssh);
|
|
|
|
+ if (forbid_ssh_rsa)
|
|
+ ssh->compat |= SSH_RH_RSASIGSHA;
|
|
+
|
|
/* Prepare the channels layer */
|
|
channel_init_channels(ssh);
|
|
channel_set_af(ssh, options.address_family);
|
|
diff -Nur openssh-8.7p1/ssh-keygen.c openssh-8.7p1_patched/ssh-keygen.c
|
|
--- openssh-8.7p1/ssh-keygen.c 2023-01-18 17:41:47.894515779 +0100
|
|
+++ openssh-8.7p1_patched/ssh-keygen.c 2023-01-18 17:41:44.500488818 +0100
|
|
@@ -491,6 +491,8 @@
|
|
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
|
|
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
|
|
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
|
|
+ char rsa_safe_alg[] = "rsa-sha2-256";
|
|
+ char *alg = NULL;
|
|
|
|
if ((r = sshbuf_get_u32(b, &magic)) != 0)
|
|
fatal_fr(r, "parse magic");
|
|
@@ -590,6 +592,7 @@ do_convert_private_ssh2(struct sshbuf *b
|
|
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
|
|
fatal_fr(r, "generate RSA parameters");
|
|
BN_clear_free(rsa_iqmp);
|
|
+ alg = rsa_safe_alg;
|
|
break;
|
|
}
|
|
rlen = sshbuf_len(b);
|
|
@@ -598,9 +601,9 @@ do_convert_private_ssh2(struct sshbuf *b
|
|
|
|
/* try the key */
|
|
if (sshkey_sign(key, &sig, &slen, data, sizeof(data),
|
|
- NULL, NULL, NULL, 0) != 0 ||
|
|
+ alg, NULL, NULL, 0) != 0 ||
|
|
sshkey_verify(key, sig, slen, data, sizeof(data),
|
|
- NULL, 0, NULL) != 0) {
|
|
+ alg, 0, NULL) != 0) {
|
|
sshkey_free(key);
|
|
free(sig);
|
|
return NULL;
|
|
diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c
|
|
--- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100
|
|
+++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100
|
|
@@ -254,7 +254,8 @@ ssh_rsa_verify(const struct sshkey *key,
|
|
ret = SSH_ERR_INVALID_ARGUMENT;
|
|
goto out;
|
|
}
|
|
- if (hash_alg != want_alg) {
|
|
+ if (hash_alg != want_alg && want_alg != SSH_DIGEST_SHA1) {
|
|
+ debug_f("Unexpected digest algorithm: got %d, wanted %d", hash_alg, want_alg);
|
|
ret = SSH_ERR_SIGNATURE_INVALID;
|
|
goto out;
|
|
}
|