Tizen 2.0 Release
[external/libgnutls26.git] / lib / ext_safe_renegotiation.c
1 /*
2  * Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3  *
4  * Author: Steve Dispensa (<dispensa@phonefactor.com>)
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
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
22  *
23  */
24
25 #include <gnutls_int.h>
26 #include <ext_safe_renegotiation.h>
27 #include <gnutls_errors.h>
28
29
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);
35
36 extension_entry_st ext_mod_sr = {
37   .name = "SAFE RENEGOTIATION",
38   .type = GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
39   .parse_type = GNUTLS_EXT_MANDATORY,
40
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,
46 };
47
48 int
49 _gnutls_ext_sr_finished (gnutls_session_t session, void *vdata,
50                          size_t vdata_size, int dir)
51 {
52   int ret;
53   sr_ext_st *priv;
54   extension_priv_data_t epriv;
55
56   if (session->internals.priorities.sr == SR_DISABLED)
57     {
58       return 0;
59     }
60
61   ret = _gnutls_ext_get_session_data (session,
62                                       GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
63                                       &epriv);
64   if (ret < 0)
65     {
66       gnutls_assert ();
67       return ret;
68     }
69   priv = epriv.ptr;
70
71   /* Save data for safe renegotiation. 
72    */
73   if (vdata_size > MAX_VERIFY_DATA_SIZE)
74     {
75       gnutls_assert ();
76       return GNUTLS_E_INTERNAL_ERROR;
77     }
78
79   if ((session->security_parameters.entity == GNUTLS_CLIENT && dir == 0) ||
80       (session->security_parameters.entity == GNUTLS_SERVER && dir == 1))
81     {
82       priv->client_verify_data_len = vdata_size;
83       memcpy (priv->client_verify_data, vdata, vdata_size);
84     }
85   else
86     {
87       priv->server_verify_data_len = vdata_size;
88       memcpy (priv->server_verify_data, vdata, vdata_size);
89     }
90
91   return 0;
92 }
93
94 int
95 _gnutls_ext_sr_verify (gnutls_session_t session)
96 {
97   int ret;
98   sr_ext_st *priv = NULL;
99   extension_priv_data_t epriv;
100
101   if (session->internals.priorities.sr == SR_DISABLED)
102     {
103       gnutls_assert ();
104       return 0;
105     }
106
107   ret = _gnutls_ext_get_session_data (session,
108                                       GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
109                                       &epriv);
110   if (ret >= 0)
111     priv = epriv.ptr;
112
113   /* Safe renegotiation */
114
115   if (priv && priv->safe_renegotiation_received)
116     {
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)))
120         {
121           gnutls_assert ();
122           _gnutls_handshake_log ("HSK[%p]: Safe renegotiation failed [1]\n",
123                                  session);
124           return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
125         }
126
127       if (session->security_parameters.entity == GNUTLS_CLIENT)
128         {
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)
134             {
135               gnutls_assert ();
136               _gnutls_handshake_log
137                 ("HSK[%p]: Safe renegotiation failed [2]\n", session);
138               return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
139             }
140         }
141       else                      /* Make sure there are 0 extra bytes */
142         {
143           if (priv->ri_extension_data_len != priv->client_verify_data_len)
144             {
145               gnutls_assert ();
146               _gnutls_handshake_log
147                 ("HSK[%p]: Safe renegotiation failed [3]\n", session);
148               return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
149             }
150         }
151
152       _gnutls_handshake_log ("HSK[%p]: Safe renegotiation succeeded\n",
153                              session);
154     }
155   else                          /* safe renegotiation not received... */
156     {
157       if (priv && priv->connection_using_safe_renegotiation)
158         {
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;
164         }
165
166       /* Clients can't tell if it's an initial negotiation */
167       if (session->internals.initial_negotiation_completed)
168         {
169           if (session->internals.priorities.sr < SR_PARTIAL)
170             {
171               _gnutls_handshake_log
172                 ("HSK[%p]: Allowing unsafe (re)negotiation\n", session);
173             }
174           else
175             {
176               gnutls_assert ();
177               _gnutls_handshake_log
178                 ("HSK[%p]: Denying unsafe (re)negotiation\n", session);
179               return GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED;
180             }
181         }
182       else
183         {
184           if (session->internals.priorities.sr < SR_SAFE)
185             {
186               _gnutls_handshake_log
187                 ("HSK[%p]: Allowing unsafe initial negotiation\n", session);
188             }
189           else
190             {
191               gnutls_assert ();
192               _gnutls_handshake_log
193                 ("HSK[%p]: Denying unsafe initial negotiation\n", session);
194               return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
195             }
196         }
197     }
198
199   return 0;
200 }
201
202 /* if a server received the special ciphersuite.
203  */
204 int
205 _gnutls_ext_sr_recv_cs (gnutls_session_t session)
206 {
207   int ret, set = 0;
208   sr_ext_st *priv;
209   extension_priv_data_t epriv;
210
211   ret = _gnutls_ext_get_session_data (session,
212                                       GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
213                                       &epriv);
214   if (ret < 0)
215     {
216       set = 1;
217     }
218   else if (ret < 0)
219     {
220       gnutls_assert ();
221       return ret;
222     }
223
224   if (set != 0)
225     {
226       priv = gnutls_calloc (1, sizeof (*priv));
227       if (priv == NULL)
228         {
229           gnutls_assert ();
230           return GNUTLS_E_MEMORY_ERROR;
231         }
232       epriv.ptr = priv;
233     }
234   else
235     priv = epriv.ptr;
236
237   priv->safe_renegotiation_received = 1;
238   priv->connection_using_safe_renegotiation = 1;
239
240   if (set != 0)
241     _gnutls_ext_set_session_data (session,
242                                   GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
243
244   return 0;
245 }
246
247 int
248 _gnutls_ext_sr_send_cs (gnutls_session_t session)
249 {
250   int ret, set = 0;
251   sr_ext_st *priv;
252   extension_priv_data_t epriv;
253
254   ret = _gnutls_ext_get_session_data (session,
255                                       GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
256                                       &epriv);
257   if (ret < 0)
258     {
259       set = 1;
260     }
261   else if (ret < 0)
262     {
263       gnutls_assert ();
264       return ret;
265     }
266
267   if (set != 0)
268     {
269       priv = gnutls_calloc (1, sizeof (*priv));
270       if (priv == NULL)
271         {
272           gnutls_assert ();
273           return GNUTLS_E_MEMORY_ERROR;
274         }
275       epriv.ptr = priv;
276     }
277   else
278     priv = epriv.ptr;
279
280   if (set != 0)
281     _gnutls_ext_set_session_data (session,
282                                   GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
283
284   return 0;
285 }
286
287 static int
288 _gnutls_sr_recv_params (gnutls_session_t session,
289                         const opaque * data, size_t _data_size)
290 {
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;
296
297   DECR_LEN (data_size, len + 1 /* count the first byte and payload */ );
298
299   if (session->internals.priorities.sr == SR_DISABLED)
300     {
301       gnutls_assert ();
302       return 0;
303     }
304
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)
309     {
310       set = 1;
311     }
312   else if (ret < 0)
313     {
314       gnutls_assert ();
315       return ret;
316     }
317
318   if (set != 0)
319     {
320       priv = gnutls_calloc (1, sizeof (*priv));
321       if (priv == NULL)
322         {
323           gnutls_assert ();
324           return GNUTLS_E_MEMORY_ERROR;
325         }
326       epriv.ptr = priv;
327     }
328   else
329     priv = epriv.ptr;
330
331   /* It is not legal to receive this extension on a renegotiation and
332    * not receive it on the initial negotiation.
333    */
334   if (session->internals.initial_negotiation_completed != 0 &&
335       priv->connection_using_safe_renegotiation == 0)
336     {
337       gnutls_assert ();
338       return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
339     }
340
341   if (len > sizeof (priv->ri_extension_data))
342     {
343       gnutls_assert ();
344       return GNUTLS_E_SAFE_RENEGOTIATION_FAILED;
345     }
346
347   if (len > 0)
348     memcpy (priv->ri_extension_data, &data[1], len);
349   priv->ri_extension_data_len = len;
350
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.
354    */
355   priv->safe_renegotiation_received = 1;
356   priv->connection_using_safe_renegotiation = 1;
357
358   if (set != 0)
359     _gnutls_ext_set_session_data (session,
360                                   GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv);
361   return 0;
362 }
363
364 static int
365 _gnutls_sr_send_params (gnutls_session_t session,
366                         opaque * data, size_t _data_size)
367 {
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.
372    */
373   ssize_t data_size = _data_size;
374   sr_ext_st *priv;
375   int ret, set = 0;
376   extension_priv_data_t epriv;
377
378   if (session->internals.priorities.sr == SR_DISABLED)
379     {
380       gnutls_assert ();
381       return 0;
382     }
383
384   ret = _gnutls_ext_get_session_data (session,
385                                       GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
386                                       &epriv);
387   if (ret < 0)
388     {
389       set = 1;
390     }
391
392   if (set != 0)
393     {
394       priv = gnutls_calloc (1, sizeof (*priv));
395       if (priv == NULL)
396         {
397           gnutls_assert ();
398           return GNUTLS_E_MEMORY_ERROR;
399         }
400       epriv.ptr = priv;
401
402       _gnutls_ext_set_session_data (session,
403                                     GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
404                                     epriv);
405     }
406   else
407     priv = epriv.ptr;
408
409   data[0] = 0;
410
411   /* Always offer the extension if we're a client */
412   if (priv->connection_using_safe_renegotiation ||
413       session->security_parameters.entity == GNUTLS_CLIENT)
414     {
415       DECR_LEN (data_size, 1);
416       data[0] = priv->client_verify_data_len;
417
418       DECR_LEN (data_size, priv->client_verify_data_len);
419
420       if (priv->client_verify_data_len > 0)
421         memcpy (&data[1], priv->client_verify_data,
422                 priv->client_verify_data_len);
423
424       if (session->security_parameters.entity == GNUTLS_SERVER)
425         {
426           data[0] += priv->server_verify_data_len;
427
428           DECR_LEN (data_size, priv->server_verify_data_len);
429
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);
433         }
434     }
435   else
436     return 0;
437
438   return 1 + data[0];           /* don't forget the length byte */
439 }
440
441 static void
442 _gnutls_sr_deinit_data (extension_priv_data_t priv)
443 {
444   gnutls_free (priv.ptr);
445 }
446
447 /**
448  * gnutls_safe_renegotiation_status:
449  * @session: is a #gnutls_session_t structure.
450  *
451  * Can be used to check whether safe renegotiation is being used
452  * in the current session.
453  *
454  * Returns: 0 when safe renegotiation is not used and non zero when
455  *   safe renegotiation is used.
456  *
457  * Since: 2.10.0
458  **/
459 int
460 gnutls_safe_renegotiation_status (gnutls_session_t session)
461 {
462   int ret;
463   sr_ext_st *priv;
464   extension_priv_data_t epriv;
465
466   ret = _gnutls_ext_get_session_data (session,
467                                       GNUTLS_EXTENSION_SAFE_RENEGOTIATION,
468                                       &epriv);
469   if (ret < 0)
470     {
471       gnutls_assert ();
472       return 0;
473     }
474   priv = epriv.ptr;
475
476   return priv->connection_using_safe_renegotiation;
477 }