+ fprintf(stderr, "\ndh_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
+ fprintf(stderr, "\np= ");
+ BN_print_fp(stderr, dh->p);
+ fprintf(stderr, "\ng= ");
+ bn_print(dh->g);
+ fprintf(stderr, "\npub= ");
+ BN_print_fp(stderr, dh->pub_key);
+ fprintf(stderr, "\n");
+ DHparams_print_fp(stderr, dh);
+#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
+ debug("shared secret: len %d/%d", klen, kout);
+ fprintf(stderr, "shared secret == ");
+ for (i = 0; i< kout; i++)
+ fprintf(stderr, "%02x", (kbuf[i])&0xff);
+ fprintf(stderr, "\n");
+#endif
+ shared_secret = BN_new();
+
+ BN_bin2bn(kbuf, kout, shared_secret);
+ memset(kbuf, 0, klen);
+ xfree(kbuf);
+
+ /* XXX precompute? */
+ key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
+
+ /* calc H */ /* XXX depends on 'kex' */
+ hash = kex_hash_gex(
+ client_version_string,
+ server_version_string,
+ buffer_ptr(client_kexinit), buffer_len(client_kexinit),
+ buffer_ptr(server_kexinit), buffer_len(server_kexinit),
+ (char *)server_host_key_blob, sbloblen,
+ nbits, dh->p, dh->g,
+ dh_client_pub,
+ dh->pub_key,
+ shared_secret
+ );
+ buffer_free(client_kexinit);
+ buffer_free(server_kexinit);
+ xfree(client_kexinit);
+ xfree(server_kexinit);
+ BN_free(dh_client_pub);
+#ifdef DEBUG_KEXDH
+ fprintf(stderr, "hash == ");
+ for (i = 0; i< 20; i++)
+ fprintf(stderr, "%02x", (hash[i])&0xff);
+ fprintf(stderr, "\n");
+#endif
+ /* save session id := H */
+ /* XXX hashlen depends on KEX */
+ session_id2_len = 20;
+ session_id2 = xmalloc(session_id2_len);
+ memcpy(session_id2, hash, session_id2_len);
+
+ /* sign H */
+ /* XXX hashlen depends on KEX */
+ key_sign(hostkey, &signature, &slen, hash, 20);
+
+ destroy_sensitive_data();
+
+ /* send server hostkey, DH pubkey 'f' and singed H */
+ packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
+ packet_put_string((char *)server_host_key_blob, sbloblen);
+ packet_put_bignum2(dh->pub_key); /* f */
+ packet_put_string((char *)signature, slen);