kexgexc.c revision 162852
11590Srgrimes/* $OpenBSD: kexgexc.c,v 1.9 2006/08/03 03:34:42 deraadt Exp $ */
21590Srgrimes/*
31590Srgrimes * Copyright (c) 2000 Niels Provos.  All rights reserved.
41590Srgrimes * Copyright (c) 2001 Markus Friedl.  All rights reserved.
51590Srgrimes *
61590Srgrimes * Redistribution and use in source and binary forms, with or without
71590Srgrimes * modification, are permitted provided that the following conditions
81590Srgrimes * are met:
91590Srgrimes * 1. Redistributions of source code must retain the above copyright
101590Srgrimes *    notice, this list of conditions and the following disclaimer.
111590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121590Srgrimes *    notice, this list of conditions and the following disclaimer in the
131590Srgrimes *    documentation and/or other materials provided with the distribution.
141590Srgrimes *
151590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
161590Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
171590Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
181590Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
191590Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
201590Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
211590Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
221590Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231590Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
241590Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251590Srgrimes */
261590Srgrimes
271590Srgrimes#include "includes.h"
281590Srgrimes
291590Srgrimes#include <sys/types.h>
301590Srgrimes
3127751Scharnier#include <stdarg.h>
321590Srgrimes#include <stdio.h>
331590Srgrimes#include <string.h>
341590Srgrimes#include <signal.h>
351590Srgrimes
3694992Sbde#include "xmalloc.h"
371590Srgrimes#include "buffer.h"
3827751Scharnier#include "key.h"
3994992Sbde#include "cipher.h"
4027751Scharnier#include "kex.h"
411590Srgrimes#include "log.h"
4294504Scharnier#include "packet.h"
4394504Scharnier#include "dh.h"
4494504Scharnier#include "ssh2.h"
451590Srgrimes#include "compat.h"
461590Srgrimes
471590Srgrimesvoid
481590Srgrimeskexgex_client(Kex *kex)
491590Srgrimes{
501590Srgrimes	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
511590Srgrimes	BIGNUM *p = NULL, *g = NULL;
521590Srgrimes	Key *server_host_key;
531590Srgrimes	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
541590Srgrimes	u_int klen, kout, slen, sbloblen, hashlen;
551590Srgrimes	int min, max, nbits;
561590Srgrimes	DH *dh;
571590Srgrimes
581590Srgrimes	nbits = dh_estimate(kex->we_need * 8);
591590Srgrimes
601590Srgrimes	if (datafellows & SSH_OLD_DHGEX) {
611590Srgrimes		/* Old GEX request */
621590Srgrimes		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
631590Srgrimes		packet_put_int(nbits);
641590Srgrimes		min = DH_GRP_MIN;
651590Srgrimes		max = DH_GRP_MAX;
661590Srgrimes
671590Srgrimes		debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", nbits);
688382Srgrimes	} else {
691590Srgrimes		/* New GEX request */
708382Srgrimes		min = DH_GRP_MIN;
711590Srgrimes		max = DH_GRP_MAX;
721590Srgrimes		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
731590Srgrimes		packet_put_int(min);
741590Srgrimes		packet_put_int(nbits);
7518485Sbde		packet_put_int(max);
7627751Scharnier
771590Srgrimes		debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent",
7837534Sghelmer		    min, nbits, max);
7912809Sache	}
801590Srgrimes#ifdef DEBUG_KEXDH
811590Srgrimes	fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
8227751Scharnier	    min, nbits, max);
836591Swollman#endif
841590Srgrimes	packet_send();
851590Srgrimes
861590Srgrimes	debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
871590Srgrimes	packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP);
881590Srgrimes
891590Srgrimes	if ((p = BN_new()) == NULL)
901590Srgrimes		fatal("BN_new");
911590Srgrimes	packet_get_bignum2(p);
9212390Sache	if ((g = BN_new()) == NULL)
931590Srgrimes		fatal("BN_new");
941590Srgrimes	packet_get_bignum2(g);
951590Srgrimes	packet_check_eom();
961590Srgrimes
971590Srgrimes	if (BN_num_bits(p) < min || BN_num_bits(p) > max)
981590Srgrimes		fatal("DH_GEX group out of range: %d !< %d !< %d",
991590Srgrimes		    min, BN_num_bits(p), max);
1001590Srgrimes
1011590Srgrimes	dh = dh_new_group(g, p);
1021590Srgrimes	dh_gen_key(dh, kex->we_need * 8);
1031590Srgrimes
1041590Srgrimes#ifdef DEBUG_KEXDH
1051590Srgrimes	DHparams_print_fp(stderr, dh);
1061590Srgrimes	fprintf(stderr, "pub= ");
1071590Srgrimes	BN_print_fp(stderr, dh->pub_key);
108241737Sed	fprintf(stderr, "\n");
109241737Sed#endif
110241737Sed
111241737Sed	debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
112241737Sed	/* generate and send 'e', client DH public key */
113241737Sed	packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
114241737Sed	packet_put_bignum2(dh->pub_key);
115241737Sed	packet_send();
116241737Sed
117241737Sed	debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
118241737Sed	packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY);
119241737Sed
120241737Sed	/* key, cert */
121241737Sed	server_host_key_blob = packet_get_string(&sbloblen);
122241737Sed	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
123241737Sed	if (server_host_key == NULL)
124241737Sed		fatal("cannot decode server_host_key_blob");
125241737Sed	if (server_host_key->type != kex->hostkey_type)
126241737Sed		fatal("type mismatch for decoded server_host_key_blob");
127241737Sed	if (kex->verify_host_key == NULL)
128241737Sed		fatal("cannot verify server_host_key");
129241737Sed	if (kex->verify_host_key(server_host_key) == -1)
130241737Sed		fatal("server_host_key verification failed");
131241737Sed
132241737Sed	/* DH parameter f, server public DH key */
133241737Sed	if ((dh_server_pub = BN_new()) == NULL)
134241737Sed		fatal("dh_server_pub == NULL");
135241737Sed	packet_get_bignum2(dh_server_pub);
136241737Sed
137241737Sed#ifdef DEBUG_KEXDH
1381590Srgrimes	fprintf(stderr, "dh_server_pub= ");
1391590Srgrimes	BN_print_fp(stderr, dh_server_pub);
140241737Sed	fprintf(stderr, "\n");
141241737Sed	debug("bits %d", BN_num_bits(dh_server_pub));
142241737Sed#endif
143241737Sed
144241737Sed	/* signed H */
145241737Sed	signature = packet_get_string(&slen);
146241737Sed	packet_check_eom();
147241737Sed
148241737Sed	if (!dh_pub_is_valid(dh, dh_server_pub))
1491590Srgrimes		packet_disconnect("bad server public DH value");
150140389Sdelphij
151140389Sdelphij	klen = DH_size(dh);
152140389Sdelphij	kbuf = xmalloc(klen);
153140389Sdelphij	kout = DH_compute_key(kbuf, dh_server_pub, dh);
154140389Sdelphij#ifdef DEBUG_KEXDH
155140389Sdelphij	dump_digest("shared secret", kbuf, kout);
156140389Sdelphij#endif
157140389Sdelphij	if ((shared_secret = BN_new()) == NULL)
158241737Sed		fatal("kexgex_client: BN_new failed");
15927751Scharnier	BN_bin2bn(kbuf, kout, shared_secret);
16027751Scharnier	memset(kbuf, 0, klen);
161102944Sdwmalone	xfree(kbuf);
1621590Srgrimes
1631590Srgrimes	if (datafellows & SSH_OLD_DHGEX)
1641590Srgrimes		min = max = -1;
1651590Srgrimes
16612646Sdg	/* calc and verify H */
1671590Srgrimes	kexgex_hash(
16837476Sjkh	    kex->evp_md,
1691590Srgrimes	    kex->client_version_string,
170173169Skevlo	    kex->server_version_string,
1711590Srgrimes	    buffer_ptr(&kex->my), buffer_len(&kex->my),
1721590Srgrimes	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
1731590Srgrimes	    server_host_key_blob, sbloblen,
1741590Srgrimes	    min, nbits, max,
17512809Sache	    dh->p, dh->g,
1761590Srgrimes	    dh->pub_key,
1771590Srgrimes	    dh_server_pub,
178241848Seadler	    shared_secret,
179241848Seadler	    &hash, &hashlen
1801590Srgrimes	);
1811590Srgrimes
1821590Srgrimes	/* have keys, free DH */
1831590Srgrimes	DH_free(dh);
1841590Srgrimes	xfree(server_host_key_blob);
1851590Srgrimes	BN_clear_free(dh_server_pub);
1861590Srgrimes
1871590Srgrimes	if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1)
1881590Srgrimes		fatal("key_verify failed for server_host_key");
1891590Srgrimes	key_free(server_host_key);
1901590Srgrimes	xfree(signature);
1911590Srgrimes
1921590Srgrimes	/* save session id */
1931590Srgrimes	if (kex->session_id == NULL) {
1941590Srgrimes		kex->session_id_len = hashlen;
1951590Srgrimes		kex->session_id = xmalloc(kex->session_id_len);
1961590Srgrimes		memcpy(kex->session_id, hash, kex->session_id_len);
1971590Srgrimes	}
1981590Srgrimes	kex_derive_keys(kex, hash, hashlen, shared_secret);
1991590Srgrimes	BN_clear_free(shared_secret);
20094504Scharnier
20194504Scharnier	kex_finish(kex);
20294504Scharnier}
2031590Srgrimes