ssh1 keyexchange problem ?

Markus Friedl Markus.Friedl at informatik.uni-erlangen.de
Fri Feb 9 00:53:59 EST 2001


On Thu, Feb 08, 2001 at 01:31:14PM +0200, Jarno Huuskonen wrote:
> Hi,
> 
> Has anybody produced diffs for openssh-2.3.0p1 for the rsa keyexchange
> problem that Core-SDI described ? ( I noticed that fix is already
> in openbsd tree ).
> 
> -Jarno
> 
> -- 
> Jarno Huuskonen - System Administrator   |  Jarno.Huuskonen at uku.fi
> University of Kuopio - Computer Center   |  Work:   +358 17 162822
> PO BOX 1627, 70211 Kuopio, Finland       |  Mobile: +358 40 5388169
> 

this one should help.

the fix from the advisory should help, too (just 
move the 'kill' to rsa.c).

Index: rsa.c
===================================================================
RCS file: /home/markus/cvs/ssh/rsa.c,v
retrieving revision 1.18
diff -u -r1.18 rsa.c
--- rsa.c	2000/12/19 23:17:57	1.18
+++ rsa.c	2001/01/20 18:59:12
@@ -94,7 +94,7 @@
 	xfree(inbuf);
 }
 
-void
+int
 rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
 {
 	u_char *inbuf, *outbuf;
@@ -108,13 +108,14 @@
 	BN_bn2bin(in, inbuf);
 
 	if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
-	    RSA_PKCS1_PADDING)) <= 0)
-		fatal("rsa_private_decrypt() failed");
-
-	BN_bin2bn(outbuf, len, out);
-
+	    RSA_PKCS1_PADDING)) <= 0) {
+		error("rsa_private_decrypt() failed");
+	} else {
+		BN_bin2bn(outbuf, len, out);
+	}
 	memset(outbuf, 0, olen);
 	memset(inbuf, 0, ilen);
 	xfree(outbuf);
 	xfree(inbuf);
+	return len;
 }
Index: rsa.h
===================================================================
RCS file: /home/markus/cvs/ssh/rsa.h,v
retrieving revision 1.9
diff -u -r1.9 rsa.h
--- rsa.h	2000/11/12 19:50:38	1.9
+++ rsa.h	2001/01/20 17:12:23
@@ -20,6 +20,6 @@
 #include <openssl/rsa.h>
 
 void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
-void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
+int rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
 
 #endif				/* RSA_H */
Index: ssh-agent.c
===================================================================
RCS file: /home/markus/cvs/ssh/ssh-agent.c,v
retrieving revision 1.46
diff -u -r1.46 ssh-agent.c
--- ssh-agent.c	2001/01/11 21:37:30	1.46
+++ ssh-agent.c	2001/01/20 18:59:26
@@ -195,7 +195,8 @@
 	private = lookup_private_key(key, NULL, 1);
 	if (private != NULL) {
 		/* Decrypt the challenge using the private key. */
-		rsa_private_decrypt(challenge, challenge, private->rsa);
+		if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
+			goto failure;
 
 		/* The response is MD5 of decrypted challenge plus session id. */
 		len = BN_num_bytes(challenge);
Index: sshconnect1.c
===================================================================
RCS file: /home/markus/cvs/ssh/sshconnect1.c,v
retrieving revision 1.17
diff -u -r1.17 sshconnect1.c
--- sshconnect1.c	2001/01/19 15:55:12	1.17
+++ sshconnect1.c	2001/01/20 18:59:31
@@ -153,14 +153,17 @@
 	int i, len;
 
 	/* Decrypt the challenge using the private key. */
-	rsa_private_decrypt(challenge, challenge, prv);
+	/* XXX think about Bleichenbacher, too */
+	if (rsa_private_decrypt(challenge, challenge, prv) <= 0)
+		packet_disconnect(
+		    "respond_to_rsa_challenge: rsa_private_decrypt failed");
 
 	/* Compute the response. */
 	/* The response is MD5 of decrypted challenge plus session id. */
 	len = BN_num_bytes(challenge);
 	if (len <= 0 || len > sizeof(buf))
-		packet_disconnect("respond_to_rsa_challenge: bad challenge length %d",
-				  len);
+		packet_disconnect(
+		    "respond_to_rsa_challenge: bad challenge length %d", len);
 
 	memset(buf, 0, sizeof(buf));
 	BN_bn2bin(challenge, buf + sizeof(buf) - len);
Index: sshd.c
===================================================================
RCS file: /home/markus/cvs/ssh/sshd.c,v
retrieving revision 1.154
diff -u -r1.154 sshd.c
--- sshd.c	2001/01/19 15:55:12	1.154
+++ sshd.c	2001/01/20 20:32:29
@@ -1163,6 +1163,7 @@
 {
 	int i, len;
 	int plen, slen;
+	int rsafail = 0;
 	BIGNUM *session_key_int;
 	u_char session_key[SSH_SESSION_KEY_LENGTH];
 	u_char cookie[8];
@@ -1273,7 +1274,7 @@
 	 * with larger modulus first).
 	 */
 	if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
-		/* Private key has bigger modulus. */
+		/* Server key has bigger modulus. */
 		if (BN_num_bits(sensitive_data.server_key->rsa->n) <
 		    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
 			fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
@@ -1282,10 +1283,12 @@
 			    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
 			    SSH_KEY_BITS_RESERVED);
 		}
