state = xmalloc(sizeof(*state)); kex->state = state;  dispatch_set(SSH2_MSG_KEX_DH_GEX_REQUEST, &kexgex_input_request); dispatch_set(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD, &kexgex_input_request);
if (kex->load_host_key == NULL) fatal("Cannot load hostkey"); server_host_key = kex->load_host_key(kex->hostkey_type); if (server_host_key == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type);  type = packet_read(&plen); switch(type){ case SSH2_MSG_KEX_DH_GEX_REQUEST: debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); min = packet_get_int(); nbits = packet_get_int(); max = packet_get_int(); min = MAX(DH_GRP_MIN, min); max = MIN(DH_GRP_MAX, max); break; case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); nbits = packet_get_int(); min = DH_GRP_MIN; max = DH_GRP_MAX;  break; default: fatal("protocol error during kex, no DH_GEX_REQUEST"); } packet_done();  if (max < min || nbits < min || max < nbits) fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", min, nbits, max);  dh = choose_dh(min, nbits, max); if (dh == NULL) packet_disconnect("Protocol error: no matching DH grp found");  debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); packet_put_bignum2(dh->p); packet_put_bignum2(dh->g); packet_send();   packet_write_wait();   dh_gen_key(dh, kex->we_need * 8);  debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_INIT);   dh_client_pub = BN_new(); if (dh_client_pub == NULL) fatal("dh_client_pub == NULL"); packet_get_bignum2(dh_client_pub, &dlen);  #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); BN_print_fp(stderr, dh_client_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_client_pub)); #endif  #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); #endif if (!dh_pub_is_valid(dh, dh_client_pub)) packet_disconnect("bad client public DH value");  klen = DH_size(dh); kbuf = xmalloc(klen); kout = DH_compute_key(kbuf, dh_client_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);  key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);  if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) min = max = -1;  			 hash = kexgex_hash( kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), (char *)server_host_key_blob, sbloblen, min, nbits, max, dh->p, dh->g, dh_client_pub, dh->pub_key, shared_secret ); BN_free(dh_client_pub);    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); }    key_sign(server_host_key, &signature, &slen, hash, 20);     debug("SSH2_MSG_KEX_DH_GEX_REPLY sent"); packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); packet_put_string((char *)server_host_key_blob, sbloblen); packet_put_bignum2(dh->pub_key);	 packet_put_string((char *)signature, slen); packet_send(); xfree(signature); xfree(server_host_key_blob);  kex_derive_keys(kex, hash, shared_secret); BN_clear_free(shared_secret);  kex_send_newkeys();   DH_free(dh);
kexgex_server(Kex *kex){	State *state;	state = xmalloc(sizeof(*state));	kex->state = state;		dispatch_set(SSH2_MSG_KEX_DH_GEX_REQUEST, &kexgex_input_request);	dispatch_set(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD, &kexgex_input_request);}