Exemple #1
0
/* hash the ssh representation of the mp_int mp */
void sha1_process_mp(hash_state *hs, mp_int *mp) {

	int i;
	buffer * buf;

	buf = buf_new(512 + 20); /* max buffer is a 4096 bit key, 
								plus header + some leeway*/
	buf_putmpint(buf, mp);
	i = buf->pos;
	buf_setpos(buf, 0);
	sha1_process(hs, buf_getptr(buf, i), i);
	buf_free(buf);
}
void send_msg_kexdh_init() {

	cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int));
	cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int));
	m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL);

	gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x);

	CHECKCLEARTOWRITE();
	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
	buf_putmpint(ses.writepayload, cli_ses.dh_e);
	encrypt_packet();
	ses.requirenext = SSH_MSG_KEXDH_REPLY;
}
Exemple #3
0
void send_msg_kexdh_init() {
	TRACE(("send_msg_kexdh_init()"))	

	CHECKCLEARTOWRITE();
	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_INIT);
	switch (ses.newkeys->algo_kex->mode) {
		case DROPBEAR_KEX_NORMAL_DH:
			if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
				|| !cli_ses.dh_param) {
				if (cli_ses.dh_param) {
					free_kexdh_param(cli_ses.dh_param);
				}
				cli_ses.dh_param = gen_kexdh_param();
			}
			buf_putmpint(ses.writepayload, &cli_ses.dh_param->pub);
			break;
		case DROPBEAR_KEX_ECDH:
#ifdef DROPBEAR_ECDH
			if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
				|| !cli_ses.ecdh_param) {
				if (cli_ses.ecdh_param) {
					free_kexecdh_param(cli_ses.ecdh_param);
				}
				cli_ses.ecdh_param = gen_kexecdh_param();
			}
			buf_put_ecc_raw_pubkey_string(ses.writepayload, &cli_ses.ecdh_param->key);
#endif
			break;
#ifdef DROPBEAR_CURVE25519
		case DROPBEAR_KEX_CURVE25519:
			if (ses.newkeys->algo_kex != cli_ses.param_kex_algo
				|| !cli_ses.curve25519_param) {
				if (cli_ses.curve25519_param) {
					free_kexcurve25519_param(cli_ses.curve25519_param);
				}
				cli_ses.curve25519_param = gen_kexcurve25519_param();
			}
			buf_putstring(ses.writepayload, cli_ses.curve25519_param->pub, CURVE25519_LEN);
#endif
			break;
	}

	cli_ses.param_kex_algo = ses.newkeys->algo_kex;
	encrypt_packet();
	ses.requirenext[0] = SSH_MSG_KEXDH_REPLY;
	ses.requirenext[1] = SSH_MSG_KEXINIT;
}
Exemple #4
0
/* Generate our side of the diffie-hellman key exchange value (dh_f), and
 * calculate the session key using the diffie-hellman algorithm. Following
 * that, the session hash is calculated, and signed with RSA or DSS. The
 * result is sent to the client. 
 *
 * See the ietf-secsh-transport draft, section 6, for details */
static void send_msg_kexdh_reply(mp_int *dh_e) {

	mp_int dh_p, dh_q, dh_g, dh_y, dh_f;
	unsigned char randbuf[DH_P_LEN];
	int dh_q_len;
	hash_state hs;

	TRACE(("enter send_msg_kexdh_reply"));
	
	assert(ses.kexstate.recvkexinit);

	m_mp_init_multi(&dh_g, &dh_p, &dh_q, &dh_y, &dh_f, NULL);

	/* read the prime and generator*/
	if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN)
			!= MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	
	if (mp_set_int(&dh_g, dh_g_val) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* calculate q = (p-1)/2 */
	if (mp_sub_d(&dh_p, 1, &dh_y) != MP_OKAY) { /*dh_y is just a temp var here*/
		dropbear_exit("Diffie-Hellman error");
	}
	if (mp_div_2(&dh_y, &dh_q) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	dh_q_len = mp_unsigned_bin_size(&dh_q);

	/* calculate our random value dh_y */
	do {
		assert((unsigned int)dh_q_len <= sizeof(randbuf));
		genrandom(randbuf, dh_q_len);
		if (mp_read_unsigned_bin(&dh_y, randbuf, dh_q_len) != MP_OKAY) {
			dropbear_exit("Diffie-Hellman error");
		}
	} while (mp_cmp(&dh_y, &dh_q) == MP_GT || mp_cmp_d(&dh_y, 0) != MP_GT);

	/* f = g^y mod p */
	if (mp_exptmod(&dh_g, &dh_y, &dh_p, &dh_f) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	mp_clear(&dh_g);

	/* K = e^y mod p */
	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int));
	m_mp_init(ses.dh_K);
	if (mp_exptmod(dh_e, &dh_y, &dh_p, ses.dh_K) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* clear no longer needed vars */
	mp_clear_multi(&dh_y, &dh_p, &dh_q, NULL);

	/* Create the remainder of the hash buffer, to generate the exchange hash */
	/* K_S, the host key */
	buf_put_pub_key(ses.kexhashbuf, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey);
	/* e, exchange value sent by the client */
	buf_putmpint(ses.kexhashbuf, dh_e);
	/* f, exchange value sent by the server */
	buf_putmpint(ses.kexhashbuf, &dh_f);
	/* K, the shared secret */
	buf_putmpint(ses.kexhashbuf, ses.dh_K);

	/* calculate the hash H to sign */
	sha1_init(&hs);
	buf_setpos(ses.kexhashbuf, 0);
	sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
			ses.kexhashbuf->len);
	sha1_done(&hs, ses.hash);
	buf_free(ses.kexhashbuf);
	ses.kexhashbuf = NULL;
	
	/* first time around, we set the session_id to H */
	if (ses.session_id == NULL) {
		/* create the session_id, this never needs freeing */
		ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE);
		memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE);
	}
	
	/* we can start creating the kexdh_reply packet */
	CHECKCLEARTOWRITE();
	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
	buf_put_pub_key(ses.writepayload, ses.opts->hostkey,
			ses.newkeys->algo_hostkey);

	/* put f */
	buf_putmpint(ses.writepayload, &dh_f);
	mp_clear(&dh_f);

	/* calc the signature */
	buf_put_sign(ses.writepayload, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey, ses.hash, SHA1_HASH_SIZE);

	/* the SSH_MSG_KEXDH_REPLY is done */
	encrypt_packet();

	TRACE(("leave send_msg_kexdh_reply"));
}