debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);  if ((p = BN_new()) == NULL) fatal("BN_new"); packet_get_bignum2(p, &dlen); if ((g = BN_new()) == NULL) fatal("BN_new"); packet_get_bignum2(g, &dlen); packet_done();  if (BN_num_bits(p) < min || BN_num_bits(p) > max) fatal("DH_GEX group out of range: %d !< %d !< %d", min, BN_num_bits(p), max);  dh = dh_new_group(g, p); dh_gen_key(dh, kex->we_need * 8);  #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); #endif  debug("SSH2_MSG_KEX_DH_GEX_INIT sent");  packet_start(SSH2_MSG_KEX_DH_GEX_INIT); packet_put_bignum2(dh->pub_key); packet_send();  debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);   server_host_key_blob = packet_get_string(&sbloblen); server_host_key = key_from_blob(server_host_key_blob, sbloblen); if (server_host_key == NULL) fatal("cannot decode server_host_key_blob");  if (kex->check_host_key == NULL) fatal("cannot check server_host_key"); kex->check_host_key(server_host_key);   dh_server_pub = BN_new(); if (dh_server_pub == NULL) fatal("dh_server_pub == NULL"); packet_get_bignum2(dh_server_pub, &dlen);  #ifdef DEBUG_KEXDH fprintf(stderr, "dh_server_pub= "); BN_print_fp(stderr, dh_server_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_server_pub)); #endif   signature = packet_get_string(&slen); packet_done();  if (!dh_pub_is_valid(dh, dh_server_pub)) packet_disconnect("bad server public DH value");  klen = DH_size(dh); kbuf = xmalloc(klen); kout = DH_compute_key(kbuf, dh_server_pub, dh); #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif shared_secret = BN_new(); BN_bin2bn(kbuf, kout, shared_secret); memset(kbuf, 0, klen); xfree(kbuf);  if (datafellows & SSH_OLD_DHGEX) min = max = -1;   hash = kexgex_hash( kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->my), buffer_len(&kex->my), buffer_ptr(&kex->peer), buffer_len(&kex->peer), server_host_key_blob, sbloblen, min, nbits, max, dh->p, dh->g, dh->pub_key, dh_server_pub, shared_secret ); xfree(server_host_key_blob); BN_free(dh_server_pub);  if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1) fatal("key_verify failed for server_host_key"); key_free(server_host_key); xfree(signature);   if (kex->session_id == NULL) { kex->session_id_len = 20; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); }  kex_derive_keys(kex, hash, shared_secret); BN_clear_free(shared_secret);  kex_send_newkeys();   DH_free(dh);
kexgex_client(Kex *kex){	State *state;	dispatch_set(SSH2_MSG_KEX_DH_GEX_GROUP, &kexgex_input_group);	state = xmalloc(sizeof(*state));	state->nbits = dh_estimate(kex->we_need * 8);	kex->state = state;	if (datafellows & SSH_OLD_DHGEX) {		debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD sent");		/* Old GEX request */		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);		packet_put_int(state->nbits);		state->min = DH_GRP_MIN;		state->max = DH_GRP_MAX;	} else {		debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent");		/* New GEX request */		state->min = DH_GRP_MIN;		state->max = DH_GRP_MAX;		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);		packet_put_int(state->min);		packet_put_int(state->nbits);		packet_put_int(state->max);	}#ifdef DEBUG_KEXDH	fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",	    state->min, state->nbits, state->max);#endif	packet_send();}