xref: /freebsd/crypto/openssh/kexgexc.c (revision f7167e0ea0bf5aaabff9490453b3b71b3f1b4d51)
1*f7167e0eSDag-Erling Smørgrav /* $OpenBSD: kexgexc.c,v 1.16 2014/01/25 10:12:50 dtucker Exp $ */
2d0c8c0bcSDag-Erling Smørgrav /*
3d0c8c0bcSDag-Erling Smørgrav  * Copyright (c) 2000 Niels Provos.  All rights reserved.
4d0c8c0bcSDag-Erling Smørgrav  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
5d0c8c0bcSDag-Erling Smørgrav  *
6d0c8c0bcSDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
7d0c8c0bcSDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
8d0c8c0bcSDag-Erling Smørgrav  * are met:
9d0c8c0bcSDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
10d0c8c0bcSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
11d0c8c0bcSDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
12d0c8c0bcSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
13d0c8c0bcSDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
14d0c8c0bcSDag-Erling Smørgrav  *
15d0c8c0bcSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16d0c8c0bcSDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17d0c8c0bcSDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18d0c8c0bcSDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19d0c8c0bcSDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20d0c8c0bcSDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21d0c8c0bcSDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22d0c8c0bcSDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23d0c8c0bcSDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24d0c8c0bcSDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25d0c8c0bcSDag-Erling Smørgrav  */
26d0c8c0bcSDag-Erling Smørgrav 
27d0c8c0bcSDag-Erling Smørgrav #include "includes.h"
28761efaa7SDag-Erling Smørgrav 
29761efaa7SDag-Erling Smørgrav #include <sys/types.h>
30761efaa7SDag-Erling Smørgrav 
314a421b63SDag-Erling Smørgrav #include <openssl/dh.h>
324a421b63SDag-Erling Smørgrav 
33761efaa7SDag-Erling Smørgrav #include <stdarg.h>
34761efaa7SDag-Erling Smørgrav #include <stdio.h>
35761efaa7SDag-Erling Smørgrav #include <string.h>
36761efaa7SDag-Erling Smørgrav #include <signal.h>
37d0c8c0bcSDag-Erling Smørgrav 
38d0c8c0bcSDag-Erling Smørgrav #include "xmalloc.h"
39761efaa7SDag-Erling Smørgrav #include "buffer.h"
40d0c8c0bcSDag-Erling Smørgrav #include "key.h"
41761efaa7SDag-Erling Smørgrav #include "cipher.h"
42d0c8c0bcSDag-Erling Smørgrav #include "kex.h"
43d0c8c0bcSDag-Erling Smørgrav #include "log.h"
44d0c8c0bcSDag-Erling Smørgrav #include "packet.h"
45d0c8c0bcSDag-Erling Smørgrav #include "dh.h"
46d0c8c0bcSDag-Erling Smørgrav #include "ssh2.h"
47d0c8c0bcSDag-Erling Smørgrav #include "compat.h"
48d0c8c0bcSDag-Erling Smørgrav 
49d0c8c0bcSDag-Erling Smørgrav void
50d0c8c0bcSDag-Erling Smørgrav kexgex_client(Kex *kex)
51d0c8c0bcSDag-Erling Smørgrav {
52d0c8c0bcSDag-Erling Smørgrav 	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
53d0c8c0bcSDag-Erling Smørgrav 	BIGNUM *p = NULL, *g = NULL;
54d0c8c0bcSDag-Erling Smørgrav 	Key *server_host_key;
55d0c8c0bcSDag-Erling Smørgrav 	u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
5692eb0aa1SDag-Erling Smørgrav 	u_int klen, slen, sbloblen, hashlen;
5792eb0aa1SDag-Erling Smørgrav 	int kout;
58d0c8c0bcSDag-Erling Smørgrav 	int min, max, nbits;
59d0c8c0bcSDag-Erling Smørgrav 	DH *dh;
60d0c8c0bcSDag-Erling Smørgrav 
61*f7167e0eSDag-Erling Smørgrav 	nbits = dh_estimate(kex->dh_need * 8);
62d0c8c0bcSDag-Erling Smørgrav 
63d0c8c0bcSDag-Erling Smørgrav 	if (datafellows & SSH_OLD_DHGEX) {
64d0c8c0bcSDag-Erling Smørgrav 		/* Old GEX request */
65d0c8c0bcSDag-Erling Smørgrav 		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
66d0c8c0bcSDag-Erling Smørgrav 		packet_put_int(nbits);
67d0c8c0bcSDag-Erling Smørgrav 		min = DH_GRP_MIN;
68d0c8c0bcSDag-Erling Smørgrav 		max = DH_GRP_MAX;
69d0c8c0bcSDag-Erling Smørgrav 
70efcad6b7SDag-Erling Smørgrav 		debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", nbits);
71efcad6b7SDag-Erling Smørgrav 	} else {
72d0c8c0bcSDag-Erling Smørgrav 		/* New GEX request */
73d0c8c0bcSDag-Erling Smørgrav 		min = DH_GRP_MIN;
74d0c8c0bcSDag-Erling Smørgrav 		max = DH_GRP_MAX;
75d0c8c0bcSDag-Erling Smørgrav 		packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
76d0c8c0bcSDag-Erling Smørgrav 		packet_put_int(min);
77d0c8c0bcSDag-Erling Smørgrav 		packet_put_int(nbits);
78d0c8c0bcSDag-Erling Smørgrav 		packet_put_int(max);
79efcad6b7SDag-Erling Smørgrav 
80efcad6b7SDag-Erling Smørgrav 		debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent",
81efcad6b7SDag-Erling Smørgrav 		    min, nbits, max);
82d0c8c0bcSDag-Erling Smørgrav 	}
83d0c8c0bcSDag-Erling Smørgrav #ifdef DEBUG_KEXDH
84d0c8c0bcSDag-Erling Smørgrav 	fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
85d0c8c0bcSDag-Erling Smørgrav 	    min, nbits, max);
86d0c8c0bcSDag-Erling Smørgrav #endif
87d0c8c0bcSDag-Erling Smørgrav 	packet_send();
88d0c8c0bcSDag-Erling Smørgrav 
89d0c8c0bcSDag-Erling Smørgrav 	debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
90d0c8c0bcSDag-Erling Smørgrav 	packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP);
91d0c8c0bcSDag-Erling Smørgrav 
92d0c8c0bcSDag-Erling Smørgrav 	if ((p = BN_new()) == NULL)
93d0c8c0bcSDag-Erling Smørgrav 		fatal("BN_new");
94d0c8c0bcSDag-Erling Smørgrav 	packet_get_bignum2(p);
95d0c8c0bcSDag-Erling Smørgrav 	if ((g = BN_new()) == NULL)
96d0c8c0bcSDag-Erling Smørgrav 		fatal("BN_new");
97d0c8c0bcSDag-Erling Smørgrav 	packet_get_bignum2(g);
98d0c8c0bcSDag-Erling Smørgrav 	packet_check_eom();
99d0c8c0bcSDag-Erling Smørgrav 
100d0c8c0bcSDag-Erling Smørgrav 	if (BN_num_bits(p) < min || BN_num_bits(p) > max)
101d0c8c0bcSDag-Erling Smørgrav 		fatal("DH_GEX group out of range: %d !< %d !< %d",
102d0c8c0bcSDag-Erling Smørgrav 		    min, BN_num_bits(p), max);
103d0c8c0bcSDag-Erling Smørgrav 
104d0c8c0bcSDag-Erling Smørgrav 	dh = dh_new_group(g, p);
105d0c8c0bcSDag-Erling Smørgrav 	dh_gen_key(dh, kex->we_need * 8);
106d0c8c0bcSDag-Erling Smørgrav 
107d0c8c0bcSDag-Erling Smørgrav #ifdef DEBUG_KEXDH
108d0c8c0bcSDag-Erling Smørgrav 	DHparams_print_fp(stderr, dh);
109d0c8c0bcSDag-Erling Smørgrav 	fprintf(stderr, "pub= ");
110d0c8c0bcSDag-Erling Smørgrav 	BN_print_fp(stderr, dh->pub_key);
111d0c8c0bcSDag-Erling Smørgrav 	fprintf(stderr, "\n");
112d0c8c0bcSDag-Erling Smørgrav #endif
113d0c8c0bcSDag-Erling Smørgrav 
114d0c8c0bcSDag-Erling Smørgrav 	debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
115d0c8c0bcSDag-Erling Smørgrav 	/* generate and send 'e', client DH public key */
116d0c8c0bcSDag-Erling Smørgrav 	packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
117d0c8c0bcSDag-Erling Smørgrav 	packet_put_bignum2(dh->pub_key);
118d0c8c0bcSDag-Erling Smørgrav 	packet_send();
119d0c8c0bcSDag-Erling Smørgrav 
120d0c8c0bcSDag-Erling Smørgrav 	debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
121d0c8c0bcSDag-Erling Smørgrav 	packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY);
122d0c8c0bcSDag-Erling Smørgrav 
123d0c8c0bcSDag-Erling Smørgrav 	/* key, cert */
124d0c8c0bcSDag-Erling Smørgrav 	server_host_key_blob = packet_get_string(&sbloblen);
125d0c8c0bcSDag-Erling Smørgrav 	server_host_key = key_from_blob(server_host_key_blob, sbloblen);
126d0c8c0bcSDag-Erling Smørgrav 	if (server_host_key == NULL)
127d0c8c0bcSDag-Erling Smørgrav 		fatal("cannot decode server_host_key_blob");
128d0c8c0bcSDag-Erling Smørgrav 	if (server_host_key->type != kex->hostkey_type)
129d0c8c0bcSDag-Erling Smørgrav 		fatal("type mismatch for decoded server_host_key_blob");
130d0c8c0bcSDag-Erling Smørgrav 	if (kex->verify_host_key == NULL)
131d0c8c0bcSDag-Erling Smørgrav 		fatal("cannot verify server_host_key");
132d0c8c0bcSDag-Erling Smørgrav 	if (kex->verify_host_key(server_host_key) == -1)
133d0c8c0bcSDag-Erling Smørgrav 		fatal("server_host_key verification failed");
134d0c8c0bcSDag-Erling Smørgrav 
135761efaa7SDag-Erling Smørgrav 	/* DH parameter f, server public DH key */
136d0c8c0bcSDag-Erling Smørgrav 	if ((dh_server_pub = BN_new()) == NULL)
137d0c8c0bcSDag-Erling Smørgrav 		fatal("dh_server_pub == NULL");
138d0c8c0bcSDag-Erling Smørgrav 	packet_get_bignum2(dh_server_pub);
139d0c8c0bcSDag-Erling Smørgrav 
140d0c8c0bcSDag-Erling Smørgrav #ifdef DEBUG_KEXDH
141d0c8c0bcSDag-Erling Smørgrav 	fprintf(stderr, "dh_server_pub= ");
142d0c8c0bcSDag-Erling Smørgrav 	BN_print_fp(stderr, dh_server_pub);
143d0c8c0bcSDag-Erling Smørgrav 	fprintf(stderr, "\n");
144d0c8c0bcSDag-Erling Smørgrav 	debug("bits %d", BN_num_bits(dh_server_pub));
145d0c8c0bcSDag-Erling Smørgrav #endif
146d0c8c0bcSDag-Erling Smørgrav 
147d0c8c0bcSDag-Erling Smørgrav 	/* signed H */
148d0c8c0bcSDag-Erling Smørgrav 	signature = packet_get_string(&slen);
149d0c8c0bcSDag-Erling Smørgrav 	packet_check_eom();
150d0c8c0bcSDag-Erling Smørgrav 
151d0c8c0bcSDag-Erling Smørgrav 	if (!dh_pub_is_valid(dh, dh_server_pub))
152d0c8c0bcSDag-Erling Smørgrav 		packet_disconnect("bad server public DH value");
153d0c8c0bcSDag-Erling Smørgrav 
154d0c8c0bcSDag-Erling Smørgrav 	klen = DH_size(dh);
155d0c8c0bcSDag-Erling Smørgrav 	kbuf = xmalloc(klen);
15692eb0aa1SDag-Erling Smørgrav 	if ((kout = DH_compute_key(kbuf, dh_server_pub, dh)) < 0)
15792eb0aa1SDag-Erling Smørgrav 		fatal("DH_compute_key: failed");
158d0c8c0bcSDag-Erling Smørgrav #ifdef DEBUG_KEXDH
159d0c8c0bcSDag-Erling Smørgrav 	dump_digest("shared secret", kbuf, kout);
160d0c8c0bcSDag-Erling Smørgrav #endif
161d0c8c0bcSDag-Erling Smørgrav 	if ((shared_secret = BN_new()) == NULL)
162d0c8c0bcSDag-Erling Smørgrav 		fatal("kexgex_client: BN_new failed");
16392eb0aa1SDag-Erling Smørgrav 	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
16492eb0aa1SDag-Erling Smørgrav 		fatal("kexgex_client: BN_bin2bn failed");
165d0c8c0bcSDag-Erling Smørgrav 	memset(kbuf, 0, klen);
166e4a9863fSDag-Erling Smørgrav 	free(kbuf);
167d0c8c0bcSDag-Erling Smørgrav 
168d0c8c0bcSDag-Erling Smørgrav 	if (datafellows & SSH_OLD_DHGEX)
169d0c8c0bcSDag-Erling Smørgrav 		min = max = -1;
170d0c8c0bcSDag-Erling Smørgrav 
171d0c8c0bcSDag-Erling Smørgrav 	/* calc and verify H */
172021d409fSDag-Erling Smørgrav 	kexgex_hash(
173*f7167e0eSDag-Erling Smørgrav 	    kex->hash_alg,
174d0c8c0bcSDag-Erling Smørgrav 	    kex->client_version_string,
175d0c8c0bcSDag-Erling Smørgrav 	    kex->server_version_string,
176d0c8c0bcSDag-Erling Smørgrav 	    buffer_ptr(&kex->my), buffer_len(&kex->my),
177d0c8c0bcSDag-Erling Smørgrav 	    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
178d0c8c0bcSDag-Erling Smørgrav 	    server_host_key_blob, sbloblen,
179d0c8c0bcSDag-Erling Smørgrav 	    min, nbits, max,
180d0c8c0bcSDag-Erling Smørgrav 	    dh->p, dh->g,
181d0c8c0bcSDag-Erling Smørgrav 	    dh->pub_key,
182d0c8c0bcSDag-Erling Smørgrav 	    dh_server_pub,
183021d409fSDag-Erling Smørgrav 	    shared_secret,
184021d409fSDag-Erling Smørgrav 	    &hash, &hashlen
185d0c8c0bcSDag-Erling Smørgrav 	);
186021d409fSDag-Erling Smørgrav 
187d0c8c0bcSDag-Erling Smørgrav 	/* have keys, free DH */
188d0c8c0bcSDag-Erling Smørgrav 	DH_free(dh);
189e4a9863fSDag-Erling Smørgrav 	free(server_host_key_blob);
190d0c8c0bcSDag-Erling Smørgrav 	BN_clear_free(dh_server_pub);
191d0c8c0bcSDag-Erling Smørgrav 
192021d409fSDag-Erling Smørgrav 	if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1)
193d0c8c0bcSDag-Erling Smørgrav 		fatal("key_verify failed for server_host_key");
194d0c8c0bcSDag-Erling Smørgrav 	key_free(server_host_key);
195e4a9863fSDag-Erling Smørgrav 	free(signature);
196d0c8c0bcSDag-Erling Smørgrav 
197d0c8c0bcSDag-Erling Smørgrav 	/* save session id */
198d0c8c0bcSDag-Erling Smørgrav 	if (kex->session_id == NULL) {
199021d409fSDag-Erling Smørgrav 		kex->session_id_len = hashlen;
200d0c8c0bcSDag-Erling Smørgrav 		kex->session_id = xmalloc(kex->session_id_len);
201d0c8c0bcSDag-Erling Smørgrav 		memcpy(kex->session_id, hash, kex->session_id_len);
202d0c8c0bcSDag-Erling Smørgrav 	}
203*f7167e0eSDag-Erling Smørgrav 	kex_derive_keys_bn(kex, hash, hashlen, shared_secret);
204d0c8c0bcSDag-Erling Smørgrav 	BN_clear_free(shared_secret);
205d0c8c0bcSDag-Erling Smørgrav 
206d0c8c0bcSDag-Erling Smørgrav 	kex_finish(kex);
207d0c8c0bcSDag-Erling Smørgrav }
208