- debug("done: KEX2.");
-}
-
-/* diffie-hellman-group1-sha1 */
-
-void
-ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
- Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
- int i;
-#endif
- int plen, dlen;
- u_int klen, kout;
- char *signature = NULL;
- u_int slen;
- char *server_host_key_blob = NULL;
- Key *server_host_key;
- u_int sbloblen;
- DH *dh;
- BIGNUM *dh_server_pub = 0;
- BIGNUM *shared_secret = 0;
- u_char *kbuf;
- u_char *hash;
-
- debug("Sending SSH2_MSG_KEXDH_INIT.");
- /* generate and send 'e', client DH public key */
- dh = dh_new_group1();
- dh_gen_key(dh);
- packet_start(SSH2_MSG_KEXDH_INIT);
- packet_put_bignum2(dh->pub_key);
- packet_send();
- packet_write_wait();
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "\np= ");
- BN_print_fp(stderr, dh->p);
- fprintf(stderr, "\ng= ");
- BN_print_fp(stderr, dh->g);
- fprintf(stderr, "\npub= ");
- BN_print_fp(stderr, dh->pub_key);
- fprintf(stderr, "\n");
- DHparams_print_fp(stderr, dh);
-#endif
-
- debug("Wait SSH2_MSG_KEXDH_REPLY.");
-
- packet_read_expect(&plen, SSH2_MSG_KEXDH_REPLY);
-
- debug("Got SSH2_MSG_KEXDH_REPLY.");
-
- /* key, cert */
- 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");
-
- check_host_key(host, hostaddr, server_host_key,
- options.user_hostfile2, options.system_hostfile2);
-
- /* DH paramter f, server public DH 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, "\ndh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-
- /* signed H */
- 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
- 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);
-
- /* calc and verify H */
- hash = kex_hash(
- client_version_string,
- server_version_string,
- buffer_ptr(client_kexinit), buffer_len(client_kexinit),
- buffer_ptr(server_kexinit), buffer_len(server_kexinit),
- server_host_key_blob, sbloblen,
- dh->pub_key,
- dh_server_pub,
- shared_secret
- );
- xfree(server_host_key_blob);
- DH_free(dh);
- BN_free(dh_server_pub);
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "hash == ");
- for (i = 0; i< 20; i++)
- fprintf(stderr, "%02x", (hash[i])&0xff);
- fprintf(stderr, "\n");
-#endif
- 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);
-
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
- packet_set_kex(kex);
-
- /* save session id */
- session_id2_len = 20;
- session_id2 = xmalloc(session_id2_len);
- memcpy(session_id2, hash, session_id2_len);
-}
-
-/* diffie-hellman-group-exchange-sha1 */
-
-/*
- * Estimates the group order for a Diffie-Hellman group that has an
- * attack complexity approximately the same as O(2**bits). Estimate
- * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
- */
-
-int
-dh_estimate(int bits)
-{
-
- if (bits < 64)
- return (512); /* O(2**63) */
- if (bits < 128)
- return (1024); /* O(2**86) */
- if (bits < 192)
- return (2048); /* O(2**116) */
- return (4096); /* O(2**156) */
-}
-
-void
-ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
- Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
- int i;
-#endif
- int plen, dlen;
- u_int klen, kout;
- char *signature = NULL;
- u_int slen, nbits;
- char *server_host_key_blob = NULL;
- Key *server_host_key;
- u_int sbloblen;
- DH *dh;
- BIGNUM *dh_server_pub = 0;
- BIGNUM *shared_secret = 0;
- BIGNUM *p = 0, *g = 0;
- u_char *kbuf;
- u_char *hash;
-
- nbits = dh_estimate(kex->enc[MODE_OUT].cipher->key_len * 8);
-
- debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
- packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
- packet_put_int(nbits);
- packet_send();
- packet_write_wait();
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "\nnbits = %d", nbits);
-#endif
-
- debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP.");
-
- packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
-
- debug("Got 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);
- dh = dh_new_group(g, p);
-
- dh_gen_key(dh);
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "\np= ");
- BN_print_fp(stderr, dh->p);
- fprintf(stderr, "\ng= ");
- BN_print_fp(stderr, dh->g);
- fprintf(stderr, "\npub= ");
- BN_print_fp(stderr, dh->pub_key);
- fprintf(stderr, "\n");
- DHparams_print_fp(stderr, dh);
-#endif
-
- debug("Sending SSH2_MSG_KEX_DH_GEX_INIT.");
- /* generate and send 'e', client DH public key */
- packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
- packet_put_bignum2(dh->pub_key);
- packet_send();
- packet_write_wait();
-
- debug("Wait SSH2_MSG_KEX_DH_GEX_REPLY.");
-
- packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
-
- debug("Got SSH2_MSG_KEXDH_REPLY.");
-
- /* key, cert */
- 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");
-
- check_host_key(host, hostaddr, server_host_key,
- options.user_hostfile2, options.system_hostfile2);
-
- /* DH paramter f, server public DH 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, "\ndh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-
- /* signed H */
- 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
- 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);
-
- /* calc and verify H */
- 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),
- server_host_key_blob, sbloblen,
- nbits, dh->p, dh->g,
- dh->pub_key,
- dh_server_pub,
- shared_secret
- );
- xfree(server_host_key_blob);
- DH_free(dh);
- BN_free(dh_server_pub);
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "hash == ");
- for (i = 0; i< 20; i++)
- fprintf(stderr, "%02x", (hash[i])&0xff);
- fprintf(stderr, "\n");
-#endif
- 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);
-
- kex_derive_keys(kex, hash, shared_secret);
- BN_clear_free(shared_secret);
- packet_set_kex(kex);
-
- /* save session id */
- session_id2_len = 20;
- session_id2 = xmalloc(session_id2_len);
- memcpy(session_id2, hash, session_id2_len);