1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

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
parent 862d6a496d
commit cc9d7ba87e
3 changed files with 85 additions and 17 deletions

88
ssh.c
View File

@ -87,6 +87,10 @@
#define SSH2_MSG_NEWKEYS 21 /* 0x15 */ #define SSH2_MSG_NEWKEYS 21 /* 0x15 */
#define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */ #define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */
#define SSH2_MSG_KEXDH_REPLY 31 /* 0x1f */ #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_REQUEST 50 /* 0x32 */
#define SSH2_MSG_USERAUTH_FAILURE 51 /* 0x33 */ #define SSH2_MSG_USERAUTH_FAILURE 51 /* 0x33 */
#define SSH2_MSG_USERAUTH_SUCCESS 52 /* 0x34 */ #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 }; const static struct ssh_cipher *ciphers[] = { &ssh_blowfish_ssh2, &ssh_3des_ssh2 };
extern const struct ssh_kex ssh_diffiehellman; 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; extern const struct ssh_signkey ssh_dss;
const static struct ssh_signkey *hostkey_algs[] = { &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 * Utility routines for putting an SSH-protocol `string' and
* state. * `uint32' into a SHA state.
*/ */
#include <stdio.h> #include <stdio.h>
static void sha_string(SHA_State *s, void *str, int len) { 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); 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. * 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 do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
{ {
static int i, len; static int i, len, nbits;
static char *str; 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 const struct ssh_mac **maclist;
static int nmacs; static int nmacs;
static const struct ssh_cipher *cscipher_tobe = NULL; 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 * If we're doing Diffie-Hellman group exchange, start by
* bomb out if those aren't selected. * requesting a group.
*/ */
if (kex != &ssh_diffiehellman || hostkey != &ssh_dss) { if (kex == &ssh_diffiehellman_gex) {
bombout(("internal fault: chaos in SSH 2 transport layer")); int csbits, scbits;
crReturn(0);
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(); e = dh_create_e();
ssh2_pkt_init(SSH2_MSG_KEXDH_INIT); ssh2_pkt_init(kex_init_value);
ssh2_pkt_addmp(e); ssh2_pkt_addmp(e);
ssh2_pkt_send(); ssh2_pkt_send();
crWaitUntil(ispkt); crWaitUntil(ispkt);
if (pktin.type != SSH2_MSG_KEXDH_REPLY) { if (pktin.type != kex_reply_value) {
bombout(("expected key exchange packet from server")); bombout(("expected key exchange reply packet from server"));
crReturn(0); crReturn(0);
} }
ssh2_pkt_getstring(&hostkeydata, &hostkeylen); 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); K = dh_find_K(f);
sha_string(&exhash, hostkeydata, hostkeylen); 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, e);
sha_mpint(&exhash, f); sha_mpint(&exhash, f);
sha_mpint(&exhash, K); sha_mpint(&exhash, K);
@ -2433,7 +2487,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
fingerprint = hostkey->fingerprint(hkey); fingerprint = hostkey->fingerprint(hkey);
verify_ssh_host_key(savedhost, savedport, hostkey->keytype, verify_ssh_host_key(savedhost, savedport, hostkey->keytype,
keystr, fingerprint); 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("Host key fingerprint is:");
logevent(fingerprint); logevent(fingerprint);
} }

1
ssh.h
View File

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

13
sshdh.c
View File

@ -4,6 +4,10 @@ struct ssh_kex ssh_diffiehellman = {
"diffie-hellman-group1-sha1" "diffie-hellman-group1-sha1"
}; };
struct ssh_kex ssh_diffiehellman_gex = {
"diffie-hellman-group-exchange-sha1"
};
/* /*
* The prime p used in the key exchange. * The prime p used in the key exchange.
*/ */
@ -49,6 +53,15 @@ void dh_setup_group1(void) {
dh_init(); 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. * Clean up.
*/ */