debug(("Exchange hash is:\r\n")); for (i = 0; i < 20; i++) debug((" %02x", exchange_hash[i])); debug(("\r\n"));
debug(("Exchange hash is:\n")); dmemdump(exchange_hash, 20);
static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt){    static int i, j, len, nbits, pbits;    static char *str;    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 ssh2_cipher *cscipher_tobe = NULL;    static const struct ssh2_cipher *sccipher_tobe = NULL;    static const struct ssh_mac *csmac_tobe = NULL;    static const struct ssh_mac *scmac_tobe = NULL;    static const struct ssh_compress *cscomp_tobe = NULL;    static const struct ssh_compress *sccomp_tobe = NULL;    static char *hostkeydata, *sigdata, *keystr, *fingerprint;    static int hostkeylen, siglen;    static void *hkey;		       /* actual host key */    static unsigned char exchange_hash[20];    static unsigned char keyspace[40];    static const struct ssh2_ciphers *preferred_cipher;    static const struct ssh_compress *preferred_comp;    static int first_kex;    crBegin;    random_init();    first_kex = 1;    /*     * Set up the preferred cipher and compression.     */    if (cfg.cipher == CIPHER_BLOWFISH) {        preferred_cipher = &ssh2_blowfish;    } else if (cfg.cipher == CIPHER_DES) {        logevent("Single DES not supported in SSH2; using 3DES");        preferred_cipher = &ssh2_3des;    } else if (cfg.cipher == CIPHER_3DES) {        preferred_cipher = &ssh2_3des;    } else if (cfg.cipher == CIPHER_AES) {        preferred_cipher = &ssh2_aes;    } else {        /* Shouldn't happen, but we do want to initialise to _something_. */        preferred_cipher = &ssh2_3des;    }    if (cfg.compression)	preferred_comp = &ssh_zlib;    else	preferred_comp = &ssh_comp_none;    /*     * Be prepared to work around the buggy MAC problem.     */    if (cfg.buggymac || (ssh_remote_bugs & BUG_SSH2_HMAC))        maclist = buggymacs, nmacs = lenof(buggymacs);    else        maclist = macs, nmacs = lenof(macs);    begin_key_exchange:    /*     * Construct and send our key exchange packet.     */    ssh2_pkt_init(SSH2_MSG_KEXINIT);    for (i = 0; i < 16; i++)        ssh2_pkt_addbyte((unsigned char)random_byte());    /* List key exchange algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(kex_algs); i++) {        ssh2_pkt_addstring_str(kex_algs[i]->name);        if (i < lenof(kex_algs)-1)            ssh2_pkt_addstring_str(",");    }    /* List server host key algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(hostkey_algs); i++) {        ssh2_pkt_addstring_str(hostkey_algs[i]->name);        if (i < lenof(hostkey_algs)-1)            ssh2_pkt_addstring_str(",");    }    /* List client->server encryption algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(ciphers)+1; i++) {        const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];        for (j = 0; j < c->nciphers; j++) {            ssh2_pkt_addstring_str(c->list[j]->name);            if (i < lenof(ciphers) || j < c->nciphers-1)                ssh2_pkt_addstring_str(",");        }    }    /* List server->client encryption algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(ciphers)+1; i++) {        const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];        for (j = 0; j < c->nciphers; j++) {            ssh2_pkt_addstring_str(c->list[j]->name);            if (i < lenof(ciphers) || j < c->nciphers-1)                ssh2_pkt_addstring_str(",");        }    }    /* List client->server MAC algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < nmacs; i++) {        ssh2_pkt_addstring_str(maclist[i]->name);        if (i < nmacs-1)            ssh2_pkt_addstring_str(",");    }    /* List server->client MAC algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < nmacs; i++) {        ssh2_pkt_addstring_str(maclist[i]->name);        if (i < nmacs-1)            ssh2_pkt_addstring_str(",");    }    /* List client->server compression algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(compressions)+1; i++) {        const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];        ssh2_pkt_addstring_str(c->name);        if (i < lenof(compressions))            ssh2_pkt_addstring_str(",");    }    /* List server->client compression algorithms. */    ssh2_pkt_addstring_start();    for (i = 0; i < lenof(compressions)+1; i++) {        const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];        ssh2_pkt_addstring_str(c->name);        if (i < lenof(compressions))            ssh2_pkt_addstring_str(",");    }    /* List client->server languages. Empty list. */    ssh2_pkt_addstring_start();    /* List server->client languages. Empty list. */    ssh2_pkt_addstring_start();    /* First KEX packet does _not_ follow, because we're not that brave. */    ssh2_pkt_addbool(FALSE);    /* Reserved. */    ssh2_pkt_adduint32(0);    exhash = exhashbase;    sha_string(&exhash, pktout.data+5, pktout.length-5);    ssh2_pkt_send();    if (!ispkt) crWaitUntil(ispkt);    sha_string(&exhash, pktin.data+5, pktin.length-5);    /*     * Now examine the other side's KEXINIT to see what we're up     * to.     */    if (pktin.type != SSH2_MSG_KEXINIT) {        bombout(("expected key exchange packet from server"));        crReturn(0);    }    kex = NULL; hostkey = NULL; cscipher_tobe = NULL; sccipher_tobe = NULL;    csmac_tobe = NULL; scmac_tobe = NULL; cscomp_tobe = NULL; sccomp_tobe = NULL;    pktin.savedpos += 16;              /* skip garbage cookie */    ssh2_pkt_getstring(&str, &len);    /* key exchange algorithms */    for (i = 0; i < lenof(kex_algs); i++) {        if (in_commasep_string(kex_algs[i]->name, str, len)) {            kex = kex_algs[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* host key algorithms */    for (i = 0; i < lenof(hostkey_algs); i++) {        if (in_commasep_string(hostkey_algs[i]->name, str, len)) {            hostkey = hostkey_algs[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* client->server cipher */    for (i = 0; i < lenof(ciphers)+1; i++) {        const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];        for (j = 0; j < c->nciphers; j++) {            if (in_commasep_string(c->list[j]->name, str, len)) {                cscipher_tobe = c->list[j];                break;            }        }        if (cscipher_tobe)            break;    }    ssh2_pkt_getstring(&str, &len);    /* server->client cipher */    for (i = 0; i < lenof(ciphers)+1; i++) {        const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];        for (j = 0; j < c->nciphers; j++) {            if (in_commasep_string(c->list[j]->name, str, len)) {                sccipher_tobe = c->list[j];                break;            }        }        if (sccipher_tobe)            break;    }    ssh2_pkt_getstring(&str, &len);    /* client->server mac */    for (i = 0; i < nmacs; i++) {        if (in_commasep_string(maclist[i]->name, str, len)) {            csmac_tobe = maclist[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* server->client mac */    for (i = 0; i < nmacs; i++) {        if (in_commasep_string(maclist[i]->name, str, len)) {            scmac_tobe = maclist[i];            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* client->server compression */    for (i = 0; i < lenof(compressions)+1; i++) {        const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];        if (in_commasep_string(c->name, str, len)) {            cscomp_tobe = c;            break;        }    }    ssh2_pkt_getstring(&str, &len);    /* server->client compression */    for (i = 0; i < lenof(compressions)+1; i++) {        const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];        if (in_commasep_string(c->name, str, len)) {            sccomp_tobe = c;            break;        }    }    /*     * Work out the number of bits of key we will need from the key     * exchange. We start with the maximum key length of either     * cipher...     */    {        int csbits, scbits;	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;    /*     * If we're doing Diffie-Hellman group exchange, start by     * requesting a group.     */    if (kex == &ssh_diffiehellman_gex) {        logevent("Doing Diffie-Hellman group exchange");        /*         * Work out how big a DH group we will need to allow that         * much data.	 */        pbits = 512 << ((nbits-1) / 64);        ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);        ssh2_pkt_adduint32(pbits);        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 generate and send e for Diffie-Hellman.     */    e = dh_create_e(nbits*2);    ssh2_pkt_init(kex_init_value);    ssh2_pkt_addmp(e);    ssh2_pkt_send();    crWaitUntil(ispkt);    if (pktin.type != kex_reply_value) {        bombout(("expected key exchange reply packet from server"));        crReturn(0);    }    ssh2_pkt_getstring(&hostkeydata, &hostkeylen);    f = ssh2_pkt_getmp();    ssh2_pkt_getstring(&sigdata, &siglen);    K = dh_find_K(f);    sha_string(&exhash, hostkeydata, hostkeylen);    if (kex == &ssh_diffiehellman_gex) {        sha_uint32(&exhash, pbits);        sha_mpint(&exhash, p);        sha_mpint(&exhash, g);    }    sha_mpint(&exhash, e);    sha_mpint(&exhash, f);    sha_mpint(&exhash, K);    SHA_Final(&exhash, exchange_hash);    dh_cleanup();#if 0    debug(("Exchange hash is:\r\n"));    for (i = 0; i < 20; i++)        debug((" %02x", exchange_hash[i]));    debug(("\r\n"));#endif    hkey = hostkey->newkey(hostkeydata, hostkeylen);    if (!hostkey->verifysig(hkey, sigdata, siglen, exchange_hash, 20)) {        bombout(("Server failed host key check"));        crReturn(0);    }    /*     * Expect SSH2_MSG_NEWKEYS from server.     */    crWaitUntil(ispkt);    if (pktin.type != SSH2_MSG_NEWKEYS) {        bombout(("expected new-keys packet from server"));        crReturn(0);    }    /*     * Authenticate remote host: verify host key. (We've already     * checked the signature of the exchange hash.)     */    keystr = hostkey->fmtkey(hkey);    fingerprint = hostkey->fingerprint(hkey);    verify_ssh_host_key(savedhost, savedport, hostkey->keytype,                        keystr, fingerprint);    if (first_kex) {                /* don't bother logging this in rekeys */	logevent("Host key fingerprint is:");	logevent(fingerprint);    }    sfree(fingerprint);    sfree(keystr);    hostkey->freekey(hkey);    /*     * Send SSH2_MSG_NEWKEYS.     */    ssh2_pkt_init(SSH2_MSG_NEWKEYS);    ssh2_pkt_send();    /*     * Create and initialise session keys.     */    cscipher = cscipher_tobe;    sccipher = sccipher_tobe;    csmac = csmac_tobe;    scmac = scmac_tobe;    cscomp = cscomp_tobe;    sccomp = sccomp_tobe;    cscomp->compress_init();    sccomp->decompress_init();    /*     * Set IVs after keys. Here we use the exchange hash from the     * _first_ key exchange.     */    if (first_kex)	memcpy(ssh2_session_id, exchange_hash, sizeof(exchange_hash));    ssh2_mkkey(K, exchange_hash, ssh2_session_id, 'C', keyspace);    cscipher->setcskey(keyspace);    ssh2_mkkey(K, exchange_hash, ssh2_session_id, 'D', keyspace);    sccipher->setsckey(keyspace);    ssh2_mkkey(K, exchange_hash, ssh2_session_id, 'A', keyspace);    cscipher->setcsiv(keyspace);    ssh2_mkkey(K, exchange_hash, ssh2_session_id, 'B', keyspace);    sccipher->setsciv(keyspace);    ssh2_mkkey(K, exchange_hash, ssh2_session_id, 'E', keyspace);    csmac->setcskey(keyspace);    ssh2_mkkey(K, exchange_hash, ssh2_session_id, 'F', keyspace);    scmac->setsckey(keyspace);    /*     * If this is the first key exchange phase, we must pass the     * SSH2_MSG_NEWKEYS packet to the next layer, not because it     * wants to see it but because it will need time to initialise     * itself before it sees an actual packet. In subsequent key     * exchange phases, we don't pass SSH2_MSG_NEWKEYS on, because     * it would only confuse the layer above.     */    if (!first_kex) {        crReturn(0);    }    first_kex = 0;    /*     * Now we're encrypting. Begin returning 1 to the protocol main     * function so that other things can run on top of the     * transport. If we ever see a KEXINIT, we must go back to the     * start.     */    while (!(ispkt && pktin.type == SSH2_MSG_KEXINIT)) {        crReturn(1);    }    logevent("Server initiated key re-exchange");    goto begin_key_exchange;    crFinish(1);}