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
,
42 .deinit_func
= _gnutls_sr_deinit_data
,
46 _gnutls_ext_sr_finished (gnutls_session_t session
, void *vdata
,
47 size_t vdata_size
, int dir
)
51 extension_priv_data_t epriv
;
53 if (session
->internals
.priorities
.sr
== SR_DISABLED
)
58 ret
= _gnutls_ext_get_session_data (session
,
59 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
68 /* Save data for safe renegotiation.
70 if (vdata_size
> MAX_VERIFY_DATA_SIZE
)
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
);
84 priv
->server_verify_data_len
= vdata_size
;
85 memcpy (priv
->server_verify_data
, vdata
, vdata_size
);
92 _gnutls_ext_sr_verify (gnutls_session_t session
)
95 sr_ext_st
*priv
= NULL
;
96 extension_priv_data_t epriv
;
98 if (session
->internals
.priorities
.sr
== SR_DISABLED
)
104 ret
= _gnutls_ext_get_session_data (session
,
105 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
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
)))
119 _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
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)
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
)
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",
152 else /* safe renegotiation not received... */
154 if (priv
&& priv
->connection_using_safe_renegotiation
)
157 _gnutls_handshake_log
158 ("HSK[%p]: Peer previously asked for safe renegotiation\n",
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
);
174 _gnutls_handshake_log
175 ("HSK[%p]: Denying unsafe (re)negotiation\n", session
);
176 return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED
;
181 if (session
->internals
.priorities
.sr
< SR_SAFE
)
183 _gnutls_handshake_log
184 ("HSK[%p]: Allowing unsafe initial negotiation\n", session
);
189 _gnutls_handshake_log
190 ("HSK[%p]: Denying unsafe initial negotiation\n", session
);
191 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED
;
199 /* if a server received the special ciphersuite.
202 _gnutls_ext_sr_recv_cs (gnutls_session_t session
)
206 extension_priv_data_t epriv
;
208 ret
= _gnutls_ext_get_session_data (session
,
209 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
223 priv
= gnutls_calloc (1, sizeof (*priv
));
227 return GNUTLS_E_MEMORY_ERROR
;
234 priv
->safe_renegotiation_received
= 1;
235 priv
->connection_using_safe_renegotiation
= 1;
238 _gnutls_ext_set_session_data (session
,
239 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
, epriv
);
245 _gnutls_ext_sr_send_cs (gnutls_session_t session
)
249 extension_priv_data_t epriv
;
251 ret
= _gnutls_ext_get_session_data (session
,
252 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
266 priv
= gnutls_calloc (1, sizeof (*priv
));
270 return GNUTLS_E_MEMORY_ERROR
;
276 _gnutls_ext_set_session_data (session
,
277 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
, epriv
);
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
;
289 extension_priv_data_t epriv
;
292 DECR_LEN (data_size
, len
+ 1 /* count the first byte and payload */ );
294 if (session
->internals
.priorities
.sr
== SR_DISABLED
)
300 ret
= _gnutls_ext_get_session_data (session
,
301 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
303 if (ret
< 0 && session
->security_parameters
.entity
== GNUTLS_SERVER
)
315 priv
= gnutls_calloc (1, sizeof (*priv
));
319 return GNUTLS_E_MEMORY_ERROR
;
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)
333 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED
;
336 if (len
> sizeof (priv
->ri_extension_data
))
339 return GNUTLS_E_SAFE_RENEGOTIATION_FAILED
;
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;
354 _gnutls_ext_set_session_data (session
,
355 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
, epriv
);
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.
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
)
378 ret
= _gnutls_ext_get_session_data (session
,
379 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
388 priv
= gnutls_calloc (1, sizeof (*priv
));
392 return GNUTLS_E_MEMORY_ERROR
;
396 _gnutls_ext_set_session_data (session
,
397 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
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
);
413 return gnutls_assert_val(ret
);
415 ret
= _gnutls_buffer_append_data(extdata
, priv
->client_verify_data
,
416 priv
->client_verify_data_len
);
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
);
425 return gnutls_assert_val(ret
);
431 return extdata
->length
- init_length
;
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.
453 gnutls_safe_renegotiation_status (gnutls_session_t session
)
457 extension_priv_data_t epriv
;
459 ret
= _gnutls_ext_get_session_data (session
,
460 GNUTLS_EXTENSION_SAFE_RENEGOTIATION
,
469 return priv
->connection_using_safe_renegotiation
;