3des cipher and DH group size

Darren Tucker dtucker at zip.com.au
Sat Jan 25 21:17:28 EST 2014


On Fri, Jan 24, 2014 at 05:28:03PM +0100, Petr Lautrbach wrote:
> On 01/21/2014 05:14 PM, Petr Lautrbach wrote:
> > Hello everybody,
> > 
> > An issue was reported in RH bugzilla [1] about the size of the used DH
> > group  when combined with the 3des-cbc cipher. OpenSSH uses the
> > actual key length for the size estimation. This is probably fine as far
> > as the cipher has the same number of bits of security as the key
> > length. But this is not true for 3TDEA where the key size is 168 resp
> > 192 but it's security is only 112.
> > 
> > Given that the key size in openssh is set to 192, DH group size is
> > estimated to 7680. But according to NIST SP 800-57, the size of DH key
> > should be 2048 so openssh doesn't follow that  and it might cause
> > problems with key exchanges with some servers.
> > 
> 
> It was confirmed that openssh can't connect to the server with a server string
> 'SSH-2.0-cryptlib' using diffie-hellman-group-exchange-sha1 and 3des-cbc with
> SSH2_MSG_KEX_DH_GEX_REQUEST(1024<7680<8192).
 
Thanks for the patch.  Since we are so close to the 6.5 release I have
committed a smaller change that should still resolve the problem
(confirmed by checking the debug output for the requested group sizes).

Thanks.

Index: cipher.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/cipher.c,v
retrieving revision 1.93
diff -u -p -r1.93 cipher.c
--- cipher.c	6 Dec 2013 13:34:54 -0000	1.93
+++ cipher.c	25 Jan 2014 10:04:23 -0000
@@ -136,6 +136,14 @@ cipher_keylen(const Cipher *c)
 }
 
 u_int
+cipher_seclen(const Cipher *c)
+{
+	if (strcmp("3des-cbc", c->name) == 0)
+		return 14;
+	return cipher_keylen(c);
+}
+
+u_int
 cipher_authlen(const Cipher *c)
 {
 	return (c->auth_len);
Index: cipher.h
===================================================================
RCS file: /cvs/src/usr.bin/ssh/cipher.h,v
retrieving revision 1.43
diff -u -p -r1.43 cipher.h
--- cipher.h	6 Dec 2013 13:34:54 -0000	1.43
+++ cipher.h	25 Jan 2014 10:04:23 -0000
@@ -89,6 +89,7 @@ void	 cipher_cleanup(CipherContext *);
 void	 cipher_set_key_string(CipherContext *, const Cipher *, const char *, int);
 u_int	 cipher_blocksize(const Cipher *);
 u_int	 cipher_keylen(const Cipher *);
+u_int	 cipher_seclen(const Cipher *);
 u_int	 cipher_authlen(const Cipher *);
 u_int	 cipher_ivlen(const Cipher *);
 u_int	 cipher_is_cbc(const Cipher *);
Index: kex.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/kex.c,v
retrieving revision 1.95
diff -u -p -r1.95 kex.c
--- kex.c	12 Jan 2014 08:13:13 -0000	1.95
+++ kex.c	25 Jan 2014 10:04:23 -0000
@@ -438,7 +438,7 @@ kex_choose_conf(Kex *kex)
 	char **my, **peer;
 	char **cprop, **sprop;
 	int nenc, nmac, ncomp;
-	u_int mode, ctos, need, authlen;
+	u_int mode, ctos, need, dh_need, authlen;
 	int first_kex_follows, type;
 
 	my   = kex_buf2prop(&kex->my, NULL);
@@ -486,7 +486,7 @@ kex_choose_conf(Kex *kex)
 	choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
 	choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
 	    sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
-	need = 0;
+	need = dh_need = 0;
 	for (mode = 0; mode < MODE_MAX; mode++) {
 		newkeys = kex->newkeys[mode];
 		if (need < newkeys->enc.key_len)
@@ -497,9 +497,12 @@ kex_choose_conf(Kex *kex)
 			need = newkeys->enc.iv_len;
 		if (need < newkeys->mac.key_len)
 			need = newkeys->mac.key_len;
+		if (dh_need < cipher_seclen(newkeys->enc.cipher))
+			dh_need = cipher_seclen(newkeys->enc.cipher);
 	}
 	/* XXX need runden? */
 	kex->we_need = need;
+	kex->dh_need = dh_need;
 
 	/* ignore the next message if the proposals do not match */
 	if (first_kex_follows && !proposals_match(my, peer) &&
Index: kex.h
===================================================================
RCS file: /cvs/src/usr.bin/ssh/kex.h,v
retrieving revision 1.60
diff -u -p -r1.60 kex.h
--- kex.h	12 Jan 2014 08:13:13 -0000	1.60
+++ kex.h	25 Jan 2014 10:04:23 -0000
@@ -121,6 +121,7 @@ struct Kex {
 	u_int	session_id_len;
 	Newkeys	*newkeys[MODE_MAX];
 	u_int	we_need;
+	u_int	dh_need;
 	int	server;
 	char	*name;
 	int	hostkey_type;
Index: kexgexc.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/kexgexc.c,v
retrieving revision 1.15
diff -u -p -r1.15 kexgexc.c
--- kexgexc.c	12 Jan 2014 08:13:13 -0000	1.15
+++ kexgexc.c	25 Jan 2014 10:04:23 -0000
@@ -55,7 +55,7 @@ kexgex_client(Kex *kex)
 	int min, max, nbits;
 	DH *dh;
 
-	nbits = dh_estimate(kex->we_need * 8);
+	nbits = dh_estimate(kex->dh_need * 8);
 
 	if (datafellows & SSH_OLD_DHGEX) {
 		/* Old GEX request */

-- 
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.


More information about the openssh-unix-dev mailing list