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,
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
,
45 .deinit_func
= _gnutls_sr_deinit_data
,
49 _gnutls_ext_sr_finished (gnutls_session_t session
, void *vdata
,
50 size_t vdata_size
, int dir
)
54 extension_priv_data_t epriv
;
56 if (session
->internals
.priorities
.sr
== SR_DISABLED
)
61 ret
= _gnutls_ext_get_session_data (session
,
62 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
71 /* Save data for safe renegotiation.
73 if (vdata_size
> MAX_VERIFY_DATA_SIZE
)
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
);
87 priv
->server_verify_data_len
= vdata_size
;
88 memcpy (priv
->server_verify_data
, vdata
, vdata_size
);
95 _gnutls_ext_sr_verify (gnutls_session_t session
)
98 sr_ext_st
*priv
= NULL
;
99 extension_priv_data_t epriv
;
101 if (session
->internals
.priorities
.sr
== SR_DISABLED
)
107 ret
= _gnutls_ext_get_session_data (session
,
108 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
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
)))
122 _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
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)
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
)
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",
155 else /* safe renegotiation not received... */
157 if (priv
&& priv
->connection_using_safe_renegotiation
)
160 _gnutls_handshake_log
161 ("HSK[%p]: Peer previously asked for safe renegotiation\n",
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
);
177 _gnutls_handshake_log
178 ("HSK[%p]: Denying unsafe (re)negotiation\n", session
);
179 return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED
;
184 if (session
->internals
.priorities
.sr
< SR_SAFE
)
186 _gnutls_handshake_log
187 ("HSK[%p]: Allowing unsafe initial negotiation\n", session
);
192 _gnutls_handshake_log
193 ("HSK[%p]: Denying unsafe initial negotiation\n", session
);
194 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED
;
202 /* if a server received the special ciphersuite.
205 _gnutls_ext_sr_recv_cs (gnutls_session_t session
)
209 extension_priv_data_t epriv
;
211 ret
= _gnutls_ext_get_session_data (session
,
212 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
226 priv
= gnutls_calloc (1, sizeof (*priv
));
230 return GNUTLS_E_MEMORY_ERROR
;
237 priv
->safe_renegotiation_received
= 1;
238 priv
->connection_using_safe_renegotiation
= 1;
241 _gnutls_ext_set_session_data (session
,
242 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
, epriv
);
248 _gnutls_ext_sr_send_cs (gnutls_session_t session
)
252 extension_priv_data_t epriv
;
254 ret
= _gnutls_ext_get_session_data (session
,
255 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
269 priv
= gnutls_calloc (1, sizeof (*priv
));
273 return GNUTLS_E_MEMORY_ERROR
;
281 _gnutls_ext_set_session_data (session
,
282 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
, epriv
);
288 _gnutls_sr_recv_params (gnutls_session_t session
,
289 const opaque
* data
, size_t _data_size
)
292 ssize_t data_size
= _data_size
;
294 extension_priv_data_t epriv
;
297 DECR_LEN (data_size
, len
+ 1 /* count the first byte and payload */ );
299 if (session
->internals
.priorities
.sr
== SR_DISABLED
)
305 ret
= _gnutls_ext_get_session_data (session
,
306 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
308 if (ret
< 0 && session
->security_parameters
.entity
== GNUTLS_SERVER
)
320 priv
= gnutls_calloc (1, sizeof (*priv
));
324 return GNUTLS_E_MEMORY_ERROR
;
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)
338 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED
;
341 if (len
> sizeof (priv
->ri_extension_data
))
344 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED
;
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;
359 _gnutls_ext_set_session_data (session
,
360 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
, epriv
);
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
;
376 extension_priv_data_t epriv
;
378 if (session
->internals
.priorities
.sr
== SR_DISABLED
)
384 ret
= _gnutls_ext_get_session_data (session
,
385 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
394 priv
= gnutls_calloc (1, sizeof (*priv
));
398 return GNUTLS_E_MEMORY_ERROR
;
402 _gnutls_ext_set_session_data (session
,
403 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
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
);
438 return 1 + data
[0]; /* don't forget the length byte */
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.
460 gnutls_safe_renegotiation_status (gnutls_session_t session
)
464 extension_priv_data_t epriv
;
466 ret
= _gnutls_ext_get_session_data (session
,
467 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
476 return priv
->connection_using_safe_renegotiation
;