[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