1 /*
2  * Copyright (C) 2000-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 the RSA key exchange part of the certificate
24  * authentication.
25  */
26 
27 #include "gnutls_int.h"
28 #include "auth.h"
29 #include "errors.h"
30 #include "dh.h"
31 #include "num.h"
32 #include "datum.h"
33 #include <auth/cert.h>
34 #include <pk.h>
35 #include <algorithms.h>
36 #include <global.h>
37 #include "debug.h"
38 #include <tls-sig.h>
39 #include <x509.h>
40 #include <random.h>
41 #include <mpi.h>
42 #include <abstract_int.h>
43 #include <auth/rsa_common.h>
44 
45 int _gnutls_gen_rsa_client_kx(gnutls_session_t, gnutls_buffer_st *);
46 static int proc_rsa_client_kx(gnutls_session_t, uint8_t *, size_t);
47 
48 const mod_auth_st rsa_auth_struct = {
49 	"RSA",
50 	_gnutls_gen_cert_server_crt,
51 	_gnutls_gen_cert_client_crt,
52 	NULL,			/* gen server kx */
53 	_gnutls_gen_rsa_client_kx,
54 	_gnutls_gen_cert_client_crt_vrfy,	/* gen client cert vrfy */
55 	_gnutls_gen_cert_server_cert_req,	/* server cert request */
56 
57 	_gnutls_proc_crt,
58 	_gnutls_proc_crt,
59 	NULL,			/* proc server kx */
60 	proc_rsa_client_kx,	/* proc client kx */
61 	_gnutls_proc_cert_client_crt_vrfy,	/* proc client cert vrfy */
62 	_gnutls_proc_cert_cert_req	/* proc server cert request */
63 };
64 
65 static
check_key_usage_for_enc(gnutls_session_t session,unsigned key_usage)66 int check_key_usage_for_enc(gnutls_session_t session, unsigned key_usage)
67 {
68 	if (key_usage != 0) {
69 		if (!(key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT) && !(key_usage & GNUTLS_KEY_KEY_AGREEMENT)) {
70 			gnutls_assert();
71 			if (session->internals.allow_key_usage_violation == 0) {
72 				_gnutls_audit_log(session,
73 					  "Peer's certificate does not allow encryption. Key usage violation detected.\n");
74 				return GNUTLS_E_KEY_USAGE_VIOLATION;
75 			} else {
76 				_gnutls_audit_log(session,
77 					  "Peer's certificate does not allow encryption. Key usage violation detected (ignored).\n");
78 			}
79 		}
80 	}
81 	return 0;
82 }
83 
84 /* This function reads the RSA parameters from peer's certificate;
85  *
86  * IMPORTANT:
87  * Currently this function gets only called on the client side
88  * during generation of the client kx msg. This function
89  * retrieves the RSA params from the peer's certificate. That is in
90  * this case the server's certificate. As of GNUTLS version 3.6.4 it is
91  * possible to negotiate different certificate types for client and
92  * server. Therefore the correct cert type needs to be retrieved to be
93  * used for the _gnutls_get_auth_info_pcert call. If this
94  * function is to be called on the server side in the future, extra
95  * checks need to be build in order to retrieve the correct
96  * certificate type.
97  */
98 int
_gnutls_get_public_rsa_params(gnutls_session_t session,gnutls_pk_params_st * params)99 _gnutls_get_public_rsa_params(gnutls_session_t session,
100 			      gnutls_pk_params_st * params)
101 {
102 	int ret;
103 	cert_auth_info_t info;
104 	unsigned key_usage;
105 	gnutls_pcert_st peer_cert;
106 	gnutls_certificate_type_t cert_type;
107 
108 	assert(!IS_SERVER(session));
109 
110 	/* normal non export case */
111 
112 	info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
113 
114 	if (info == NULL || info->ncerts == 0) {
115 		gnutls_assert();
116 		return GNUTLS_E_INTERNAL_ERROR;
117 	}
118 
119 	// Get the negotiated server certificate type
120 	cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER);
121 
122 	ret = _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info);
123 
124 	if (ret < 0) {
125 		gnutls_assert();
126 		return ret;
127 	}
128 
129 	gnutls_pubkey_get_key_usage(peer_cert.pubkey, &key_usage);
130 
131 	ret = check_key_usage_for_enc(session, key_usage);
132 	if (ret < 0) {
133 		gnutls_assert();
134 		goto cleanup2;
135 	}
136 
137 	gnutls_pk_params_init(params);
138 
139 	ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params);
140 	if (ret < 0) {
141 		ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
142 		goto cleanup2;
143 	}
144 
145 	gnutls_pcert_deinit(&peer_cert);
146 	return 0;
147 
148       cleanup2:
149 	gnutls_pcert_deinit(&peer_cert);
150 
151 	return ret;
152 }
153 
154 static int
proc_rsa_client_kx(gnutls_session_t session,uint8_t * data,size_t _data_size)155 proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
156 		   size_t _data_size)
157 {
158 	const char attack_error[] = "auth_rsa: Possible PKCS #1 attack\n";
159 	gnutls_datum_t ciphertext;
160 	int ret, dsize;
161 	ssize_t data_size = _data_size;
162 	volatile uint8_t ver_maj, ver_min;
163 	volatile uint8_t check_ver_min;
164 	volatile uint32_t ok;
165 
166 #ifdef ENABLE_SSL3
167 	if (get_num_version(session) == GNUTLS_SSL3) {
168 		/* SSL 3.0
169 		 */
170 		ciphertext.data = data;
171 		ciphertext.size = data_size;
172 	} else
173 #endif
174 	{
175 		/* TLS 1.0+
176 		 */
177 		DECR_LEN(data_size, 2);
178 		ciphertext.data = &data[2];
179 		dsize = _gnutls_read_uint16(data);
180 
181 		if (dsize != data_size) {
182 			gnutls_assert();
183 			return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
184 		}
185 		ciphertext.size = dsize;
186 	}
187 
188 	ver_maj = _gnutls_get_adv_version_major(session);
189 	ver_min = _gnutls_get_adv_version_minor(session);
190 	check_ver_min = (session->internals.allow_wrong_pms == 0);
191 
192 	session->key.key.data = gnutls_malloc(GNUTLS_MASTER_SIZE);
193 	if (session->key.key.data == NULL) {
194 		gnutls_assert();
195 		return GNUTLS_E_MEMORY_ERROR;
196 	}
197 	session->key.key.size = GNUTLS_MASTER_SIZE;
198 
199 	/* Fallback value when decryption fails. Needs to be unpredictable. */
200 	ret = gnutls_rnd(GNUTLS_RND_NONCE, session->key.key.data,
201 			 GNUTLS_MASTER_SIZE);
202 	if (ret < 0) {
203 		gnutls_free(session->key.key.data);
204 		session->key.key.size = 0;
205 		gnutls_assert();
206 		return ret;
207 	}
208 
209 	ret =
210 	    gnutls_privkey_decrypt_data2(session->internals.selected_key,
211 					 0, &ciphertext, session->key.key.data,
212 					 session->key.key.size);
213 	/* After this point, any conditional on failure that cause differences
214 	 * in execution may create a timing or cache access pattern side
215 	 * channel that can be used as an oracle, so treat very carefully */
216 
217 	/* Error handling logic:
218 	 * In case decryption fails then don't inform the peer. Just use the
219 	 * random key previously generated. (in order to avoid attack against
220 	 * pkcs-1 formatting).
221 	 *
222 	 * If we get version mismatches no error is returned either. We
223 	 * proceed normally. This is to defend against the attack described
224 	 * in the paper "Attacking RSA-based sessions in SSL/TLS" by
225 	 * Vlastimil Klima, Ondej Pokorny and Tomas Rosa.
226 	 */
227 
228 	/* ok is 0 in case of error and 1 in case of success. */
229 
230 	/* if ret < 0 */
231 	ok = CONSTCHECK_EQUAL(ret, 0);
232 	/* session->key.key.data[0] must equal ver_maj */
233 	ok &= CONSTCHECK_EQUAL(session->key.key.data[0], ver_maj);
234 	/* if check_ver_min then session->key.key.data[1] must equal ver_min */
235 	ok &= CONSTCHECK_NOT_EQUAL(check_ver_min, 0) &
236 	        CONSTCHECK_EQUAL(session->key.key.data[1], ver_min);
237 
238 	if (ok) {
239 		/* call logging function unconditionally so all branches are
240 		 * indistinguishable for timing and cache access when debug
241 		 * logging is disabled */
242 		_gnutls_no_log("%s", attack_error);
243 	} else {
244 		_gnutls_debug_log("%s", attack_error);
245 	}
246 
247 	/* This is here to avoid the version check attack
248 	 * discussed above.
249 	 */
250 	session->key.key.data[0] = ver_maj;
251 	session->key.key.data[1] = ver_min;
252 
253 	return 0;
254 }
255 
256 
257 
258 /* return RSA(random) using the peers public key
259  */
260 int
_gnutls_gen_rsa_client_kx(gnutls_session_t session,gnutls_buffer_st * data)261 _gnutls_gen_rsa_client_kx(gnutls_session_t session,
262 			  gnutls_buffer_st * data)
263 {
264 	cert_auth_info_t auth = session->key.auth_info;
265 	gnutls_datum_t sdata;	/* data to send */
266 	gnutls_pk_params_st params;
267 	int ret;
268 
269 	if (auth == NULL) {
270 		/* this shouldn't have happened. The proc_certificate
271 		 * function should have detected that.
272 		 */
273 		gnutls_assert();
274 		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
275 	}
276 
277 	session->key.key.size = GNUTLS_MASTER_SIZE;
278 	session->key.key.data = gnutls_malloc(session->key.key.size);
279 
280 	if (session->key.key.data == NULL) {
281 		gnutls_assert();
282 		return GNUTLS_E_MEMORY_ERROR;
283 	}
284 
285 	ret = gnutls_rnd(GNUTLS_RND_RANDOM, session->key.key.data,
286 			  session->key.key.size);
287 	if (ret < 0) {
288 		gnutls_assert();
289 		return ret;
290 	}
291 
292 	if (session->internals.rsa_pms_version[0] == 0) {
293 		session->key.key.data[0] =
294 		    _gnutls_get_adv_version_major(session);
295 		session->key.key.data[1] =
296 		    _gnutls_get_adv_version_minor(session);
297 	} else {		/* use the version provided */
298 		session->key.key.data[0] =
299 		    session->internals.rsa_pms_version[0];
300 		session->key.key.data[1] =
301 		    session->internals.rsa_pms_version[1];
302 	}
303 
304 	/* move RSA parameters to key (session).
305 	 */
306 	if ((ret = _gnutls_get_public_rsa_params(session, &params)) < 0) {
307 		gnutls_assert();
308 		return ret;
309 	}
310 
311 	ret =
312 	    _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &session->key.key,
313 			       &params);
314 
315 	gnutls_pk_params_release(&params);
316 
317 	if (ret < 0)
318 		return gnutls_assert_val(ret);
319 
320 
321 #ifdef ENABLE_SSL3
322 	if (get_num_version(session) == GNUTLS_SSL3) {
323 		/* SSL 3.0 */
324 		ret =
325 		    _gnutls_buffer_append_data(data, sdata.data,
326 					       sdata.size);
327 
328 		_gnutls_free_datum(&sdata);
329 		return ret;
330 	} else
331 #endif
332 	{		/* TLS 1.x */
333 		ret =
334 		    _gnutls_buffer_append_data_prefix(data, 16, sdata.data,
335 						      sdata.size);
336 
337 		_gnutls_free_datum(&sdata);
338 		return ret;
339 	}
340 }
341