sk_set_frozen(ssh->s, 0);
static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,			     struct Packet *pktin){    struct do_ssh2_transport_state {	int nbits, pbits, warn;	Bignum p, g, e, f, K;	int kex_init_value, kex_reply_value;	const struct ssh_mac **maclist;	int nmacs;	const struct ssh2_cipher *cscipher_tobe;	const struct ssh2_cipher *sccipher_tobe;	const struct ssh_mac *csmac_tobe;	const struct ssh_mac *scmac_tobe;	const struct ssh_compress *cscomp_tobe;	const struct ssh_compress *sccomp_tobe;	char *hostkeydata, *sigdata, *keystr, *fingerprint;	int hostkeylen, siglen;	void *hkey;		       /* actual host key */	unsigned char exchange_hash[20];	int n_preferred_kex;	const struct ssh_kex *preferred_kex[KEX_MAX];	int n_preferred_ciphers;	const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX];	const struct ssh_compress *preferred_comp;	int got_session_id, activated_authconn;	struct Packet *pktout;    };    crState(do_ssh2_transport_state);    crBegin(ssh->do_ssh2_transport_crstate);    s->cscipher_tobe = s->sccipher_tobe = NULL;    s->csmac_tobe = s->scmac_tobe = NULL;    s->cscomp_tobe = s->sccomp_tobe = NULL;    s->got_session_id = s->activated_authconn = FALSE;    /*     * Be prepared to work around the buggy MAC problem.     */    if (ssh->remote_bugs & BUG_SSH2_HMAC)	s->maclist = buggymacs, s->nmacs = lenof(buggymacs);    else	s->maclist = macs, s->nmacs = lenof(macs);  begin_key_exchange:    {	int i, j, commalist_started;	/*	 * Set up the preferred key exchange. (NULL => warn below here)	 */	s->n_preferred_kex = 0;	for (i = 0; i < KEX_MAX; i++) {	    switch (ssh->cfg.ssh_kexlist[i]) {	      case KEX_DHGEX:		s->preferred_kex[s->n_preferred_kex++] =		    &ssh_diffiehellman_gex;		break;	      case KEX_DHGROUP14:		s->preferred_kex[s->n_preferred_kex++] =		    &ssh_diffiehellman_group14;		break;	      case KEX_DHGROUP1:		s->preferred_kex[s->n_preferred_kex++] =		    &ssh_diffiehellman_group1;		break;	      case CIPHER_WARN:		/* Flag for later. Don't bother if it's the last in		 * the list. */		if (i < KEX_MAX - 1) {		    s->preferred_kex[s->n_preferred_kex++] = NULL;		}		break;	    }	}	/*	 * Set up the preferred ciphers. (NULL => warn below here)	 */	s->n_preferred_ciphers = 0;	for (i = 0; i < CIPHER_MAX; i++) {	    switch (ssh->cfg.ssh_cipherlist[i]) {	      case CIPHER_BLOWFISH:		s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_blowfish;		break;	      case CIPHER_DES:		if (ssh->cfg.ssh2_des_cbc) {		    s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_des;		}		break;	      case CIPHER_3DES:		s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_3des;		break;	      case CIPHER_AES:		s->preferred_ciphers[s->n_preferred_ciphers++] = &ssh2_aes;		break;	      case CIPHER_WARN:		/* Flag for later. Don't bother if it's the last in		 * the list. */		if (i < CIPHER_MAX - 1) {		    s->preferred_ciphers[s->n_preferred_ciphers++] = NULL;		}		break;	    }	}	/*	 * Set up preferred compression.	 */	if (ssh->cfg.compression)	    s->preferred_comp = &ssh_zlib;	else	    s->preferred_comp = &ssh_comp_none;	/*	 * Enable queueing of outgoing auth- or connection-layer	 * packets while we are in the middle of a key exchange.	 */	ssh->queueing = TRUE;	/*	 * Flag that KEX is in progress.	 */	ssh->kex_in_progress = TRUE;	/*	 * Construct and send our key exchange packet.	 */	s->pktout = ssh2_pkt_init(SSH2_MSG_KEXINIT);	for (i = 0; i < 16; i++)	    ssh2_pkt_addbyte(s->pktout, (unsigned char) random_byte());	/* List key exchange algorithms. */	ssh2_pkt_addstring_start(s->pktout);	commalist_started = 0;	for (i = 0; i < s->n_preferred_kex; i++) {	    const struct ssh_kex *k = s->preferred_kex[i];	    if (!k) continue;	       /* warning flag */	    if (commalist_started)		ssh2_pkt_addstring_str(s->pktout, ",");	    ssh2_pkt_addstring_str(s->pktout, s->preferred_kex[i]->name);	    commalist_started = 1;	}	/* List server host key algorithms. */	ssh2_pkt_addstring_start(s->pktout);	for (i = 0; i < lenof(hostkey_algs); i++) {	    ssh2_pkt_addstring_str(s->pktout, hostkey_algs[i]->name);	    if (i < lenof(hostkey_algs) - 1)		ssh2_pkt_addstring_str(s->pktout, ",");	}	/* List client->server encryption algorithms. */	ssh2_pkt_addstring_start(s->pktout);	commalist_started = 0;	for (i = 0; i < s->n_preferred_ciphers; i++) {	    const struct ssh2_ciphers *c = s->preferred_ciphers[i];	    if (!c) continue;	       /* warning flag */	    for (j = 0; j < c->nciphers; j++) {		if (commalist_started)		    ssh2_pkt_addstring_str(s->pktout, ",");		ssh2_pkt_addstring_str(s->pktout, c->list[j]->name);		commalist_started = 1;	    }	}	/* List server->client encryption algorithms. */	ssh2_pkt_addstring_start(s->pktout);	commalist_started = 0;	for (i = 0; i < s->n_preferred_ciphers; i++) {	    const struct ssh2_ciphers *c = s->preferred_ciphers[i];	    if (!c) continue; /* warning flag */	    for (j = 0; j < c->nciphers; j++) {		if (commalist_started)		    ssh2_pkt_addstring_str(s->pktout, ",");		ssh2_pkt_addstring_str(s->pktout, c->list[j]->name);		commalist_started = 1;	    }	}	/* List client->server MAC algorithms. */	ssh2_pkt_addstring_start(s->pktout);	for (i = 0; i < s->nmacs; i++) {	    ssh2_pkt_addstring_str(s->pktout, s->maclist[i]->name);	    if (i < s->nmacs - 1)		ssh2_pkt_addstring_str(s->pktout, ",");	}	/* List server->client MAC algorithms. */	ssh2_pkt_addstring_start(s->pktout);	for (i = 0; i < s->nmacs; i++) {	    ssh2_pkt_addstring_str(s->pktout, s->maclist[i]->name);	    if (i < s->nmacs - 1)		ssh2_pkt_addstring_str(s->pktout, ",");	}	/* List client->server compression algorithms. */	ssh2_pkt_addstring_start(s->pktout);	assert(lenof(compressions) > 1);	ssh2_pkt_addstring_str(s->pktout, s->preferred_comp->name);	for (i = 0; i < lenof(compressions); i++) {	    const struct ssh_compress *c = compressions[i];	    if (c != s->preferred_comp) {		ssh2_pkt_addstring_str(s->pktout, ",");		ssh2_pkt_addstring_str(s->pktout, c->name);	    }	}	/* List server->client compression algorithms. */	ssh2_pkt_addstring_start(s->pktout);	assert(lenof(compressions) > 1);	ssh2_pkt_addstring_str(s->pktout, s->preferred_comp->name);	for (i = 0; i < lenof(compressions); i++) {	    const struct ssh_compress *c = compressions[i];	    if (c != s->preferred_comp) {		ssh2_pkt_addstring_str(s->pktout, ",");		ssh2_pkt_addstring_str(s->pktout, c->name);	    }	}	/* List client->server languages. Empty list. */	ssh2_pkt_addstring_start(s->pktout);	/* List server->client languages. Empty list. */	ssh2_pkt_addstring_start(s->pktout);	/* First KEX packet does _not_ follow, because we're not that brave. */	ssh2_pkt_addbool(s->pktout, FALSE);	/* Reserved. */	ssh2_pkt_adduint32(s->pktout, 0);    }    ssh->exhash = ssh->exhashbase;    sha_string(&ssh->exhash, s->pktout->data + 5, s->pktout->length - 5);    ssh2_pkt_send_noqueue(ssh, s->pktout);    if (!pktin)	crWaitUntil(pktin);    if (pktin->length > 5)	sha_string(&ssh->exhash, pktin->data + 5, pktin->length - 5);    /*     * Now examine the other side's KEXINIT to see what we're up     * to.     */    {	char *str;	int i, j, len;	if (pktin->type != SSH2_MSG_KEXINIT) {	    bombout(("expected key exchange packet from server"));	    crStop(0);	}	ssh->kex = NULL;	ssh->hostkey = NULL;	s->cscipher_tobe = NULL;	s->sccipher_tobe = NULL;	s->csmac_tobe = NULL;	s->scmac_tobe = NULL;	s->cscomp_tobe = NULL;	s->sccomp_tobe = NULL;	pktin->savedpos += 16;	        /* skip garbage cookie */	ssh_pkt_getstring(pktin, &str, &len);    /* key exchange algorithms */	s->warn = 0;	for (i = 0; i < s->n_preferred_kex; i++) {	    const struct ssh_kex *k = s->preferred_kex[i];	    if (!k) {		s->warn = 1;	    } else if (in_commasep_string(k->name, str, len)) {		ssh->kex = k;	    }	    if (ssh->kex) {		if (s->warn)		    askalg(ssh->frontend, "key-exchange algorithm",			   ssh->kex->name);		break;	    }	}	if (!ssh->kex) {	    bombout(("Couldn't agree a key exchange algorithm (available: %s)",		     str ? str : "(null)"));	    crStop(0);	}	ssh_pkt_getstring(pktin, &str, &len);    /* host key algorithms */	for (i = 0; i < lenof(hostkey_algs); i++) {	    if (in_commasep_string(hostkey_algs[i]->name, str, len)) {		ssh->hostkey = hostkey_algs[i];		break;	    }	}	ssh_pkt_getstring(pktin, &str, &len);    /* client->server cipher */	s->warn = 0;	for (i = 0; i < s->n_preferred_ciphers; i++) {	    const struct ssh2_ciphers *c = s->preferred_ciphers[i];	    if (!c) {		s->warn = 1;	    } else {		for (j = 0; j < c->nciphers; j++) {		    if (in_commasep_string(c->list[j]->name, str, len)) {			s->cscipher_tobe = c->list[j];			break;		    }		}	    }	    if (s->cscipher_tobe) {		if (s->warn)		    askalg(ssh->frontend, "client-to-server cipher",			   s->cscipher_tobe->name);		break;	    }	}	if (!s->cscipher_tobe) {	    bombout(("Couldn't agree a client-to-server cipher (available: %s)",		     str ? str : "(null)"));	    crStop(0);	}	ssh_pkt_getstring(pktin, &str, &len);    /* server->client cipher */	s->warn = 0;	for (i = 0; i < s->n_preferred_ciphers; i++) {	    const struct ssh2_ciphers *c = s->preferred_ciphers[i];	    if (!c) {		s->warn = 1;	    } else {		for (j = 0; j < c->nciphers; j++) {		    if (in_commasep_string(c->list[j]->name, str, len)) {			s->sccipher_tobe = c->list[j];			break;		    }		}	    }	    if (s->sccipher_tobe) {		if (s->warn)		    askalg(ssh->frontend, "server-to-client cipher",			   s->sccipher_tobe->name);		break;	    }	}	if (!s->sccipher_tobe) {	    bombout(("Couldn't agree a server-to-client cipher (available: %s)",		     str ? str : "(null)"));	    crStop(0);	}	ssh_pkt_getstring(pktin, &str, &len);    /* client->server mac */	for (i = 0; i < s->nmacs; i++) {	    if (in_commasep_string(s->maclist[i]->name, str, len)) {		s->csmac_tobe = s->maclist[i];		break;	    }	}	ssh_pkt_getstring(pktin, &str, &len);    /* server->client mac */	for (i = 0; i < s->nmacs; i++) {	    if (in_commasep_string(s->maclist[i]->name, str, len)) {		s->scmac_tobe = s->maclist[i];		break;	    }	}	ssh_pkt_getstring(pktin, &str, &len);  /* client->server compression */	for (i = 0; i < lenof(compressions) + 1; i++) {	    const struct ssh_compress *c =		i == 0 ? s->preferred_comp : compressions[i - 1];	    if (in_commasep_string(c->name, str, len)) {		s->cscomp_tobe = c;		break;	    }	}	ssh_pkt_getstring(pktin, &str, &len);  /* server->client compression */	for (i = 0; i < lenof(compressions) + 1; i++) {	    const struct ssh_compress *c =		i == 0 ? s->preferred_comp : compressions[i - 1];	    if (in_commasep_string(c->name, str, len)) {		s->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 = s->cscipher_tobe->keylen;	scbits = s->sccipher_tobe->keylen;	s->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 (s->nbits > 160)	s->nbits = 160;    /*     * If we're doing Diffie-Hellman group exchange, start by     * requesting a group.     */    if (!ssh->kex->pdata) {	logevent("Doing Diffie-Hellman group exchange");	ssh->pkt_ctx |= SSH2_PKTCTX_DHGEX;	/*	 * Work out how big a DH group we will need to allow that	 * much data.	 */	s->pbits = 512 << ((s->nbits - 1) / 64);	s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_DH_GEX_REQUEST);	ssh2_pkt_adduint32(s->pktout, s->pbits);	ssh2_pkt_send_noqueue(ssh, s->pktout);	crWaitUntil(pktin);	if (pktin->type != SSH2_MSG_KEX_DH_GEX_GROUP) {	    bombout(("expected key exchange group packet from server"));	    crStop(0);	}	s->p = ssh2_pkt_getmp(pktin);	s->g = ssh2_pkt_getmp(pktin);	if (!s->p || !s->g) {	    bombout(("unable to read mp-ints from incoming group packet"));	    crStop(0);	}	ssh->kex_ctx = dh_setup_gex(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_DHGROUP;	ssh->kex_ctx = dh_setup_group(ssh->kex);	s->kex_init_value = SSH2_MSG_KEXDH_INIT;	s->kex_reply_value = SSH2_MSG_KEXDH_REPLY;	logeventf(ssh, "Using Diffie-Hellman with standard group \"%s\"",		  ssh->kex->groupname);    }    logevent("Doing Diffie-Hellman key exchange");    /*     * Now generate and send e for Diffie-Hellman.     */    s->e = dh_create_e(ssh->kex_ctx, s->nbits * 2);    s->pktout = ssh2_pkt_init(s->kex_init_value);    ssh2_pkt_addmp(s->pktout, s->e);    ssh2_pkt_send_noqueue(ssh, s->pktout);    crWaitUntil(pktin);    if (pktin->type != s->kex_reply_value) {	bombout(("expected key exchange reply packet from server"));	crStop(0);    }    ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);    s->f = ssh2_pkt_getmp(pktin);    if (!s->f) {	bombout(("unable to parse key exchange reply packet"));	crStop(0);    }    ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);    s->K = dh_find_K(ssh->kex_ctx, s->f);    sha_string(&ssh->exhash, s->hostkeydata, s->hostkeylen);    if (ssh->kex == &ssh_diffiehellman_gex) {	sha_uint32(&ssh->exhash, s->pbits);	sha_mpint(&ssh->exhash, s->p);	sha_mpint(&ssh->exhash, s->g);    }    sha_mpint(&ssh->exhash, s->e);    sha_mpint(&ssh->exhash, s->f);    sha_mpint(&ssh->exhash, s->K);    SHA_Final(&ssh->exhash, s->exchange_hash);    dh_cleanup(ssh->kex_ctx);    ssh->kex_ctx = NULL;#if 0    debug(("Exchange hash is:\n"));    dmemdump(s->exchange_hash, 20);#endif    s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen);    if (!s->hkey ||	!ssh->hostkey->verifysig(s->hkey, s->sigdata, s->siglen,				 (char *)s->exchange_hash, 20)) {	bombout(("Server's host key did not match the signature supplied"));	crStop(0);    }    /*     * Authenticate remote host: verify host key. (We've already     * checked the signature of the exchange hash.)     */    s->keystr = ssh->hostkey->fmtkey(s->hkey);    s->fingerprint = ssh->hostkey->fingerprint(s->hkey);    verify_ssh_host_key(ssh->frontend,			ssh->savedhost, ssh->savedport, ssh->hostkey->keytype,			s->keystr, s->fingerprint);    if (!s->got_session_id) {     /* don't bother logging this in rekeys */	logevent("Host key fingerprint is:");	logevent(s->fingerprint);    }    sfree(s->fingerprint);    sfree(s->keystr);    ssh->hostkey->freekey(s->hkey);    /*     * The exchange hash from the very first key exchange is also     * the session id, used in session key construction and     * authentication.     */    if (!s->got_session_id) {	memcpy(ssh->v2_session_id, s->exchange_hash,	       sizeof(s->exchange_hash));	s->got_session_id = TRUE;    }    /*     * Send SSH2_MSG_NEWKEYS.     */    s->pktout = ssh2_pkt_init(SSH2_MSG_NEWKEYS);    ssh2_pkt_send_noqueue(ssh, s->pktout);    ssh->outgoing_data_size = 0;       /* start counting from here */    /*     * We've sent client NEWKEYS, so create and initialise     * client-to-server session keys.     */    if (ssh->cs_cipher_ctx)	ssh->cscipher->free_context(ssh->cs_cipher_ctx);    ssh->cscipher = s->cscipher_tobe;    ssh->cs_cipher_ctx = ssh->cscipher->make_context();    if (ssh->cs_mac_ctx)	ssh->csmac->free_context(ssh->cs_mac_ctx);    ssh->csmac = s->csmac_tobe;    ssh->cs_mac_ctx = ssh->csmac->make_context();    if (ssh->cs_comp_ctx)	ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx);    ssh->cscomp = s->cscomp_tobe;    ssh->cs_comp_ctx = ssh->cscomp->compress_init();    /*     * Set IVs on client-to-server keys. Here we use the exchange     * hash from the _first_ key exchange.     */    {	unsigned char keyspace[40];	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'C',keyspace);	ssh->cscipher->setkey(ssh->cs_cipher_ctx, keyspace);	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'A',keyspace);	ssh->cscipher->setiv(ssh->cs_cipher_ctx, keyspace);	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'E',keyspace);	ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace);    }    logeventf(ssh, "Initialised %.200s client->server encryption",	      ssh->cscipher->text_name);    logeventf(ssh, "Initialised %.200s client->server MAC algorithm",	      ssh->csmac->text_name);    if (ssh->cscomp->text_name)	logeventf(ssh, "Initialised %s compression",		  ssh->cscomp->text_name);    /*     * Now our end of the key exchange is complete, we can send all     * our queued higher-layer packets.     */    ssh->queueing = FALSE;    ssh2_pkt_queuesend(ssh);    /*     * Expect SSH2_MSG_NEWKEYS from server.     */    crWaitUntil(pktin);    if (pktin->type != SSH2_MSG_NEWKEYS) {	bombout(("expected new-keys packet from server"));	crStop(0);    }    ssh->incoming_data_size = 0;       /* start counting from here */    /*     * We've seen server NEWKEYS, so create and initialise     * server-to-client session keys.     */    if (ssh->sc_cipher_ctx)	ssh->sccipher->free_context(ssh->sc_cipher_ctx);    ssh->sccipher = s->sccipher_tobe;    ssh->sc_cipher_ctx = ssh->sccipher->make_context();    if (ssh->sc_mac_ctx)	ssh->scmac->free_context(ssh->sc_mac_ctx);    ssh->scmac = s->scmac_tobe;    ssh->sc_mac_ctx = ssh->scmac->make_context();    if (ssh->sc_comp_ctx)	ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx);    ssh->sccomp = s->sccomp_tobe;    ssh->sc_comp_ctx = ssh->sccomp->decompress_init();    /*     * Set IVs on server-to-client keys. Here we use the exchange     * hash from the _first_ key exchange.     */    {	unsigned char keyspace[40];	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'D',keyspace);	ssh->sccipher->setkey(ssh->sc_cipher_ctx, keyspace);	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'B',keyspace);	ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace);	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'F',keyspace);	ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace);    }    logeventf(ssh, "Initialised %.200s server->client encryption",	      ssh->sccipher->text_name);    logeventf(ssh, "Initialised %.200s server->client MAC algorithm",	      ssh->scmac->text_name);    if (ssh->sccomp->text_name)	logeventf(ssh, "Initialised %s decompression",		  ssh->sccomp->text_name);    /*     * Free key exchange data.     */    freebn(s->f);    freebn(s->K);    if (ssh->kex == &ssh_diffiehellman_gex) {	freebn(s->g);	freebn(s->p);    }    /*     * Key exchange is over. Loop straight back round if we have a     * deferred rekey reason.     */    if (ssh->deferred_rekey_reason) {	logevent(ssh->deferred_rekey_reason);	pktin = NULL;	ssh->deferred_rekey_reason = NULL;	goto begin_key_exchange;    }    /*     * Otherwise, schedule a timer for our next rekey.     */    ssh->kex_in_progress = FALSE;    ssh->last_rekey = GETTICKCOUNT();    if (ssh->cfg.ssh_rekey_time != 0)	ssh->next_rekey = schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC,					 ssh2_timer, ssh);    /*     * 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 (s->activated_authconn) {	crReturn(1);    }    s->activated_authconn = TRUE;    /*     * 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.     *      * We _also_ go back to the start if we see pktin==NULL and     * inlen==-1, because this is a special signal meaning     * `initiate client-driven rekey', and `in' contains a message     * giving the reason for the rekey.     */    while (!((pktin && pktin->type == SSH2_MSG_KEXINIT) ||	     (!pktin && inlen == -1))) {	crReturn(1);    }    if (pktin) {	logevent("Server initiated key re-exchange");    } else {	logevent((char *)in);    }    goto begin_key_exchange;    crFinish(1);}