[openssh-commits] [openssh] 19/87: upstream: enforce some basic size and consistency checks on RSA
git+noreply at mindrot.org
git+noreply at mindrot.org
Fri Oct 30 20:20:56 AEDT 2026
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit 3e2bbf8711c999cda9c68ee664ac259567998dd3
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Fri Oct 30 01:45:14 2026 +0000
upstream: enforce some basic size and consistency checks on RSA
private values (d, iqmp, etc). This could be used for an (unlikely) DoS
against ssh-agent if an attacker can add a bogus key to it.
Anthropic ANT-2026-9VCMKJ8F
OpenBSD-Commit-ID: 0d92a5412dc1c32d25e585214bfd71f95a7883f6
---
ssh-rsa.c | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/ssh-rsa.c b/ssh-rsa.c
index ccadb14ca..7165b40ae 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.84 2026/02/14 00:18:34 jsg Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.85 2026/10/30 01:45:14 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus at openbsd.org>
*
@@ -235,7 +235,9 @@ ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
int r;
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
- BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL;
+ BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL, *rsa_pq = NULL;
+ const BIGNUM *n = NULL, *e = NULL;
+ BN_CTX *ctx = NULL;
RSA *rsa = NULL;
if (sshkey_is_cert(key)) {
@@ -264,6 +266,31 @@ ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
(r = sshbuf_get_bignum2(b, &rsa_p)) != 0 ||
(r = sshbuf_get_bignum2(b, &rsa_q)) != 0)
goto out;
+ /*
+ * libcrypto doesn't check that the private values belong to the
+ * modulus, but the cost of using the key is determined by their
+ * size, so check them here before they can be used to sign.
+ */
+ RSA_get0_key(rsa, &n, &e, NULL);
+ if ((ctx = BN_CTX_new()) == NULL || (rsa_pq = BN_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (BN_mul(rsa_pq, rsa_p, rsa_q, ctx) != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (BN_cmp(rsa_pq, n) != 0 || BN_cmp(rsa_d, n) >= 0 ||
+ BN_cmp(rsa_iqmp, rsa_p) >= 0 || BN_cmp(e, n) >= 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* Same limit on the public exponent as libcrypto's public key ops */
+ if (BN_num_bits(n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
+ BN_num_bits(e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q,
rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0)
goto out;
@@ -304,6 +331,8 @@ ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
BN_clear_free(rsa_iqmp);
BN_clear_free(rsa_dmp1);
BN_clear_free(rsa_dmq1);
+ BN_clear_free(rsa_pq);
+ BN_CTX_free(ctx);
return r;
}
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list