-
- debug("done: KEX2.");
-}
-
-/*
- * SSH2 key exchange
- */
-
-/* diffie-hellman-group1-sha1 */
-
-void
-ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
- int i;
-#endif
- int payload_len, dlen;
- int slen;
- u_char *signature = NULL;
- u_char *server_host_key_blob = NULL;
- u_int sbloblen;
- u_int klen, kout;
- u_char *kbuf;
- u_char *hash;
- BIGNUM *shared_secret = 0;
- DH *dh;
- BIGNUM *dh_client_pub = 0;
- Key *hostkey;
-
- hostkey = get_hostkey_by_type(kex->hostkey_type);
- if (hostkey == NULL)
- fatal("Unsupported hostkey type %d", kex->hostkey_type);
-
-/* KEXDH */
- /* generate DH key */
- dh = dh_new_group1(); /* XXX depends on 'kex' */
- dh_gen_key(dh);
-
- debug("Wait SSH2_MSG_KEXDH_INIT.");
- packet_read_expect(&payload_len, SSH2_MSG_KEXDH_INIT);
-
- /* key, cert */
- 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, "\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(
- 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,
- dh_client_pub,
- dh->pub_key,
- shared_secret
- );
- buffer_free(client_kexinit);
- buffer_free(server_kexinit);
- xfree(client_kexinit);
- xfree(server_kexinit);
-#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_KEXDH_REPLY);
- packet_put_string((char *)server_host_key_blob, sbloblen);
- packet_put_bignum2(dh->pub_key); /* f */
- packet_put_string((char *)signature, slen);
- packet_send();
- xfree(signature);
- xfree(server_host_key_blob);
- packet_write_wait();
-
- kex_derive_keys(kex, hash, shared_secret);
- packet_set_kex(kex);
-
- /* have keys, free DH */
- DH_free(dh);
-}
-
-/* diffie-hellman-group-exchange-sha1 */
-
-void
-ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
-{
-#ifdef DEBUG_KEXDH
- int i;
-#endif
- int payload_len, dlen;
- int slen, nbits;
- u_char *signature = NULL;
- u_char *server_host_key_blob = NULL;
- u_int sbloblen;
- u_int klen, kout;
- u_char *kbuf;
- u_char *hash;
- BIGNUM *shared_secret = 0;
- DH *dh;
- BIGNUM *dh_client_pub = 0;
- Key *hostkey;
-
- hostkey = get_hostkey_by_type(kex->hostkey_type);
- if (hostkey == NULL)
- fatal("Unsupported hostkey type %d", kex->hostkey_type);
-
-/* KEXDHGEX */
- debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST.");
- packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_REQUEST);
- nbits = packet_get_int();
- dh = choose_dh(nbits);
-
- debug("Sending SSH2_MSG_KEX_DH_GEX_GROUP.");
- packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
- packet_put_bignum2(dh->p);
- packet_put_bignum2(dh->g);
- packet_send();
- packet_write_wait();
-
- /* Compute our exchange value in parallel with the client */
-
- dh_gen_key(dh);
-
- debug("Wait SSH2_MSG_KEX_DH_GEX_INIT.");
- packet_read_expect(&payload_len, SSH2_MSG_KEX_DH_GEX_INIT);
-
- /* key, cert */
- 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, "\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);
-#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);
- packet_send();
- xfree(signature);
- xfree(server_host_key_blob);
- packet_write_wait();
-
- kex_derive_keys(kex, hash, shared_secret);
- packet_set_kex(kex);
-
- /* have keys, free DH */
- DH_free(dh);