1 /*
2  * Copyright (C) 2002-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>
20  *
21  */
22 
23 /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
24  * and Anonymous DH key exchange(DHA). These are used in the handshake
25  * procedure of the certificate and anonymous authentication.
26  */
27 
28 #include "gnutls_int.h"
29 #include "auth.h"
30 #include "errors.h"
31 #include "dh.h"
32 #include "num.h"
33 #include "tls-sig.h"
34 #include <datum.h>
35 #include <x509.h>
36 #include <state.h>
37 #include <pk.h>
38 #include <auth/dh_common.h>
39 #include <algorithms.h>
40 #include <auth/psk.h>
41 
42 #if defined(ENABLE_DHE) || defined(ENABLE_ANON)
43 
44 /* Frees the dh_info_st structure.
45  */
_gnutls_free_dh_info(dh_info_st * dh)46 void _gnutls_free_dh_info(dh_info_st * dh)
47 {
48 	dh->secret_bits = 0;
49 	_gnutls_free_datum(&dh->prime);
50 	_gnutls_free_datum(&dh->generator);
51 	_gnutls_free_datum(&dh->public_key);
52 }
53 
54 int
_gnutls_proc_dh_common_client_kx(gnutls_session_t session,uint8_t * data,size_t _data_size,gnutls_datum_t * psk_key)55 _gnutls_proc_dh_common_client_kx(gnutls_session_t session,
56 				 uint8_t * data, size_t _data_size,
57 				 gnutls_datum_t * psk_key)
58 {
59 	uint16_t n_Y;
60 	size_t _n_Y;
61 	int ret;
62 	ssize_t data_size = _data_size;
63 	gnutls_datum_t tmp_dh_key = {NULL, 0};
64 	gnutls_pk_params_st peer_pub;
65 
66 	gnutls_pk_params_init(&peer_pub);
67 
68 	DECR_LEN(data_size, 2);
69 	n_Y = _gnutls_read_uint16(&data[0]);
70 	_n_Y = n_Y;
71 
72 	DECR_LEN(data_size, n_Y);
73 
74 	if (data_size != 0)
75 		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
76 
77 	if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.client_Y, &data[2], _n_Y)) {
78 		gnutls_assert();
79 		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* most likely zero or illegal size */
80 	}
81 
82 	_gnutls_dh_set_peer_public(session, session->key.proto.tls12.dh.client_Y);
83 
84 	peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y;
85 
86 	/* calculate the key after calculating the message */
87 	ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.proto.tls12.dh.params, &peer_pub);
88 	if (ret < 0) {
89 		gnutls_assert();
90 		goto error;
91 	}
92 
93 	if (psk_key == NULL) {
94 		session->key.key.data = tmp_dh_key.data;
95 		session->key.key.size = tmp_dh_key.size;
96 	} else {		/* In DHE_PSK the key is set differently */
97 		ret =
98 		    _gnutls_set_psk_session_key(session, psk_key,
99 						&tmp_dh_key);
100 		_gnutls_free_temp_key_datum(&tmp_dh_key);
101 	}
102 
103 	if (ret < 0) {
104 		gnutls_assert();
105 		goto error;
106 	}
107 
108 	ret = 0;
109  error:
110 	_gnutls_mpi_release(&session->key.proto.tls12.dh.client_Y);
111 	gnutls_pk_params_clear(&session->key.proto.tls12.dh.params);
112 
113 	return ret;
114 }
115 
_gnutls_gen_dh_common_client_kx(gnutls_session_t session,gnutls_buffer_st * data)116 int _gnutls_gen_dh_common_client_kx(gnutls_session_t session,
117 				    gnutls_buffer_st * data)
118 {
119 	return _gnutls_gen_dh_common_client_kx_int(session, data, NULL);
120 }
121 
122 int
_gnutls_gen_dh_common_client_kx_int(gnutls_session_t session,gnutls_buffer_st * data,gnutls_datum_t * pskkey)123 _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session,
124 				    gnutls_buffer_st * data,
125 				    gnutls_datum_t * pskkey)
126 {
127 	int ret;
128 	gnutls_pk_params_st peer_pub;
129 	gnutls_datum_t tmp_dh_key = {NULL, 0};
130 	unsigned init_pos = data->length;
131 
132 	gnutls_pk_params_init(&peer_pub);
133 
134 	ret =
135 	    _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0,
136 				     &session->key.proto.tls12.dh.params, 1);
137 	if (ret < 0)
138 		return gnutls_assert_val(ret);
139 
140 	_gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_X]));
141 
142 	ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_Y], 0);
143 	if (ret < 0) {
144 		gnutls_assert();
145 		goto error;
146 	}
147 
148 	peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y;
149 
150 	/* calculate the key after calculating the message */
151 	ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.proto.tls12.dh.params, &peer_pub);
152 	if (ret < 0) {
153 		gnutls_assert();
154 		goto error;
155 	}
156 
157 	if (session->security_parameters.cs->kx_algorithm != GNUTLS_KX_DHE_PSK) {
158 		session->key.key.data = tmp_dh_key.data;
159 		session->key.key.size = tmp_dh_key.size;
160 	} else {		/* In DHE_PSK the key is set differently */
161 		ret =
162 		    _gnutls_set_psk_session_key(session, pskkey,
163 						&tmp_dh_key);
164 		_gnutls_free_temp_key_datum(&tmp_dh_key);
165 	}
166 
167 	if (ret < 0) {
168 		gnutls_assert();
169 		goto error;
170 	}
171 
172 	ret = data->length - init_pos;
173 
174  error:
175 	gnutls_pk_params_clear(&session->key.proto.tls12.dh.params);
176 	return ret;
177 }
178 
179 /* Returns the bytes parsed */
180 int
_gnutls_proc_dh_common_server_kx(gnutls_session_t session,uint8_t * data,size_t _data_size)181 _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
182 				 uint8_t * data, size_t _data_size)
183 {
184 	uint16_t n_Y, n_g, n_p;
185 	size_t _n_Y, _n_g, _n_p, _n_q;
186 	uint8_t *data_p;
187 	uint8_t *data_g;
188 	uint8_t *data_Y;
189 	uint8_t *data_q = NULL;
190 	int i, bits, ret, p_bits;
191 	unsigned j;
192 	ssize_t data_size = _data_size;
193 
194 	/* just in case we are resuming a session */
195 	gnutls_pk_params_release(&session->key.proto.tls12.dh.params);
196 
197 	gnutls_pk_params_init(&session->key.proto.tls12.dh.params);
198 
199 	i = 0;
200 
201 	DECR_LEN(data_size, 2);
202 	n_p = _gnutls_read_uint16(&data[i]);
203 	i += 2;
204 
205 	DECR_LEN(data_size, n_p);
206 	data_p = &data[i];
207 	i += n_p;
208 
209 	DECR_LEN(data_size, 2);
210 	n_g = _gnutls_read_uint16(&data[i]);
211 	i += 2;
212 
213 	DECR_LEN(data_size, n_g);
214 	data_g = &data[i];
215 	i += n_g;
216 
217 	DECR_LEN(data_size, 2);
218 	n_Y = _gnutls_read_uint16(&data[i]);
219 	i += 2;
220 
221 	DECR_LEN(data_size, n_Y);
222 	data_Y = &data[i];
223 
224 	_n_Y = n_Y;
225 	_n_g = n_g;
226 	_n_p = n_p;
227 
228 	if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.client_Y, data_Y, _n_Y) != 0) {
229 		gnutls_assert();
230 		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
231 	}
232 
233 	/* if we are doing RFC7919 */
234 	if (session->internals.priorities->groups.have_ffdhe != 0) {
235 		/* verify whether the received parameters match the advertised, otherwise
236 		 * log that. */
237 		for (j=0;j<session->internals.priorities->groups.size;j++) {
238 			if (session->internals.priorities->groups.entry[j]->generator &&
239 			    session->internals.priorities->groups.entry[j]->generator->size == n_g &&
240 			    session->internals.priorities->groups.entry[j]->prime->size == n_p &&
241 			    memcmp(session->internals.priorities->groups.entry[j]->generator->data,
242 				   data_g, n_g) == 0 &&
243 			    memcmp(session->internals.priorities->groups.entry[j]->prime->data,
244 				   data_p, n_p) == 0) {
245 
246 				session->internals.hsk_flags |= HSK_USED_FFDHE;
247 				_gnutls_session_group_set(session, session->internals.priorities->groups.entry[j]);
248 				session->key.proto.tls12.dh.params.qbits = *session->internals.priorities->groups.entry[j]->q_bits;
249 				data_q = session->internals.priorities->groups.entry[j]->q->data;
250 				_n_q = session->internals.priorities->groups.entry[j]->q->size;
251 				break;
252 			}
253 		}
254 
255 		if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) {
256 			_gnutls_audit_log(session, "FFDHE groups advertised, but server didn't support it; falling back to server's choice\n");
257 		}
258 	}
259 
260 #ifdef ENABLE_FIPS140
261 	if (gnutls_fips140_mode_enabled() &&
262 	    !_gnutls_dh_prime_match_fips_approved(data_p, n_p, data_g, n_g, NULL, NULL)) {
263 		gnutls_assert();
264 		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
265 	}
266 #endif
267 
268 	if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.params.params[DH_G], data_g, _n_g) != 0) {
269 		gnutls_assert();
270 		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
271 	}
272 
273 	if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.params.params[DH_P], data_p, _n_p) != 0) {
274 		gnutls_assert();
275 		/* we release now because session->key.proto.tls12.dh.params.params_nr is not yet set */
276 		_gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]);
277 		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
278 	}
279 	if (data_q && _gnutls_mpi_init_scan_nz(
280 			    &session->key.proto.tls12.dh.params.params[DH_Q],
281 			    data_q, _n_q) != 0) {
282 		/* we release now because params_nr is not yet set */
283 		_gnutls_mpi_release(
284 			&session->key.proto.tls12.dh.params.params[DH_P]);
285 		_gnutls_mpi_release(
286 			&session->key.proto.tls12.dh.params.params[DH_G]);
287 		return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
288 	}
289 
290 	/* include, possibly empty, q */
291 	session->key.proto.tls12.dh.params.params_nr = 3;
292 	session->key.proto.tls12.dh.params.algo = GNUTLS_PK_DH;
293 
294 	if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) {
295 		bits = _gnutls_dh_get_min_prime_bits(session);
296 		if (bits < 0) {
297 			gnutls_assert();
298 			return bits;
299 		}
300 
301 		p_bits = _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_P]);
302 		if (p_bits < bits) {
303 			/* the prime used by the peer is not acceptable
304 			 */
305 			gnutls_assert();
306 			_gnutls_debug_log
307 			    ("Received a prime of %u bits, limit is %u\n",
308 			     (unsigned) _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_P]),
309 			     (unsigned) bits);
310 			return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
311 		}
312 
313 		if (p_bits >= DEFAULT_MAX_VERIFY_BITS) {
314 			gnutls_assert();
315 			_gnutls_debug_log
316 			    ("Received a prime of %u bits, limit is %u\n",
317 			     (unsigned) p_bits,
318 			     (unsigned) DEFAULT_MAX_VERIFY_BITS);
319 			return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
320 		}
321 	}
322 
323 	_gnutls_dh_save_group(session, session->key.proto.tls12.dh.params.params[DH_G],
324 			     session->key.proto.tls12.dh.params.params[DH_P]);
325 	_gnutls_dh_set_peer_public(session, session->key.proto.tls12.dh.client_Y);
326 
327 	ret = n_Y + n_p + n_g + 6;
328 
329 	return ret;
330 }
331 
332 int
_gnutls_dh_common_print_server_kx(gnutls_session_t session,gnutls_buffer_st * data)333 _gnutls_dh_common_print_server_kx(gnutls_session_t session,
334 				  gnutls_buffer_st * data)
335 {
336 	int ret;
337 	unsigned q_bits = session->key.proto.tls12.dh.params.qbits;
338 	unsigned init_pos = data->length;
339 
340 	if (q_bits < 192 && q_bits != 0) {
341 		gnutls_assert();
342 		_gnutls_debug_log("too small q_bits value for DH: %u\n", q_bits);
343 		q_bits = 0; /* auto-detect */
344 	}
345 
346 	/* Y=g^x mod p */
347 	ret =
348 	    _gnutls_pk_generate_keys(GNUTLS_PK_DH, q_bits,
349 				     &session->key.proto.tls12.dh.params, 1);
350 	if (ret < 0)
351 		return gnutls_assert_val(ret);
352 
353 	_gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_X]));
354 
355 	ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_P], 0);
356 	if (ret < 0) {
357 		gnutls_assert();
358 		goto cleanup;
359 	}
360 
361 	ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_G], 0);
362 	if (ret < 0) {
363 		gnutls_assert();
364 		goto cleanup;
365 	}
366 
367 	ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_Y], 0);
368 	if (ret < 0) {
369 		gnutls_assert();
370 		goto cleanup;
371 	}
372 
373 	ret = data->length - init_pos;
374 
375 cleanup:
376 	return ret;
377 }
378 
379 #endif
380