minor update to the fix.
[gnutls.git] / lib / ext_safe_renegotiation.c
blobc34d450ef236d3ac3278ef87bec9f64aedcf8bd4
1 /*
2 * Copyright (C) 2009, 2010 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 #include <gnutls_int.h>
26 #include <ext_safe_renegotiation.h>
27 #include <gnutls_errors.h>
30 static int _gnutls_sr_recv_params (gnutls_session_t state,
31 const opaque * data, size_t data_size);
32 static int _gnutls_sr_send_params (gnutls_session_t state,
33 opaque * data, size_t);
34 static void _gnutls_sr_deinit_data (extension_priv_data_t priv);
36 extension_entry_st ext_mod_sr = {
37 .name = "SAFE RENEGOTIATION",
38 .type = GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
39 .parse_type = GNUTLS_EXT_MANDATORY,
41 .recv_func = _gnutls_sr_recv_params,
42 .send_func = _gnutls_sr_send_params,
43 .pack_func = NULL,
44 .unpack_func = NULL,
45 .deinit_func = _gnutls_sr_deinit_data,
48 int
49 _gnutls_ext_sr_finished (gnutls_session_t session, void *vdata,
50 size_t vdata_size, int dir)
52 int ret;
53 sr_ext_st *priv;
54 extension_priv_data_t epriv;
56 if (session->internals.priorities.sr == SR_DISABLED)
58 return 0;
61 ret = _gnutls_ext_get_session_data (session,
62 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
63 &epriv);
64 if (ret < 0)
66 gnutls_assert ();
67 return ret;
69 priv = epriv.ptr;
71 /* Save data for safe renegotiation.
73 if (vdata_size > MAX_VERIFY_DATA_SIZE)
75 gnutls_assert ();
76 return GNUTLS_E_INTERNAL_ERROR;
79 if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) ||
80 (session->security_parameters.entity == GNUTLS_SERVER && dir == 1))
82 priv->client_verify_data_len = vdata_size;
83 memcpy (priv->client_verify_data, vdata, vdata_size);
85 else
87 priv->server_verify_data_len = vdata_size;
88 memcpy (priv->server_verify_data, vdata, vdata_size);
91 return 0;
94 int
95 _gnutls_ext_sr_verify (gnutls_session_t session)
97 int ret;
98 sr_ext_st *priv = NULL;
99 extension_priv_data_t epriv;
101 if (session->internals.priorities.sr == SR_DISABLED)
103 gnutls_assert ();
104 return 0;
107 ret = _gnutls_ext_get_session_data (session,
108 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
109 &epriv);
110 if (ret >= 0)
111 priv = epriv.ptr;
113 /* Safe renegotiation */
115 if (priv && priv->safe_renegotiation_received)
117 if ((priv->ri_extension_data_len < priv->client_verify_data_len) ||
118 (memcmp (priv->ri_extension_data,
119 priv->client_verify_data, priv->client_verify_data_len)))
121 gnutls_assert ();
122 _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
123 session);
124 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
127 if (session->security_parameters.entity == GNUTLS_CLIENT)
129 if ((priv->ri_extension_data_len !=
130 priv->client_verify_data_len + priv->server_verify_data_len) ||
131 memcmp (priv->ri_extension_data + priv->client_verify_data_len,
132 priv->server_verify_data,
133 priv->server_verify_data_len) != 0)
135 gnutls_assert ();
136 _gnutls_handshake_log
137 ("HSK[%p]: Safe renegotiation failed [2]\n", session);
138 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
141 else /* Make sure there are 0 extra bytes */
143 if (priv->ri_extension_data_len != priv->client_verify_data_len)
145 gnutls_assert ();
146 _gnutls_handshake_log
147 ("HSK[%p]: Safe renegotiation failed [3]\n", session);
148 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
152 _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
153 session);
155 else /* safe renegotiation not received... */
157 if (priv && priv->connection_using_safe_renegotiation)
159 gnutls_assert ();
160 _gnutls_handshake_log
161 ("HSK[%p]: Peer previously asked for safe renegotiation\n",
162 session);
163 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
166 /* Clients can't tell if it's an initial negotiation */
167 if (session->internals.initial_negotiation_completed)
169 if (session->internals.priorities.sr < SR_PARTIAL)
171 _gnutls_handshake_log
172 ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
174 else
176 gnutls_assert ();
177 _gnutls_handshake_log
178 ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
179 return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
182 else
184 if (session->internals.priorities.sr < SR_SAFE)
186 _gnutls_handshake_log
187 ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
189 else
191 gnutls_assert ();
192 _gnutls_handshake_log
193 ("HSK[%p]: Denying unsafe initial negotiation\n", session);
194 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
199 return 0;
202 /* if a server received the special ciphersuite.
205 _gnutls_ext_sr_recv_cs (gnutls_session_t session)
207 int ret, set = 0;
208 sr_ext_st *priv;
209 extension_priv_data_t epriv;
211 ret = _gnutls_ext_get_session_data (session,
212 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
213 &epriv);
214 if (ret < 0)
216 set = 1;
218 else if (ret < 0)
220 gnutls_assert ();
221 return ret;
224 if (set != 0)
226 priv = gnutls_calloc (1, sizeof (*priv));
227 if (priv == NULL)
229 gnutls_assert ();
230 return GNUTLS_E_MEMORY_ERROR;
232 epriv.ptr = priv;
234 else
235 priv = epriv.ptr;
237 priv->safe_renegotiation_received = 1;
238 priv->connection_using_safe_renegotiation = 1;
240 if (set != 0)
241 _gnutls_ext_set_session_data (session,
242 GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
244 return 0;
248 _gnutls_ext_sr_send_cs (gnutls_session_t session)
250 int ret, set = 0;
251 sr_ext_st *priv;
252 extension_priv_data_t epriv;
254 ret = _gnutls_ext_get_session_data (session,
255 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
256 &epriv);
257 if (ret < 0)
259 set = 1;
261 else if (ret < 0)
263 gnutls_assert ();
264 return ret;
267 if (set != 0)
269 priv = gnutls_calloc (1, sizeof (*priv));
270 if (priv == NULL)
272 gnutls_assert ();
273 return GNUTLS_E_MEMORY_ERROR;
275 epriv.ptr = priv;
277 else
278 priv = epriv.ptr;
280 if (set != 0)
281 _gnutls_ext_set_session_data (session,
282 GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
284 return 0;
287 static int
288 _gnutls_sr_recv_params (gnutls_session_t session,
289 const opaque * data, size_t _data_size)
291 int len = data[0];
292 ssize_t data_size = _data_size;
293 sr_ext_st *priv;
294 extension_priv_data_t epriv;
295 int set = 0, ret;
297 DECR_LEN (data_size, len + 1 /* count the first byte and payload */ );
299 if (session->internals.priorities.sr == SR_DISABLED)
301 gnutls_assert ();
302 return 0;
305 ret = _gnutls_ext_get_session_data (session,
306 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
307 &epriv);
308 if (ret < 0 && session->security_parameters.entity == GNUTLS_SERVER)
310 set = 1;
312 else if (ret < 0)
314 gnutls_assert ();
315 return ret;
318 if (set != 0)
320 priv = gnutls_calloc (1, sizeof (*priv));
321 if (priv == NULL)
323 gnutls_assert ();
324 return GNUTLS_E_MEMORY_ERROR;
326 epriv.ptr = priv;
328 else
329 priv = epriv.ptr;
331 /* It is not legal to receive this extension on a renegotiation and
332 * not receive it on the initial negotiation.
334 if (session->internals.initial_negotiation_completed != 0 &&
335 priv->connection_using_safe_renegotiation == 0)
337 gnutls_assert ();
338 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
341 if (len > sizeof (priv->ri_extension_data))
343 gnutls_assert ();
344 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
347 if (len > 0)
348 memcpy (priv->ri_extension_data, &data[1], len);
349 priv->ri_extension_data_len = len;
351 /* "safe renegotiation received" means on *this* handshake; "connection using
352 * safe renegotiation" means that the initial hello received on the connection
353 * indicated safe renegotiation.
355 priv->safe_renegotiation_received = 1;
356 priv->connection_using_safe_renegotiation = 1;
358 if (set != 0)
359 _gnutls_ext_set_session_data (session,
360 GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
361 return 0;
364 static int
365 _gnutls_sr_send_params (gnutls_session_t session,
366 opaque * data, size_t _data_size)
368 /* The format of this extension is a one-byte length of verify data followed
369 * by the verify data itself. Note that the length byte does not include
370 * itself; IOW, empty verify data is represented as a length of 0. That means
371 * the minimum extension is one byte: 0x00.
373 ssize_t data_size = _data_size;
374 sr_ext_st *priv;
375 int ret, set = 0;
376 extension_priv_data_t epriv;
378 if (session->internals.priorities.sr == SR_DISABLED)
380 gnutls_assert ();
381 return 0;
384 ret = _gnutls_ext_get_session_data (session,
385 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
386 &epriv);
387 if (ret < 0)
389 set = 1;
392 if (set != 0)
394 priv = gnutls_calloc (1, sizeof (*priv));
395 if (priv == NULL)
397 gnutls_assert ();
398 return GNUTLS_E_MEMORY_ERROR;
400 epriv.ptr = priv;
402 _gnutls_ext_set_session_data (session,
403 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
404 epriv);
406 else
407 priv = epriv.ptr;
409 data[0] = 0;
411 /* Always offer the extension if we're a client */
412 if (priv->connection_using_safe_renegotiation ||
413 session->security_parameters.entity == GNUTLS_CLIENT)
415 DECR_LEN (data_size, 1);
416 data[0] = priv->client_verify_data_len;
418 DECR_LEN (data_size, priv->client_verify_data_len);
420 if (priv->client_verify_data_len > 0)
421 memcpy (&data[1], priv->client_verify_data,
422 priv->client_verify_data_len);
424 if (session->security_parameters.entity == GNUTLS_SERVER)
426 data[0] += priv->server_verify_data_len;
428 DECR_LEN (data_size, priv->server_verify_data_len);
430 if (priv->server_verify_data_len > 0)
431 memcpy (&data[1 + priv->client_verify_data_len],
432 priv->server_verify_data, priv->server_verify_data_len);
435 else
436 return 0;
438 return 1 + data[0]; /* don't forget the length byte */
441 static void
442 _gnutls_sr_deinit_data (extension_priv_data_t priv)
444 gnutls_free (priv.ptr);
448 * gnutls_safe_renegotiation_status:
449 * @session: is a #gnutls_session_t structure.
451 * Can be used to check whether safe renegotiation is being used
452 * in the current session.
454 * Returns: 0 when safe renegotiation is not used and non zero when
455 * safe renegotiation is used.
457 * Since: 2.10.0
460 gnutls_safe_renegotiation_status (gnutls_session_t session)
462 int ret;
463 sr_ext_st *priv;
464 extension_priv_data_t epriv;
466 ret = _gnutls_ext_get_session_data (session,
467 GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
468 &epriv);
469 if (ret < 0)
471 gnutls_assert ();
472 return 0;
474 priv = epriv.ptr;
476 return priv->connection_using_safe_renegotiation;