corrected copyright notices
[gnutls.git] / lib / ext / safe_renegotiation.c
blob98629ef62a11309eb4b61bd215f63dc45fcaaffb
1 /*
2 * Copyright (C) 2009-2012 Free Software Foundation, Inc.
4 * Author: Steve Dispensa (<dispensa@phonefactor.com>)
6 * This file is part of GnuTLS.
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 3 of
11 * the License, or (at your option) any later version.
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.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <ext/safe_renegotiation.h>
25 #include <gnutls_errors.h>
28 static int _gnutls_sr_recv_params (gnutls_session_t state,
29 const uint8_t * data, size_t data_size);
30 static int _gnutls_sr_send_params (gnutls_session_t state, gnutls_buffer_st*);
31 static void _gnutls_sr_deinit_data (extension_priv_data_t priv);
33 extension_entry_st ext_mod_sr = {
34 .name = "SAFE RENEGOTIATION",
35 .type = GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
36 .parse_type = GNUTLS_EXT_MANDATORY,
38 .recv_func = _gnutls_sr_recv_params,
39 .send_func = _gnutls_sr_send_params,
40 .pack_func = NULL,
41 .unpack_func = NULL,
42 .deinit_func = _gnutls_sr_deinit_data,
45 int
46 _gnutls_ext_sr_finished (gnutls_session_t session, void *vdata,
47 size_t vdata_size, int dir)
49 int ret;
50 sr_ext_st *priv;
51 extension_priv_data_t epriv;
53 if (session->internals.priorities.sr == SR_DISABLED)
55 return 0;
58 ret = _gnutls_ext_get_session_data (session,
59 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
60 &epriv);
61 if (ret < 0)
63 gnutls_assert ();
64 return ret;
66 priv = epriv.ptr;
68 /* Save data for safe renegotiation.
70 if (vdata_size > MAX_VERIFY_DATA_SIZE)
72 gnutls_assert ();
73 return GNUTLS_E_INTERNAL_ERROR;
76 if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) ||
77 (session->security_parameters.entity == GNUTLS_SERVER && dir == 1))
79 priv->client_verify_data_len = vdata_size;
80 memcpy (priv->client_verify_data, vdata, vdata_size);
82 else
84 priv->server_verify_data_len = vdata_size;
85 memcpy (priv->server_verify_data, vdata, vdata_size);
88 return 0;
91 int
92 _gnutls_ext_sr_verify (gnutls_session_t session)
94 int ret;
95 sr_ext_st *priv = NULL;
96 extension_priv_data_t epriv;
98 if (session->internals.priorities.sr == SR_DISABLED)
100 gnutls_assert ();
101 return 0;
104 ret = _gnutls_ext_get_session_data (session,
105 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
106 &epriv);
107 if (ret >= 0)
108 priv = epriv.ptr;
110 /* Safe renegotiation */
112 if (priv && priv->safe_renegotiation_received)
114 if ((priv->ri_extension_data_len < priv->client_verify_data_len) ||
115 (memcmp (priv->ri_extension_data,
116 priv->client_verify_data, priv->client_verify_data_len)))
118 gnutls_assert ();
119 _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
120 session);
121 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
124 if (session->security_parameters.entity == GNUTLS_CLIENT)
126 if ((priv->ri_extension_data_len !=
127 priv->client_verify_data_len + priv->server_verify_data_len) ||
128 memcmp (priv->ri_extension_data + priv->client_verify_data_len,
129 priv->server_verify_data,
130 priv->server_verify_data_len) != 0)
132 gnutls_assert ();
133 _gnutls_handshake_log
134 ("HSK[%p]: Safe renegotiation failed [2]\n", session);
135 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
138 else /* Make sure there are 0 extra bytes */
140 if (priv->ri_extension_data_len != priv->client_verify_data_len)
142 gnutls_assert ();
143 _gnutls_handshake_log
144 ("HSK[%p]: Safe renegotiation failed [3]\n", session);
145 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
149 _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
150 session);
152 else /* safe renegotiation not received... */
154 if (priv && priv->connection_using_safe_renegotiation)
156 gnutls_assert ();
157 _gnutls_handshake_log
158 ("HSK[%p]: Peer previously asked for safe renegotiation\n",
159 session);
160 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
163 /* Clients can't tell if it's an initial negotiation */
164 if (session->internals.initial_negotiation_completed)
166 if (session->internals.priorities.sr < SR_PARTIAL)
168 _gnutls_handshake_log
169 ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
171 else
173 gnutls_assert ();
174 _gnutls_handshake_log
175 ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
176 return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
179 else
181 if (session->internals.priorities.sr < SR_SAFE)
183 _gnutls_handshake_log
184 ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
186 else
188 gnutls_assert ();
189 _gnutls_handshake_log
190 ("HSK[%p]: Denying unsafe initial negotiation\n", session);
191 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
196 return 0;
199 /* if a server received the special ciphersuite.
202 _gnutls_ext_sr_recv_cs (gnutls_session_t session)
204 int ret, set = 0;
205 sr_ext_st *priv;
206 extension_priv_data_t epriv;
208 ret = _gnutls_ext_get_session_data (session,
209 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
210 &epriv);
211 if (ret < 0)
213 set = 1;
215 else if (ret < 0)
217 gnutls_assert ();
218 return ret;
221 if (set != 0)
223 priv = gnutls_calloc (1, sizeof (*priv));
224 if (priv == NULL)
226 gnutls_assert ();
227 return GNUTLS_E_MEMORY_ERROR;
229 epriv.ptr = priv;
231 else
232 priv = epriv.ptr;
234 priv->safe_renegotiation_received = 1;
235 priv->connection_using_safe_renegotiation = 1;
237 if (set != 0)
238 _gnutls_ext_set_session_data (session,
239 GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
241 return 0;
245 _gnutls_ext_sr_send_cs (gnutls_session_t session)
247 int ret, set = 0;
248 sr_ext_st *priv;
249 extension_priv_data_t epriv;
251 ret = _gnutls_ext_get_session_data (session,
252 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
253 &epriv);
254 if (ret < 0)
256 set = 1;
258 else if (ret < 0)
260 gnutls_assert ();
261 return ret;
264 if (set != 0)
266 priv = gnutls_calloc (1, sizeof (*priv));
267 if (priv == NULL)
269 gnutls_assert ();
270 return GNUTLS_E_MEMORY_ERROR;
272 epriv.ptr = priv;
275 if (set != 0)
276 _gnutls_ext_set_session_data (session,
277 GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
279 return 0;
282 static int
283 _gnutls_sr_recv_params (gnutls_session_t session,
284 const uint8_t * data, size_t _data_size)
286 unsigned int len = data[0];
287 ssize_t data_size = _data_size;
288 sr_ext_st *priv;
289 extension_priv_data_t epriv;
290 int set = 0, ret;
292 DECR_LEN (data_size, len + 1 /* count the first byte and payload */ );
294 if (session->internals.priorities.sr == SR_DISABLED)
296 gnutls_assert ();
297 return 0;
300 ret = _gnutls_ext_get_session_data (session,
301 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
302 &epriv);
303 if (ret < 0 && session->security_parameters.entity == GNUTLS_SERVER)
305 set = 1;
307 else if (ret < 0)
309 gnutls_assert ();
310 return ret;
313 if (set != 0)
315 priv = gnutls_calloc (1, sizeof (*priv));
316 if (priv == NULL)
318 gnutls_assert ();
319 return GNUTLS_E_MEMORY_ERROR;
321 epriv.ptr = priv;
323 else
324 priv = epriv.ptr;
326 /* It is not legal to receive this extension on a renegotiation and
327 * not receive it on the initial negotiation.
329 if (session->internals.initial_negotiation_completed != 0 &&
330 priv->connection_using_safe_renegotiation == 0)
332 gnutls_assert ();
333 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
336 if (len > sizeof (priv->ri_extension_data))
338 gnutls_assert ();
339 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
342 if (len > 0)
343 memcpy (priv->ri_extension_data, &data[1], len);
344 priv->ri_extension_data_len = len;
346 /* "safe renegotiation received" means on *this* handshake; "connection using
347 * safe renegotiation" means that the initial hello received on the connection
348 * indicated safe renegotiation.
350 priv->safe_renegotiation_received = 1;
351 priv->connection_using_safe_renegotiation = 1;
353 if (set != 0)
354 _gnutls_ext_set_session_data (session,
355 GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
356 return 0;
359 static int
360 _gnutls_sr_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
362 /* The format of this extension is a one-byte length of verify data followed
363 * by the verify data itself. Note that the length byte does not include
364 * itself; IOW, empty verify data is represented as a length of 0. That means
365 * the minimum extension is one byte: 0x00.
367 sr_ext_st *priv;
368 int ret, set = 0, len;
369 extension_priv_data_t epriv;
370 size_t init_length = extdata->length;
372 if (session->internals.priorities.sr == SR_DISABLED)
374 gnutls_assert ();
375 return 0;
378 ret = _gnutls_ext_get_session_data (session,
379 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
380 &epriv);
381 if (ret < 0)
383 set = 1;
386 if (set != 0)
388 priv = gnutls_calloc (1, sizeof (*priv));
389 if (priv == NULL)
391 gnutls_assert ();
392 return GNUTLS_E_MEMORY_ERROR;
394 epriv.ptr = priv;
396 _gnutls_ext_set_session_data (session,
397 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
398 epriv);
400 else
401 priv = epriv.ptr;
403 /* Always offer the extension if we're a client */
404 if (priv->connection_using_safe_renegotiation ||
405 session->security_parameters.entity == GNUTLS_CLIENT)
407 len = priv->client_verify_data_len;
408 if (session->security_parameters.entity == GNUTLS_SERVER)
409 len += priv->server_verify_data_len;
411 ret = _gnutls_buffer_append_prefix(extdata, 8, len);
412 if (ret < 0)
413 return gnutls_assert_val(ret);
415 ret = _gnutls_buffer_append_data(extdata, priv->client_verify_data,
416 priv->client_verify_data_len);
417 if (ret < 0)
418 return gnutls_assert_val(ret);
420 if (session->security_parameters.entity == GNUTLS_SERVER)
422 ret = _gnutls_buffer_append_data(extdata, priv->server_verify_data,
423 priv->server_verify_data_len);
424 if (ret < 0)
425 return gnutls_assert_val(ret);
428 else
429 return 0;
431 return extdata->length - init_length;
434 static void
435 _gnutls_sr_deinit_data (extension_priv_data_t priv)
437 gnutls_free (priv.ptr);
441 * gnutls_safe_renegotiation_status:
442 * @session: is a #gnutls_session_t structure.
444 * Can be used to check whether safe renegotiation is being used
445 * in the current session.
447 * Returns: 0 when safe renegotiation is not used and non (0) when
448 * safe renegotiation is used.
450 * Since: 2.10.0
453 gnutls_safe_renegotiation_status (gnutls_session_t session)
455 int ret;
456 sr_ext_st *priv;
457 extension_priv_data_t epriv;
459 ret = _gnutls_ext_get_session_data (session,
460 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
461 &epriv);
462 if (ret < 0)
464 gnutls_assert ();
465 return 0;
467 priv = epriv.ptr;
469 return priv->connection_using_safe_renegotiation;