Diffie-Hellman key exchange now uses a dynamically allocated context.
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index 9689fd2..c936060 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -560,6 +560,7 @@ struct ssh_tag {
     int remote_bugs;
     const struct ssh_cipher *cipher;
     void *v1_cipher_ctx;
+    void *crcda_ctx;
     const struct ssh2_cipher *cscipher, *sccipher;
     void *cs_cipher_ctx, *sc_cipher_ctx;
     const struct ssh_mac *csmac, *scmac;
@@ -568,6 +569,7 @@ struct ssh_tag {
     const struct ssh_kex *kex;
     const struct ssh_signkey *hostkey;
     unsigned char v2_session_id[20];
+    void *kex_ctx;
 
     char *savedhost;
     int savedport;
@@ -809,7 +811,8 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
        st->to_read -= st->chunk;
     }
 
-    if (ssh->cipher && detect_attack(ssh->pktin.data, st->biglen, NULL)) {
+    if (ssh->cipher && detect_attack(ssh->crcda_ctx, ssh->pktin.data,
+                                    st->biglen, NULL)) {
         bombout(("Network attack (CRC compensation) detected!"));
         crReturn(0);
     }
@@ -2377,6 +2380,9 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        logevent(buf);
     }
 
+    ssh->crcda_ctx = crcda_make_context();
+    logevent("Installing CRC compensation attack detector");
+
     crWaitUntil(ispkt);
 
     if (ssh->pktin.type != SSH1_SMSG_SUCCESS) {
@@ -3948,12 +3954,12 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        }
        s->p = ssh2_pkt_getmp(ssh);
        s->g = ssh2_pkt_getmp(ssh);
-       dh_setup_group(s->p, s->g);
+       ssh->kex_ctx = dh_setup_group(s->p, s->g);
        s->kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
        s->kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY;
     } else {
        ssh->pkt_ctx |= SSH2_PKTCTX_DHGROUP1;
-       dh_setup_group1();
+       ssh->kex_ctx = dh_setup_group1();
        s->kex_init_value = SSH2_MSG_KEXDH_INIT;
        s->kex_reply_value = SSH2_MSG_KEXDH_REPLY;
     }
@@ -3962,7 +3968,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     /*
      * Now generate and send e for Diffie-Hellman.
      */
-    s->e = dh_create_e(s->nbits * 2);
+    s->e = dh_create_e(ssh->kex_ctx, s->nbits * 2);
     ssh2_pkt_init(ssh, s->kex_init_value);
     ssh2_pkt_addmp(ssh, s->e);
     ssh2_pkt_send(ssh);
@@ -3976,7 +3982,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     s->f = ssh2_pkt_getmp(ssh);
     ssh2_pkt_getstring(ssh, &s->sigdata, &s->siglen);
 
-    s->K = dh_find_K(s->f);
+    s->K = dh_find_K(ssh->kex_ctx, s->f);
 
     sha_string(&ssh->exhash, s->hostkeydata, s->hostkeylen);
     if (ssh->kex == &ssh_diffiehellman_gex) {
@@ -3989,7 +3995,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     sha_mpint(&ssh->exhash, s->K);
     SHA_Final(&ssh->exhash, s->exchange_hash);
 
-    dh_cleanup();
+    dh_cleanup(ssh->kex_ctx);
 
 #if 0
     debug(("Exchange hash is:\n"));
@@ -5801,6 +5807,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
     ssh->s = NULL;
     ssh->cipher = NULL;
     ssh->v1_cipher_ctx = NULL;
+    ssh->crcda_ctx = NULL;
     ssh->cscipher = NULL;
     ssh->cs_cipher_ctx = NULL;
     ssh->sccipher = NULL;