Imported Upstream version 3.3.5
[platform/upstream/gnutls.git] / lib / gnutls_extensions.c
1 /*
2  * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos, Simon Josefsson
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 License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 /* Functions that relate to the TLS hello extension parsing.
24  * Hello extensions are packets appended in the TLS hello packet, and
25  * allow for extra functionality.
26  */
27
28 #include "gnutls_int.h"
29 #include "gnutls_extensions.h"
30 #include "gnutls_errors.h"
31 #include "ext/max_record.h"
32 #include <ext/cert_type.h>
33 #include <ext/server_name.h>
34 #include <ext/srp.h>
35 #include <ext/heartbeat.h>
36 #include <ext/session_ticket.h>
37 #include <ext/safe_renegotiation.h>
38 #include <ext/signature.h>
39 #include <ext/safe_renegotiation.h>
40 #include <ext/ecc.h>
41 #include <ext/status_request.h>
42 #include <ext/srtp.h>
43 #include <ext/alpn.h>
44 #include <ext/dumbfw.h>
45 #include <gnutls_num.h>
46
47
48 static void _gnutls_ext_unset_resumed_session_data(gnutls_session_t
49                                                    session, uint16_t type);
50
51
52 static size_t extfunc_size = 0;
53 static extension_entry_st *extfunc = NULL;
54
55 static gnutls_ext_parse_type_t _gnutls_ext_parse_type(uint16_t type)
56 {
57         size_t i;
58
59         for (i = 0; i < extfunc_size; i++) {
60                 if (extfunc[i].type == type)
61                         return extfunc[i].parse_type;
62         }
63
64         return GNUTLS_EXT_NONE;
65 }
66
67 static gnutls_ext_recv_func
68 _gnutls_ext_func_recv(uint16_t type, gnutls_ext_parse_type_t parse_type)
69 {
70         size_t i;
71
72         for (i = 0; i < extfunc_size; i++)
73                 if (extfunc[i].type == type)
74                         if (parse_type == GNUTLS_EXT_ANY
75                             || extfunc[i].parse_type == parse_type)
76                                 return extfunc[i].recv_func;
77
78         return NULL;
79 }
80
81 static gnutls_ext_deinit_data_func _gnutls_ext_func_deinit(uint16_t type)
82 {
83         size_t i;
84
85         for (i = 0; i < extfunc_size; i++)
86                 if (extfunc[i].type == type)
87                         return extfunc[i].deinit_func;
88
89         return NULL;
90 }
91
92 static gnutls_ext_unpack_func _gnutls_ext_func_unpack(uint16_t type)
93 {
94         size_t i;
95
96         for (i = 0; i < extfunc_size; i++)
97                 if (extfunc[i].type == type)
98                         return extfunc[i].unpack_func;
99
100         return NULL;
101 }
102
103
104 static const char *_gnutls_extension_get_name(uint16_t type)
105 {
106         size_t i;
107
108         for (i = 0; i < extfunc_size; i++)
109                 if (extfunc[i].type == type)
110                         return extfunc[i].name;
111
112         return NULL;
113 }
114
115 /* Checks if the extension we just received is one of the 
116  * requested ones. Otherwise it's a fatal error.
117  */
118 static int
119 _gnutls_extension_list_check(gnutls_session_t session, uint16_t type)
120 {
121         if (session->security_parameters.entity == GNUTLS_CLIENT) {
122                 int i;
123
124                 for (i = 0; i < session->internals.extensions_sent_size;
125                      i++) {
126                         if (type == session->internals.extensions_sent[i])
127                                 return 0;       /* ok found */
128                 }
129
130                 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
131         }
132
133         return 0;
134 }
135
136 int
137 _gnutls_parse_extensions(gnutls_session_t session,
138                          gnutls_ext_parse_type_t parse_type,
139                          const uint8_t * data, int data_size)
140 {
141         int next, ret;
142         int pos = 0;
143         uint16_t type;
144         const uint8_t *sdata;
145         gnutls_ext_recv_func ext_recv;
146         uint16_t size;
147
148 #ifdef DEBUG
149         int i;
150
151         if (session->security_parameters.entity == GNUTLS_CLIENT)
152                 for (i = 0; i < session->internals.extensions_sent_size;
153                      i++) {
154                         _gnutls_handshake_log
155                             ("EXT[%d]: expecting extension '%s'\n",
156                              session,
157                              _gnutls_extension_get_name(session->internals.
158                                                         extensions_sent
159                                                         [i]));
160                 }
161 #endif
162
163         DECR_LENGTH_RET(data_size, 2, 0);
164         next = _gnutls_read_uint16(data);
165         pos += 2;
166
167         DECR_LENGTH_RET(data_size, next, 0);
168
169         do {
170                 DECR_LENGTH_RET(next, 2, 0);
171                 type = _gnutls_read_uint16(&data[pos]);
172                 pos += 2;
173
174                 if ((ret =
175                      _gnutls_extension_list_check(session, type)) < 0) {
176                         gnutls_assert();
177                         return ret;
178                 }
179
180                 DECR_LENGTH_RET(next, 2, 0);
181                 size = _gnutls_read_uint16(&data[pos]);
182                 pos += 2;
183
184                 DECR_LENGTH_RET(next, size, 0);
185                 sdata = &data[pos];
186                 pos += size;
187
188                 ext_recv = _gnutls_ext_func_recv(type, parse_type);
189                 if (ext_recv == NULL) {
190                         _gnutls_handshake_log
191                             ("EXT[%p]: Found extension '%s/%d'\n", session,
192                              _gnutls_extension_get_name(type), type);
193
194                         continue;
195                 }
196
197                 _gnutls_handshake_log
198                     ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
199                      session, _gnutls_extension_get_name(type), type,
200                      size);
201
202                 if ((ret = ext_recv(session, sdata, size)) < 0) {
203                         gnutls_assert();
204                         return ret;
205                 }
206
207         }
208         while (next > 2);
209
210         return 0;
211
212 }
213
214 /* Adds the extension we want to send in the extensions list.
215  * This list is used to check whether the (later) received
216  * extensions are the ones we requested.
217  */
218 void _gnutls_extension_list_add(gnutls_session_t session, uint16_t type)
219 {
220
221         if (session->security_parameters.entity == GNUTLS_CLIENT) {
222                 if (session->internals.extensions_sent_size <
223                     MAX_EXT_TYPES) {
224                         session->internals.extensions_sent[session->
225                                                            internals.extensions_sent_size]
226                             = type;
227                         session->internals.extensions_sent_size++;
228                 } else {
229                         _gnutls_handshake_log
230                             ("extensions: Increase MAX_EXT_TYPES\n");
231                 }
232         }
233 }
234
235 int
236 _gnutls_gen_extensions(gnutls_session_t session,
237                        gnutls_buffer_st * extdata,
238                        gnutls_ext_parse_type_t parse_type)
239 {
240         int size;
241         int pos, size_pos, ret;
242         size_t i, init_size = extdata->length;
243
244         pos = extdata->length;  /* we will store length later on */
245
246         ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
247         if (ret < 0)
248                 return gnutls_assert_val(ret);
249
250         for (i = 0; i < extfunc_size; i++) {
251                 extension_entry_st *p = &extfunc[i];
252
253                 if (p->send_func == NULL)
254                         continue;
255
256                 if (parse_type != GNUTLS_EXT_ANY
257                     && p->parse_type != parse_type)
258                         continue;
259
260                 ret = _gnutls_buffer_append_prefix(extdata, 16, p->type);
261                 if (ret < 0)
262                         return gnutls_assert_val(ret);
263
264                 size_pos = extdata->length;
265                 ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
266                 if (ret < 0)
267                         return gnutls_assert_val(ret);
268
269                 size = p->send_func(session, extdata);
270                 /* returning GNUTLS_E_INT_RET_0 means to send an empty
271                  * extension of this type.
272                  */
273                 if (size > 0 || size == GNUTLS_E_INT_RET_0) {
274                         if (size == GNUTLS_E_INT_RET_0)
275                                 size = 0;
276
277                         /* write the real size */
278                         _gnutls_write_uint16(size,
279                                              &extdata->data[size_pos]);
280
281                         /* add this extension to the extension list
282                          */
283                         _gnutls_extension_list_add(session, p->type);
284
285                         _gnutls_handshake_log
286                             ("EXT[%p]: Sending extension %s (%d bytes)\n",
287                              session, p->name, size);
288                 } else if (size < 0) {
289                         gnutls_assert();
290                         return size;
291                 } else if (size == 0)
292                         extdata->length -= 4;   /* reset type and size */
293         }
294
295         /* remove any initial data, and the size of the header */
296         size = extdata->length - init_size - 2;
297
298         if (size > 0)
299                 _gnutls_write_uint16(size, &extdata->data[pos]);
300         else if (size == 0)
301                 extdata->length -= 2;   /* the length bytes */
302
303         return size;
304 }
305
306 int _gnutls_ext_init(void)
307 {
308         int ret;
309
310         ret = _gnutls_ext_register(&ext_mod_max_record_size);
311         if (ret != GNUTLS_E_SUCCESS)
312                 return ret;
313
314 #ifdef ENABLE_OCSP
315         ret = _gnutls_ext_register(&ext_mod_status_request);
316         if (ret != GNUTLS_E_SUCCESS)
317                 return ret;
318 #endif
319
320 #ifdef ENABLE_OPENPGP
321         ret = _gnutls_ext_register(&ext_mod_cert_type);
322         if (ret != GNUTLS_E_SUCCESS)
323                 return ret;
324 #endif
325
326         ret = _gnutls_ext_register(&ext_mod_server_name);
327         if (ret != GNUTLS_E_SUCCESS)
328                 return ret;
329
330         ret = _gnutls_ext_register(&ext_mod_sr);
331         if (ret != GNUTLS_E_SUCCESS)
332                 return ret;
333
334 #ifdef ENABLE_SRP
335         ret = _gnutls_ext_register(&ext_mod_srp);
336         if (ret != GNUTLS_E_SUCCESS)
337                 return ret;
338 #endif
339
340 #ifdef ENABLE_HEARTBEAT
341         ret = _gnutls_ext_register(&ext_mod_heartbeat);
342         if (ret != GNUTLS_E_SUCCESS)
343                 return ret;
344 #endif
345
346 #ifdef ENABLE_SESSION_TICKETS
347         ret = _gnutls_ext_register(&ext_mod_session_ticket);
348         if (ret != GNUTLS_E_SUCCESS)
349                 return ret;
350 #endif
351
352         ret = _gnutls_ext_register(&ext_mod_supported_ecc);
353         if (ret != GNUTLS_E_SUCCESS)
354                 return ret;
355
356         ret = _gnutls_ext_register(&ext_mod_supported_ecc_pf);
357         if (ret != GNUTLS_E_SUCCESS)
358                 return ret;
359
360         ret = _gnutls_ext_register(&ext_mod_sig);
361         if (ret != GNUTLS_E_SUCCESS)
362                 return ret;
363
364 #ifdef ENABLE_DTLS_SRTP
365         ret = _gnutls_ext_register(&ext_mod_srtp);
366         if (ret != GNUTLS_E_SUCCESS)
367                 return ret;
368 #endif
369
370 #ifdef ENABLE_ALPN
371         ret = _gnutls_ext_register(&ext_mod_alpn);
372         if (ret != GNUTLS_E_SUCCESS)
373                 return ret;
374 #endif
375
376         /* This must be the last extension registered.
377          */
378         ret = _gnutls_ext_register(&ext_mod_dumbfw);
379         if (ret != GNUTLS_E_SUCCESS)
380                 return ret;
381
382         return GNUTLS_E_SUCCESS;
383 }
384
385 void _gnutls_ext_deinit(void)
386 {
387         gnutls_free(extfunc);
388         extfunc = NULL;
389         extfunc_size = 0;
390 }
391
392 int _gnutls_ext_register(extension_entry_st * mod)
393 {
394         extension_entry_st *p;
395
396         p = gnutls_realloc_fast(extfunc,
397                                 sizeof(*extfunc) * (extfunc_size + 1));
398         if (!p) {
399                 gnutls_assert();
400                 return GNUTLS_E_MEMORY_ERROR;
401         }
402
403         extfunc = p;
404
405         memcpy(&extfunc[extfunc_size], mod, sizeof(*mod));
406
407         extfunc_size++;
408
409         return GNUTLS_E_SUCCESS;
410 }
411
412 int _gnutls_ext_before_epoch_change(gnutls_session_t session)
413 {
414         unsigned int i;
415         int ret;
416
417         for (i = 0; i < extfunc_size; i++) {
418                 if (extfunc[i].epoch_func != NULL) {
419                         ret = extfunc[i].epoch_func(session);
420                         if (ret < 0)
421                                 return gnutls_assert_val(ret);
422                 }
423         }
424
425         return 0;
426 }
427
428
429 int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed)
430 {
431         unsigned int i;
432         int ret;
433         extension_priv_data_t data;
434         int cur_size;
435         int size_offset;
436         int total_exts_pos;
437         int exts = 0;
438
439         total_exts_pos = packed->length;
440         BUFFER_APPEND_NUM(packed, 0);
441
442         for (i = 0; i < extfunc_size; i++) {
443                 ret =
444                     _gnutls_ext_get_session_data(session, extfunc[i].type,
445                                                  &data);
446                 if (ret >= 0 && extfunc[i].pack_func != NULL) {
447                         BUFFER_APPEND_NUM(packed, extfunc[i].type);
448
449                         size_offset = packed->length;
450                         BUFFER_APPEND_NUM(packed, 0);
451
452                         cur_size = packed->length;
453
454                         ret = extfunc[i].pack_func(data, packed);
455                         if (ret < 0) {
456                                 gnutls_assert();
457                                 return ret;
458                         }
459
460                         exts++;
461                         /* write the actual size */
462                         _gnutls_write_uint32(packed->length - cur_size,
463                                              packed->data + size_offset);
464                 }
465         }
466
467         _gnutls_write_uint32(exts, packed->data + total_exts_pos);
468
469         return 0;
470 }
471
472 void _gnutls_ext_restore_resumed_session(gnutls_session_t session)
473 {
474         int i;
475
476
477         /* clear everything except MANDATORY extensions */
478         for (i = 0; i < MAX_EXT_TYPES; i++) {
479                 if (session->internals.extension_int_data[i].set != 0 &&
480                     _gnutls_ext_parse_type(session->
481                                            internals.extension_int_data[i].
482                                            type) != GNUTLS_EXT_MANDATORY) {
483                         _gnutls_ext_unset_session_data(session,
484                                                        session->internals.
485                                                        extension_int_data
486                                                        [i].type);
487                 }
488         }
489
490         /* copy resumed to main */
491         for (i = 0; i < MAX_EXT_TYPES; i++) {
492                 if (session->internals.resumed_extension_int_data[i].set !=
493                     0
494                     && _gnutls_ext_parse_type(session->internals.
495                                               resumed_extension_int_data
496                                               [i].type) !=
497                     GNUTLS_EXT_MANDATORY) {
498                         _gnutls_ext_set_session_data(session,
499                                                      session->internals.
500                                                      resumed_extension_int_data
501                                                      [i].type,
502                                                      session->internals.
503                                                      resumed_extension_int_data
504                                                      [i].priv);
505                         session->internals.resumed_extension_int_data[i].
506                             set = 0;
507                 }
508         }
509
510 }
511
512
513 static void
514 _gnutls_ext_set_resumed_session_data(gnutls_session_t session,
515                                      uint16_t type,
516                                      extension_priv_data_t data)
517 {
518         int i;
519
520         for (i = 0; i < MAX_EXT_TYPES; i++) {
521                 if (session->internals.resumed_extension_int_data[i].
522                     type == type
523                     || session->internals.resumed_extension_int_data[i].
524                     set == 0) {
525
526                         if (session->internals.
527                             resumed_extension_int_data[i].set != 0)
528                                 _gnutls_ext_unset_resumed_session_data
529                                     (session, type);
530
531                         session->internals.resumed_extension_int_data[i].
532                             type = type;
533                         session->internals.resumed_extension_int_data[i].
534                             priv = data;
535                         session->internals.resumed_extension_int_data[i].
536                             set = 1;
537                         return;
538                 }
539         }
540 }
541
542 int _gnutls_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed)
543 {
544         int i, ret;
545         extension_priv_data_t data;
546         gnutls_ext_unpack_func unpack;
547         int max_exts = 0;
548         uint16_t type;
549         int size_for_type, cur_pos;
550
551
552         BUFFER_POP_NUM(packed, max_exts);
553         for (i = 0; i < max_exts; i++) {
554                 BUFFER_POP_NUM(packed, type);
555                 BUFFER_POP_NUM(packed, size_for_type);
556
557                 cur_pos = packed->length;
558
559                 unpack = _gnutls_ext_func_unpack(type);
560                 if (unpack == NULL) {
561                         gnutls_assert();
562                         return GNUTLS_E_PARSING_ERROR;
563                 }
564
565                 ret = unpack(packed, &data);
566                 if (ret < 0) {
567                         gnutls_assert();
568                         return ret;
569                 }
570
571                 /* verify that unpack read the correct bytes */
572                 cur_pos = cur_pos - packed->length;
573                 if (cur_pos /* read length */  != size_for_type) {
574                         gnutls_assert();
575                         return GNUTLS_E_PARSING_ERROR;
576                 }
577
578                 _gnutls_ext_set_resumed_session_data(session, type, data);
579         }
580
581         return 0;
582
583       error:
584         return ret;
585 }
586
587 void
588 _gnutls_ext_unset_session_data(gnutls_session_t session, uint16_t type)
589 {
590         gnutls_ext_deinit_data_func deinit;
591         extension_priv_data_t data;
592         int ret, i;
593
594         deinit = _gnutls_ext_func_deinit(type);
595         ret = _gnutls_ext_get_session_data(session, type, &data);
596
597         if (ret >= 0 && deinit != NULL) {
598                 deinit(data);
599         }
600
601         for (i = 0; i < MAX_EXT_TYPES; i++) {
602                 if (session->internals.extension_int_data[i].type == type) {
603                         session->internals.extension_int_data[i].set = 0;
604                         return;
605                 }
606         }
607
608 }
609
610 static void
611 _gnutls_ext_unset_resumed_session_data(gnutls_session_t session,
612                                        uint16_t type)
613 {
614         gnutls_ext_deinit_data_func deinit;
615         extension_priv_data_t data;
616         int ret, i;
617
618         deinit = _gnutls_ext_func_deinit(type);
619         ret = _gnutls_ext_get_resumed_session_data(session, type, &data);
620
621         if (ret >= 0 && deinit != NULL) {
622                 deinit(data);
623         }
624
625         for (i = 0; i < MAX_EXT_TYPES; i++) {
626                 if (session->internals.resumed_extension_int_data[i].
627                     type == type) {
628                         session->internals.resumed_extension_int_data[i].
629                             set = 0;
630                         return;
631                 }
632         }
633
634 }
635
636 /* Deinitializes all data that are associated with TLS extensions.
637  */
638 void _gnutls_ext_free_session_data(gnutls_session_t session)
639 {
640         unsigned int i;
641
642         for (i = 0; i < extfunc_size; i++) {
643                 _gnutls_ext_unset_session_data(session, extfunc[i].type);
644         }
645
646         for (i = 0; i < extfunc_size; i++) {
647                 _gnutls_ext_unset_resumed_session_data(session,
648                                                        extfunc[i].type);
649         }
650
651 }
652
653 /* This function allows and extension to store data in the current session
654  * and retrieve them later on. We use functions instead of a pointer to a
655  * private pointer, to allow API additions by individual extensions.
656  */
657 void
658 _gnutls_ext_set_session_data(gnutls_session_t session, uint16_t type,
659                              extension_priv_data_t data)
660 {
661         unsigned int i;
662         gnutls_ext_deinit_data_func deinit;
663
664         deinit = _gnutls_ext_func_deinit(type);
665
666         for (i = 0; i < MAX_EXT_TYPES; i++) {
667                 if (session->internals.extension_int_data[i].type == type
668                     || session->internals.extension_int_data[i].set == 0) {
669                         if (session->internals.extension_int_data[i].set !=
670                             0) {
671                                 if (deinit)
672                                         deinit(session->internals.
673                                                extension_int_data[i].priv);
674                         }
675                         session->internals.extension_int_data[i].type =
676                             type;
677                         session->internals.extension_int_data[i].priv =
678                             data;
679                         session->internals.extension_int_data[i].set = 1;
680                         return;
681                 }
682         }
683 }
684
685 int
686 _gnutls_ext_get_session_data(gnutls_session_t session,
687                              uint16_t type, extension_priv_data_t * data)
688 {
689         int i;
690
691         for (i = 0; i < MAX_EXT_TYPES; i++) {
692                 if (session->internals.extension_int_data[i].set != 0 &&
693                     session->internals.extension_int_data[i].type == type)
694                 {
695                         *data =
696                             session->internals.extension_int_data[i].priv;
697                         return 0;
698                 }
699         }
700         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
701 }
702
703 int
704 _gnutls_ext_get_resumed_session_data(gnutls_session_t session,
705                                      uint16_t type,
706                                      extension_priv_data_t * data)
707 {
708         int i;
709
710         for (i = 0; i < MAX_EXT_TYPES; i++) {
711                 if (session->internals.resumed_extension_int_data[i].set !=
712                     0
713                     && session->internals.resumed_extension_int_data[i].
714                     type == type) {
715                         *data =
716                             session->internals.
717                             resumed_extension_int_data[i].priv;
718                         return 0;
719                 }
720         }
721         return GNUTLS_E_INVALID_REQUEST;
722 }