Diffie-Hellman group exchange in SSH2. Currently #ifdeffed out

(change the sense of #ifdef DO_DIFFIE_HELLMAN_GEX in ssh.c) because
it's _far_ too slow. Will be re-enabled once the bignum routines
work a bit faster (or rather a _lot_ faster).

[originally from svn r962]
This commit is contained in:
Simon Tatham 2001-03-01 17:55:40 +00:00
Родитель 862d6a496d
Коммит cc9d7ba87e
3 изменённых файлов: 85 добавлений и 17 удалений

88
ssh.c
Просмотреть файл

@ -87,6 +87,10 @@
#define SSH2_MSG_NEWKEYS 21 /* 0x15 */
#define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */
#define SSH2_MSG_KEXDH_REPLY 31 /* 0x1f */
#define SSH2_MSG_KEX_DH_GEX_REQUEST 30 /* 0x1e */
#define SSH2_MSG_KEX_DH_GEX_GROUP 31 /* 0x1f */
#define SSH2_MSG_KEX_DH_GEX_INIT 32 /* 0x20 */
#define SSH2_MSG_KEX_DH_GEX_REPLY 33 /* 0x21 */
#define SSH2_MSG_USERAUTH_REQUEST 50 /* 0x32 */
#define SSH2_MSG_USERAUTH_FAILURE 51 /* 0x33 */
#define SSH2_MSG_USERAUTH_SUCCESS 52 /* 0x34 */
@ -180,7 +184,12 @@ extern void x11_invent_auth(char *, int, char *, int);
const static struct ssh_cipher *ciphers[] = { &ssh_blowfish_ssh2, &ssh_3des_ssh2 };
extern const struct ssh_kex ssh_diffiehellman;
const static struct ssh_kex *kex_algs[] = { &ssh_diffiehellman };
extern const struct ssh_kex ssh_diffiehellman_gex;
const static struct ssh_kex *kex_algs[] = {
#ifdef DO_DIFFIE_HELLMAN_GEX
&ssh_diffiehellman_gex,
#endif
&ssh_diffiehellman };
extern const struct ssh_signkey ssh_dss;
const static struct ssh_signkey *hostkey_algs[] = { &ssh_dss };
@ -806,8 +815,8 @@ static int ssh_versioncmp(char *a, char *b) {
/*
* Utility routine for putting an SSH-protocol `string' into a SHA
* state.
* Utility routines for putting an SSH-protocol `string' and
* `uint32' into a SHA state.
*/
#include <stdio.h>
static void sha_string(SHA_State *s, void *str, int len) {
@ -817,6 +826,12 @@ static void sha_string(SHA_State *s, void *str, int len) {
SHA_Bytes(s, str, len);
}
static void sha_uint32(SHA_State *s, unsigned i) {
unsigned char intblk[4];
PUT_32BIT(intblk, i);
SHA_Bytes(s, intblk, 4);
}
/*
* SSH2 packet construction functions.
*/
@ -2157,9 +2172,10 @@ static void ssh2_mkkey(Bignum K, char *H, char *sessid, char chr, char *keyspace
*/
static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
{
static int i, len;
static int i, len, nbits;
static char *str;
static Bignum e, f, K;
static Bignum p, g, e, f, K;
static int kex_init_value, kex_reply_value;
static const struct ssh_mac **maclist;
static int nmacs;
static const struct ssh_cipher *cscipher_tobe = NULL;
@ -2366,27 +2382,60 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
}
/*
* Currently we only support Diffie-Hellman and DSS, so let's
* bomb out if those aren't selected.
* If we're doing Diffie-Hellman group exchange, start by
* requesting a group.
*/
if (kex != &ssh_diffiehellman || hostkey != &ssh_dss) {
bombout(("internal fault: chaos in SSH 2 transport layer"));
crReturn(0);
if (kex == &ssh_diffiehellman_gex) {
int csbits, scbits;
logevent("Doing Diffie-Hellman group exchange");
/*
* Work out number of bits. We start with the maximum key
* length of either cipher...
*/
csbits = cscipher_tobe->keylen;
scbits = sccipher_tobe->keylen;
nbits = (csbits > scbits ? csbits : scbits);
/* The keys only have 160-bit entropy, since they're based on
* a SHA-1 hash. So cap the key size at 160 bits. */
if (nbits > 160) nbits = 160;
/*
* ... and then work out how big a DH group we will need to
* allow that much data.
*/
nbits = 512 << ((nbits-1) / 64);
ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);
ssh2_pkt_adduint32(nbits);
ssh2_pkt_send();
crWaitUntil(ispkt);
if (pktin.type != SSH2_MSG_KEX_DH_GEX_GROUP) {
bombout(("expected key exchange group packet from server"));
crReturn(0);
}
p = ssh2_pkt_getmp();
g = ssh2_pkt_getmp();
dh_setup_group(p, g);
kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY;
} else {
dh_setup_group1();
kex_init_value = SSH2_MSG_KEXDH_INIT;
kex_reply_value = SSH2_MSG_KEXDH_REPLY;
}
logevent("Doing Diffie-Hellman key exchange");
/*
* Now we begin the fun. Generate and send e for Diffie-Hellman.
* Now generate and send e for Diffie-Hellman.
*/
dh_setup_group1();
e = dh_create_e();
ssh2_pkt_init(SSH2_MSG_KEXDH_INIT);
ssh2_pkt_init(kex_init_value);
ssh2_pkt_addmp(e);
ssh2_pkt_send();
crWaitUntil(ispkt);
if (pktin.type != SSH2_MSG_KEXDH_REPLY) {
bombout(("expected key exchange packet from server"));
if (pktin.type != kex_reply_value) {
bombout(("expected key exchange reply packet from server"));
crReturn(0);
}
ssh2_pkt_getstring(&hostkeydata, &hostkeylen);
@ -2396,6 +2445,11 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
K = dh_find_K(f);
sha_string(&exhash, hostkeydata, hostkeylen);
if (kex == &ssh_diffiehellman_gex) {
sha_uint32(&exhash, nbits);
sha_mpint(&exhash, p);
sha_mpint(&exhash, g);
}
sha_mpint(&exhash, e);
sha_mpint(&exhash, f);
sha_mpint(&exhash, K);
@ -2433,7 +2487,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
fingerprint = hostkey->fingerprint(hkey);
verify_ssh_host_key(savedhost, savedport, hostkey->keytype,
keystr, fingerprint);
if (first_kex) { /* don't bother logging this in rekeys */
if (first_kex) { /* don't bother logging this in rekeys */
logevent("Host key fingerprint is:");
logevent(fingerprint);
}

1
ssh.h
Просмотреть файл

@ -187,6 +187,7 @@ int bignum_cmp(Bignum a, Bignum b);
char *bignum_decimal(Bignum x);
void dh_setup_group1(void);
void dh_setup_group(Bignum pval, Bignum gval);
void dh_cleanup(void);
Bignum dh_create_e(void);
Bignum dh_find_K(Bignum f);

13
sshdh.c
Просмотреть файл

@ -4,6 +4,10 @@ struct ssh_kex ssh_diffiehellman = {
"diffie-hellman-group1-sha1"
};
struct ssh_kex ssh_diffiehellman_gex = {
"diffie-hellman-group-exchange-sha1"
};
/*
* The prime p used in the key exchange.
*/
@ -49,6 +53,15 @@ void dh_setup_group1(void) {
dh_init();
}
/*
* Initialise DH for an alternative group.
*/
void dh_setup_group(Bignum pval, Bignum gval) {
p = copybn(pval);
g = copybn(gval);
dh_init();
}
/*
* Clean up.
*/