-		rsa_private_decrypt(session_key_int, session_key_int,
-		    sensitive_data.server_key->rsa);
-		rsa_private_decrypt(session_key_int, session_key_int,
-		    sensitive_data.ssh1_host_key->rsa);
+		if (rsa_private_decrypt(session_key_int, session_key_int,
+		    sensitive_data.server_key->rsa) <= 0)
+			rsafail++;
+		if (rsa_private_decrypt(session_key_int, session_key_int,
+		    sensitive_data.ssh1_host_key->rsa) <= 0)
+			rsafail++;
 	} else {
 		/* Host key has bigger modulus (or they are equal). */
 		if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
@@ -1296,10 +1299,12 @@
 			    BN_num_bits(sensitive_data.server_key->rsa->n),
 			    SSH_KEY_BITS_RESERVED);
 		}
-		rsa_private_decrypt(session_key_int, session_key_int,
-		    sensitive_data.ssh1_host_key->rsa);
-		rsa_private_decrypt(session_key_int, session_key_int,
-		    sensitive_data.server_key->rsa);
+		if (rsa_private_decrypt(session_key_int, session_key_int,
+		    sensitive_data.ssh1_host_key->rsa) < 0)
+			rsafail++;
+		if (rsa_private_decrypt(session_key_int, session_key_int,
+		    sensitive_data.server_key->rsa) < 0)
+			rsafail++;
 	}
 
 	compute_session_id(session_id, cookie,
@@ -1314,15 +1319,29 @@
 	 * least significant 256 bits of the integer; the first byte of the
 	 * key is in the highest bits.
 	 */
-	BN_mask_bits(session_key_int, sizeof(session_key) * 8);
-	len = BN_num_bytes(session_key_int);
-	if (len < 0 || len > sizeof(session_key))
-		fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d",
-		    get_remote_ipaddr(),
-		    len, sizeof(session_key));
-	memset(session_key, 0, sizeof(session_key));
-	BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
-
+	if (!rsafail) {
+		BN_mask_bits(session_key_int, sizeof(session_key) * 8);
+		len = BN_num_bytes(session_key_int);
+		if (len < 0 || len > sizeof(session_key)) {
+			error("do_connection: bad session key len from %s: "
+			    "session_key_int %d > sizeof(session_key) %d",
+			    get_remote_ipaddr(), len, sizeof(session_key));
+			rsafail++;
+		} else {
+			memset(session_key, 0, sizeof(session_key));
+			BN_bn2bin(session_key_int,
+			    session_key + sizeof(session_key) - len);
+		}
+	}
+	if (rsafail) {
+		log("do_connection: generating a fake encryption key");
+		for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
+			if (i % 4 == 0)
+				rand = arc4random();
+			session_key[i] = rand & 0xff;
+			rand >>= 8;
+		}
+	}
 	/* Destroy the decrypted integer.  It is no longer needed. */
 	BN_clear_free(session_key_int);
 







More information about the openssh-unix-dev mailing list