diff -U0 openssh-6.4p1/ChangeLog.3des-dh-size openssh-6.4p1/ChangeLog --- openssh-6.4p1/ChangeLog.3des-dh-size 2014-01-28 14:15:25.178358616 +0100 +++ openssh-6.4p1/ChangeLog 2014-01-28 14:18:24.678444650 +0100 @@ -0,0 +1,15 @@ +20140126 + - OpenBSD CVS Sync + - dtucker@cvs.openbsd.org 2014/01/25 10:12:50 + [cipher.c cipher.h kex.c kex.h kexgexc.c] + Add a special case for the DH group size for 3des-cbc, which has an + effective strength much lower than the key size. This causes problems + with some cryptlib implementations, which don't support group sizes larger + than 4k but also don't use the largest group size it does support as + specified in the RFC. Based on a patch from Petr Lautrbach at Redhat, + reduced by me with input from Markus. ok djm@ markus@ + - markus@cvs.openbsd.org 2014/01/25 20:35:37 + [kex.c] + dh_need needs to be set to max(seclen, blocksize, ivlen, mac_len) + ok dtucker@, noted by mancha + diff -up openssh-6.4p1/cipher.c.3des-dh-size openssh-6.4p1/cipher.c --- openssh-6.4p1/cipher.c.3des-dh-size 2014-01-28 14:15:25.101359008 +0100 +++ openssh-6.4p1/cipher.c 2014-01-28 14:17:48.119630792 +0100 @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.89 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: cipher.c,v 1.94 2014/01/25 10:12:50 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -144,6 +144,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); diff -up openssh-6.4p1/cipher.h.3des-dh-size openssh-6.4p1/cipher.h --- openssh-6.4p1/cipher.h.3des-dh-size 2014-01-28 14:15:25.178358616 +0100 +++ openssh-6.4p1/cipher.h 2014-01-28 14:17:17.858784879 +0100 @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.h,v 1.40 2013/04/19 01:06:50 djm Exp $ */ +/* $OpenBSD: cipher.h,v 1.44 2014/01/25 10:12:50 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -95,6 +95,7 @@ void cipher_cleanup(CipherContext *); int 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 *); diff -up openssh-6.4p1/kex.c.3des-dh-size openssh-6.4p1/kex.c --- openssh-6.4p1/kex.c.3des-dh-size 2014-01-28 14:15:25.165358682 +0100 +++ openssh-6.4p1/kex.c 2014-01-28 14:19:22.038152586 +0100 @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.91 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.97 2014/01/25 20:35:37 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -494,7 +494,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); @@ -545,20 +545,21 @@ 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) - need = newkeys->enc.key_len; - if (need < newkeys->enc.block_size) - need = newkeys->enc.block_size; - if (need < newkeys->enc.iv_len) - need = newkeys->enc.iv_len; - if (need < newkeys->mac.key_len) - need = newkeys->mac.key_len; + need = MAX(need, newkeys->enc.key_len); + need = MAX(need, newkeys->enc.block_size); + need = MAX(need, newkeys->enc.iv_len); + need = MAX(need, newkeys->mac.key_len); + dh_need = MAX(dh_need, cipher_seclen(newkeys->enc.cipher)); + dh_need = MAX(dh_need, newkeys->enc.block_size); + dh_need = MAX(dh_need, newkeys->enc.iv_len); + dh_need = MAX(dh_need, newkeys->mac.key_len); } /* 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) && diff -up openssh-6.4p1/kexgexc.c.3des-dh-size openssh-6.4p1/kexgexc.c --- openssh-6.4p1/kexgexc.c.3des-dh-size 2014-01-28 14:15:25.165358682 +0100 +++ openssh-6.4p1/kexgexc.c 2014-01-28 14:19:09.718215323 +0100 @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.16 2014/01/25 10:12:50 dtucker Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -60,7 +60,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 */ diff -up openssh-6.4p1/kex.h.3des-dh-size openssh-6.4p1/kex.h --- openssh-6.4p1/kex.h.3des-dh-size 2014-01-28 14:15:25.142358799 +0100 +++ openssh-6.4p1/kex.h 2014-01-28 14:18:49.431318614 +0100 @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.56 2013/07/19 07:37:48 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.61 2014/01/25 10:12:50 dtucker Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -125,6 +125,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;