1 /*
2 * Copyright (C) 2001-2018 Free Software Foundation, Inc.
3 * Copyright (C) 2015-2018 Red Hat, Inc.
4 *
5 * Author: Nikos Mavrogiannopoulos, Simon Josefsson
6 *
7 * This file is part of GnuTLS.
8 *
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>
21 *
22 */
23
24 /* Functions that relate to the TLS hello extension parsing.
25 * Hello extensions are packets appended in the TLS hello packet, and
26 * allow for extra functionality.
27 */
28
29 #include "gnutls_int.h"
30 #include "hello_ext.h"
31 #include "errors.h"
32 #include "ext/max_record.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/supported_groups.h"
41 #include "ext/ec_point_formats.h"
42 #include <ext/status_request.h>
43 #include <ext/ext_master_secret.h>
44 #include <ext/supported_versions.h>
45 #include <ext/post_handshake.h>
46 #include <ext/srtp.h>
47 #include <ext/alpn.h>
48 #include <ext/dumbfw.h>
49 #include <ext/key_share.h>
50 #include <ext/pre_shared_key.h>
51 #include <ext/psk_ke_modes.h>
52 #include <ext/etm.h>
53 #include <ext/cookie.h>
54 #include <ext/early_data.h>
55 #include <ext/record_size_limit.h>
56 #include "extv.h"
57 #include <num.h>
58 #include <ext/client_cert_type.h>
59 #include <ext/server_cert_type.h>
60
61 static void
62 unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx);
63
64 static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx);
65
66 static hello_ext_entry_st const *extfunc[MAX_EXT_TYPES+1] = {
67 [GNUTLS_EXTENSION_EXT_MASTER_SECRET] = &ext_mod_ext_master_secret,
68 [GNUTLS_EXTENSION_SUPPORTED_VERSIONS] = &ext_mod_supported_versions,
69 [GNUTLS_EXTENSION_POST_HANDSHAKE] = &ext_mod_post_handshake,
70 [GNUTLS_EXTENSION_ETM] = &ext_mod_etm,
71 #ifdef ENABLE_OCSP
72 [GNUTLS_EXTENSION_STATUS_REQUEST] = &ext_mod_status_request,
73 #endif
74 [GNUTLS_EXTENSION_SERVER_NAME] = &ext_mod_server_name,
75 [GNUTLS_EXTENSION_SAFE_RENEGOTIATION] = &ext_mod_sr,
76 #ifdef ENABLE_SRP
77 [GNUTLS_EXTENSION_SRP] = &ext_mod_srp,
78 #endif
79 #ifdef ENABLE_HEARTBEAT
80 [GNUTLS_EXTENSION_HEARTBEAT] = &ext_mod_heartbeat,
81 #endif
82 [GNUTLS_EXTENSION_SESSION_TICKET] = &ext_mod_session_ticket,
83 [GNUTLS_EXTENSION_CLIENT_CERT_TYPE] = &ext_mod_client_cert_type,
84 [GNUTLS_EXTENSION_SERVER_CERT_TYPE] = &ext_mod_server_cert_type,
85 [GNUTLS_EXTENSION_SUPPORTED_GROUPS] = &ext_mod_supported_groups,
86 [GNUTLS_EXTENSION_SUPPORTED_EC_POINT_FORMATS] = &ext_mod_supported_ec_point_formats,
87 [GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS] = &ext_mod_sig,
88 [GNUTLS_EXTENSION_KEY_SHARE] = &ext_mod_key_share,
89 [GNUTLS_EXTENSION_COOKIE] = &ext_mod_cookie,
90 [GNUTLS_EXTENSION_EARLY_DATA] = &ext_mod_early_data,
91 #ifdef ENABLE_DTLS_SRTP
92 [GNUTLS_EXTENSION_SRTP] = &ext_mod_srtp,
93 #endif
94 #ifdef ENABLE_ALPN
95 [GNUTLS_EXTENSION_ALPN] = &ext_mod_alpn,
96 #endif
97 [GNUTLS_EXTENSION_RECORD_SIZE_LIMIT] = &ext_mod_record_size_limit,
98 [GNUTLS_EXTENSION_MAX_RECORD_SIZE] = &ext_mod_max_record_size,
99 [GNUTLS_EXTENSION_PSK_KE_MODES] = &ext_mod_psk_ke_modes,
100 [GNUTLS_EXTENSION_PRE_SHARED_KEY] = &ext_mod_pre_shared_key,
101 /* This must be the last extension registered.
102 */
103 [GNUTLS_EXTENSION_DUMBFW] = &ext_mod_dumbfw,
104 };
105
106 static const hello_ext_entry_st *
gid_to_ext_entry(gnutls_session_t session,extensions_t id)107 gid_to_ext_entry(gnutls_session_t session, extensions_t id)
108 {
109 unsigned i;
110
111 assert(id < MAX_EXT_TYPES);
112
113 for (i=0;i<session->internals.rexts_size;i++) {
114 if (session->internals.rexts[i].gid == id) {
115 return &session->internals.rexts[i];
116 }
117 }
118
119 return extfunc[id];
120 }
121
122 static const hello_ext_entry_st *
tls_id_to_ext_entry(gnutls_session_t session,uint16_t tls_id,gnutls_ext_parse_type_t parse_point)123 tls_id_to_ext_entry(gnutls_session_t session, uint16_t tls_id, gnutls_ext_parse_type_t parse_point)
124 {
125 unsigned i;
126 const hello_ext_entry_st *e;
127
128 for (i=0;i<session->internals.rexts_size;i++) {
129 if (session->internals.rexts[i].tls_id == tls_id) {
130 e = &session->internals.rexts[i];
131 goto done;
132 }
133 }
134
135 for (i = 0; i < MAX_EXT_TYPES; i++) {
136 if (!extfunc[i])
137 continue;
138
139 if (extfunc[i]->tls_id == tls_id) {
140 e = extfunc[i];
141 goto done;
142 }
143 }
144
145 return NULL;
146 done:
147 if (parse_point == GNUTLS_EXT_ANY || (IS_SERVER(session) && e->server_parse_point == parse_point) ||
148 (!IS_SERVER(session) && e->client_parse_point == parse_point)) {
149 return e;
150 } else {
151 return NULL;
152 }
153 }
154
155
156 /**
157 * gnutls_ext_get_name:
158 * @ext: is a TLS extension numeric ID
159 *
160 * Convert a TLS extension numeric ID to a printable string.
161 *
162 * Returns: a pointer to a string that contains the name of the
163 * specified cipher, or %NULL.
164 **/
gnutls_ext_get_name(unsigned int ext)165 const char *gnutls_ext_get_name(unsigned int ext)
166 {
167 size_t i;
168
169 for (i = 0; i < MAX_EXT_TYPES; i++) {
170 if (!extfunc[i])
171 continue;
172
173 if (extfunc[i]->tls_id == ext)
174 return extfunc[i]->name;
175 }
176
177 return NULL;
178 }
179
180 /* Returns %GNUTLS_EXTENSION_INVALID on error
181 */
tls_id_to_gid(gnutls_session_t session,unsigned tls_id)182 static unsigned tls_id_to_gid(gnutls_session_t session, unsigned tls_id)
183 {
184 unsigned i;
185
186 for (i=0; i < session->internals.rexts_size; i++) {
187 if (session->internals.rexts[i].tls_id == tls_id)
188 return session->internals.rexts[i].gid;
189 }
190
191 for (i = 0; i < MAX_EXT_TYPES; i++) {
192 if (!extfunc[i])
193 continue;
194
195 if (extfunc[i]->tls_id == tls_id)
196 return extfunc[i]->gid;
197 }
198
199 return GNUTLS_EXTENSION_INVALID;
200 }
201
202 typedef struct hello_ext_ctx_st {
203 gnutls_session_t session;
204 gnutls_ext_flags_t msg;
205 gnutls_ext_parse_type_t parse_point;
206 const hello_ext_entry_st *ext; /* used during send */
207 unsigned seen_pre_shared_key;
208 } hello_ext_ctx_st;
209
210 static
hello_ext_parse(void * _ctx,unsigned tls_id,const uint8_t * data,unsigned data_size)211 int hello_ext_parse(void *_ctx, unsigned tls_id, const uint8_t *data, unsigned data_size)
212 {
213 hello_ext_ctx_st *ctx = _ctx;
214 gnutls_session_t session = ctx->session;
215 const hello_ext_entry_st *ext;
216 int ret;
217
218 if (tls_id == PRE_SHARED_KEY_TLS_ID) {
219 ctx->seen_pre_shared_key = 1;
220 } else if (ctx->seen_pre_shared_key && session->security_parameters.entity == GNUTLS_SERVER) {
221 /* the pre-shared key extension must always be the last one,
222 * draft-ietf-tls-tls13-28: 4.2.11 */
223 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
224 }
225
226 ext = tls_id_to_ext_entry(session, tls_id, ctx->parse_point);
227 if (ext == NULL || ext->recv_func == NULL) {
228 goto ignore;
229 }
230
231 /* we do not hard fail when extensions defined for TLS are used for
232 * DTLS and vice-versa. They may extend their role in the future. */
233 if (IS_DTLS(session)) {
234 if (!(ext->validity & GNUTLS_EXT_FLAG_DTLS)) {
235 gnutls_assert();
236 goto ignore;
237 }
238 } else {
239 if (!(ext->validity & GNUTLS_EXT_FLAG_TLS)) {
240 gnutls_assert();
241 goto ignore;
242 }
243 }
244
245 if (session->security_parameters.entity == GNUTLS_CLIENT) {
246 if (!(ext->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) &&
247 !_gnutls_hello_ext_is_present(session, ext->gid)) {
248 _gnutls_debug_log("EXT[%p]: Received unexpected extension '%s/%d'\n", session,
249 ext->name, (int)tls_id);
250 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
251 }
252 }
253
254 if ((ext->validity & ctx->msg) == 0) {
255 _gnutls_debug_log("EXT[%p]: Received unexpected extension (%s/%d) for '%s'\n", session,
256 ext->name, (int)tls_id,
257 ext_msg_validity_to_str(ctx->msg));
258 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
259 }
260
261 if (session->security_parameters.entity == GNUTLS_SERVER) {
262 ret = _gnutls_hello_ext_save(session, ext->gid, 1);
263 if (ret == 0)
264 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
265 }
266
267 _gnutls_handshake_log
268 ("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
269 session, ext->name, (int)tls_id,
270 data_size);
271
272 _gnutls_ext_set_msg(session, ctx->msg);
273 if ((ret = ext->recv_func(session, data, data_size)) < 0) {
274 gnutls_assert();
275 return ret;
276 }
277
278 return 0;
279
280 ignore:
281 if (ext) {
282 _gnutls_handshake_log
283 ("EXT[%p]: Ignoring extension '%s/%d'\n", session,
284 ext->name, (int)tls_id);
285 }
286 return 0;
287 }
288
289 int
_gnutls_parse_hello_extensions(gnutls_session_t session,gnutls_ext_flags_t msg,gnutls_ext_parse_type_t parse_point,const uint8_t * data,int data_size)290 _gnutls_parse_hello_extensions(gnutls_session_t session,
291 gnutls_ext_flags_t msg,
292 gnutls_ext_parse_type_t parse_point,
293 const uint8_t * data, int data_size)
294 {
295 int ret;
296 hello_ext_ctx_st ctx;
297
298 msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
299
300 ctx.session = session;
301 ctx.msg = msg;
302 ctx.parse_point = parse_point;
303 ctx.seen_pre_shared_key = 0;
304
305 ret = _gnutls_extv_parse(&ctx, hello_ext_parse, data, data_size);
306 if (ret < 0)
307 return gnutls_assert_val(ret);
308
309 return 0;
310 }
311
312 static
hello_ext_send(void * _ctx,gnutls_buffer_st * buf)313 int hello_ext_send(void *_ctx, gnutls_buffer_st *buf)
314 {
315 hello_ext_ctx_st *ctx = _ctx;
316 int ret;
317 const hello_ext_entry_st *p = ctx->ext;
318 gnutls_session_t session = ctx->session;
319 int appended;
320 size_t size_prev;
321
322 if (unlikely(p->send_func == NULL))
323 return 0;
324
325 if (ctx->parse_point != GNUTLS_EXT_ANY &&
326 ((IS_SERVER(session) && p->server_parse_point != ctx->parse_point) ||
327 (!IS_SERVER(session) && p->client_parse_point != ctx->parse_point))) {
328 return 0;
329 }
330
331 if (IS_DTLS(session)) {
332 if (!(p->validity & GNUTLS_EXT_FLAG_DTLS)) {
333 gnutls_assert();
334 goto skip;
335 }
336 } else {
337 if (!(p->validity & GNUTLS_EXT_FLAG_TLS)) {
338 gnutls_assert();
339 goto skip;
340 }
341 }
342
343 if ((ctx->msg & p->validity) == 0) {
344 goto skip;
345 } else {
346 _gnutls_handshake_log("EXT[%p]: Preparing extension (%s/%d) for '%s'\n", session,
347 p->name, (int)p->tls_id,
348 ext_msg_validity_to_str(ctx->msg));
349 }
350
351 /* ensure we don't send something twice (i.e, overridden extensions in
352 * client), and ensure we are sending only what we received in server. */
353 ret = _gnutls_hello_ext_is_present(session, p->gid);
354
355 if (session->security_parameters.entity == GNUTLS_SERVER) {
356 /* if client didn't advertise and the override flag is not present */
357 if (!(p->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) && ret == 0)
358 return 0;
359 } else {
360 if (ret != 0) /* already sent */
361 return 0;
362 }
363
364
365 size_prev = buf->length;
366
367 _gnutls_ext_set_msg(session, ctx->msg);
368 ret = p->send_func(session, buf);
369 if (ret < 0 && ret != GNUTLS_E_INT_RET_0) {
370 return gnutls_assert_val(ret);
371 }
372
373 appended = buf->length - size_prev;
374
375 /* add this extension to the extension list, to know which extensions
376 * to expect.
377 */
378 if ((appended > 0 || ret == GNUTLS_E_INT_RET_0) &&
379 session->security_parameters.entity == GNUTLS_CLIENT) {
380
381 _gnutls_hello_ext_save(session, p->gid, 0);
382 }
383
384 return ret;
385
386 skip:
387 _gnutls_handshake_log("EXT[%p]: Not sending extension (%s/%d) for '%s'\n", session,
388 p->name, (int)p->tls_id,
389 ext_msg_validity_to_str(ctx->msg));
390 return 0;
391 }
392
393 int
_gnutls_gen_hello_extensions(gnutls_session_t session,gnutls_buffer_st * buf,gnutls_ext_flags_t msg,gnutls_ext_parse_type_t parse_point)394 _gnutls_gen_hello_extensions(gnutls_session_t session,
395 gnutls_buffer_st * buf,
396 gnutls_ext_flags_t msg,
397 gnutls_ext_parse_type_t parse_point)
398 {
399 int pos, ret;
400 size_t i;
401 hello_ext_ctx_st ctx;
402
403 msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
404
405 ctx.session = session;
406 ctx.msg = msg;
407 ctx.parse_point = parse_point;
408
409 ret = _gnutls_extv_append_init(buf);
410 if (ret < 0)
411 return gnutls_assert_val(ret);
412
413 pos = ret;
414 _gnutls_ext_set_extensions_offset(session, pos);
415
416 for (i=0; i < session->internals.rexts_size; i++) {
417 ctx.ext = &session->internals.rexts[i];
418 ret = _gnutls_extv_append(buf, session->internals.rexts[i].tls_id,
419 &ctx, hello_ext_send);
420 if (ret < 0)
421 return gnutls_assert_val(ret);
422
423 if (ret > 0)
424 _gnutls_handshake_log
425 ("EXT[%p]: Sending extension %s/%d (%d bytes)\n",
426 session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4);
427 }
428
429 /* hello_ext_send() ensures we don't send duplicates, in case
430 * of overridden extensions */
431 for (i = 0; i < MAX_EXT_TYPES; i++) {
432 if (!extfunc[i])
433 continue;
434
435 ctx.ext = extfunc[i];
436 ret = _gnutls_extv_append(buf, extfunc[i]->tls_id,
437 &ctx, hello_ext_send);
438 if (ret < 0)
439 return gnutls_assert_val(ret);
440
441 if (ret > 0)
442 _gnutls_handshake_log
443 ("EXT[%p]: Sending extension %s/%d (%d bytes)\n",
444 session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4);
445 }
446
447 ret = _gnutls_extv_append_final(buf, pos, !(msg & GNUTLS_EXT_FLAG_EE));
448 if (ret < 0)
449 return gnutls_assert_val(ret);
450
451 return 0;
452 }
453
454 /* Global deinit and init of global extensions */
_gnutls_hello_ext_init(void)455 int _gnutls_hello_ext_init(void)
456 {
457 return GNUTLS_E_SUCCESS;
458 }
459
_gnutls_hello_ext_deinit(void)460 void _gnutls_hello_ext_deinit(void)
461 {
462 unsigned i;
463
464 for (i = 0; i < MAX_EXT_TYPES; i++) {
465 if (!extfunc[i])
466 continue;
467
468 if (extfunc[i]->free_struct != 0) {
469 gnutls_free(((hello_ext_entry_st *)extfunc[i])->name);
470 gnutls_free(extfunc[i]);
471 }
472 }
473 }
474
475 /* Packing of extension data (for use in resumption) */
pack_extension(gnutls_session_t session,const hello_ext_entry_st * extp,gnutls_buffer_st * packed)476 static int pack_extension(gnutls_session_t session, const hello_ext_entry_st *extp,
477 gnutls_buffer_st *packed)
478 {
479 int ret;
480 int size_offset;
481 int cur_size;
482 gnutls_ext_priv_data_t data;
483 int rval = 0;
484
485 ret =
486 _gnutls_hello_ext_get_priv(session, extp->gid,
487 &data);
488 if (ret >= 0 && extp->pack_func != NULL) {
489 BUFFER_APPEND_NUM(packed, extp->gid);
490
491 size_offset = packed->length;
492 BUFFER_APPEND_NUM(packed, 0);
493
494 cur_size = packed->length;
495
496 ret = extp->pack_func(data, packed);
497 if (ret < 0) {
498 gnutls_assert();
499 return ret;
500 }
501
502 rval = 1;
503 /* write the actual size */
504 _gnutls_write_uint32(packed->length - cur_size,
505 packed->data + size_offset);
506 }
507
508 return rval;
509 }
510
_gnutls_hello_ext_pack(gnutls_session_t session,gnutls_buffer_st * packed)511 int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed)
512 {
513 unsigned int i;
514 int ret;
515 int total_exts_pos;
516 int n_exts = 0;
517 const struct hello_ext_entry_st *ext;
518
519 total_exts_pos = packed->length;
520 BUFFER_APPEND_NUM(packed, 0);
521
522 for (i = 0; i <= GNUTLS_EXTENSION_MAX_VALUE; i++) {
523 if (session->internals.used_exts & ((ext_track_t)1 << i)) {
524
525 ext = gid_to_ext_entry(session, i);
526 if (ext == NULL)
527 continue;
528
529 ret = pack_extension(session, ext, packed);
530 if (ret < 0)
531 return gnutls_assert_val(ret);
532
533 if (ret > 0)
534 n_exts++;
535 }
536 }
537
538 _gnutls_write_uint32(n_exts, packed->data + total_exts_pos);
539
540 return 0;
541 }
542
_gnutls_ext_set_full_client_hello(gnutls_session_t session,handshake_buffer_st * recv_buf)543 int _gnutls_ext_set_full_client_hello(gnutls_session_t session,
544 handshake_buffer_st *recv_buf)
545 {
546 int ret;
547 gnutls_buffer_st *buf = &session->internals.full_client_hello;
548
549 _gnutls_buffer_clear(buf);
550
551 if ((ret = _gnutls_buffer_append_prefix(buf, 8, recv_buf->htype)) < 0)
552 return gnutls_assert_val(ret);
553 if ((ret = _gnutls_buffer_append_prefix(buf, 24, recv_buf->data.length)) < 0)
554 return gnutls_assert_val(ret);
555 if ((ret = _gnutls_buffer_append_data(buf, recv_buf->data.data, recv_buf->data.length)) < 0)
556 return gnutls_assert_val(ret);
557
558 return 0;
559 }
560
_gnutls_ext_get_full_client_hello(gnutls_session_t session,gnutls_datum_t * d)561 unsigned _gnutls_ext_get_full_client_hello(gnutls_session_t session,
562 gnutls_datum_t *d)
563 {
564 gnutls_buffer_st *buf = &session->internals.full_client_hello;
565
566 if (!buf->length)
567 return 0;
568
569 d->data = buf->data;
570 d->size = buf->length;
571
572 return 1;
573 }
574
575 static void
_gnutls_ext_set_resumed_session_data(gnutls_session_t session,extensions_t id,gnutls_ext_priv_data_t data)576 _gnutls_ext_set_resumed_session_data(gnutls_session_t session,
577 extensions_t id,
578 gnutls_ext_priv_data_t data)
579 {
580 const struct hello_ext_entry_st *ext;
581
582 /* If this happens we need to increase the max */
583 assert(id < MAX_EXT_TYPES);
584
585 ext = gid_to_ext_entry(session, id);
586 assert(ext != NULL);
587
588 if (session->internals.ext_data[id].resumed_set != 0)
589 unset_resumed_ext_data(session, ext, id);
590
591 session->internals.ext_data[id].resumed_priv = data;
592 session->internals.ext_data[id].resumed_set = 1;
593 return;
594 }
595
_gnutls_hello_ext_unpack(gnutls_session_t session,gnutls_buffer_st * packed)596 int _gnutls_hello_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed)
597 {
598 int i, ret;
599 gnutls_ext_priv_data_t data;
600 int max_exts = 0;
601 extensions_t id;
602 int size_for_id, cur_pos;
603 const struct hello_ext_entry_st *ext;
604
605 BUFFER_POP_NUM(packed, max_exts);
606 for (i = 0; i < max_exts; i++) {
607 BUFFER_POP_NUM(packed, id);
608 BUFFER_POP_NUM(packed, size_for_id);
609
610 cur_pos = packed->length;
611
612 ext = gid_to_ext_entry(session, id);
613 if (ext == NULL || ext->unpack_func == NULL) {
614 gnutls_assert();
615 return GNUTLS_E_PARSING_ERROR;
616 }
617
618 ret = ext->unpack_func(packed, &data);
619 if (ret < 0) {
620 gnutls_assert();
621 return ret;
622 }
623
624 /* verify that unpack read the correct bytes */
625 cur_pos = cur_pos - packed->length;
626 if (cur_pos /* read length */ != size_for_id) {
627 gnutls_assert();
628 return GNUTLS_E_PARSING_ERROR;
629 }
630
631 _gnutls_ext_set_resumed_session_data(session, id, data);
632 }
633
634 return 0;
635
636 error:
637 return ret;
638 }
639
640 static void
unset_ext_data(gnutls_session_t session,const struct hello_ext_entry_st * ext,unsigned idx)641 unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
642 {
643 if (session->internals.ext_data[idx].set == 0)
644 return;
645
646 if (ext && ext->deinit_func && session->internals.ext_data[idx].priv != NULL)
647 ext->deinit_func(session->internals.ext_data[idx].priv);
648 session->internals.ext_data[idx].set = 0;
649 }
650
651 void
_gnutls_hello_ext_unset_priv(gnutls_session_t session,extensions_t id)652 _gnutls_hello_ext_unset_priv(gnutls_session_t session,
653 extensions_t id)
654 {
655 const struct hello_ext_entry_st *ext;
656
657 ext = gid_to_ext_entry(session, id);
658 if (ext)
659 unset_ext_data(session, ext, id);
660 }
661
unset_resumed_ext_data(gnutls_session_t session,const struct hello_ext_entry_st * ext,unsigned idx)662 static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
663 {
664 if (session->internals.ext_data[idx].resumed_set == 0)
665 return;
666
667 if (ext && ext->deinit_func && session->internals.ext_data[idx].resumed_priv) {
668 ext->deinit_func(session->internals.ext_data[idx].resumed_priv);
669 }
670 session->internals.ext_data[idx].resumed_set = 0;
671 }
672
673 /* Deinitializes all data that are associated with TLS extensions.
674 */
_gnutls_hello_ext_priv_deinit(gnutls_session_t session)675 void _gnutls_hello_ext_priv_deinit(gnutls_session_t session)
676 {
677 unsigned int i;
678 const struct hello_ext_entry_st *ext;
679
680 for (i = 0; i < MAX_EXT_TYPES; i++) {
681 if (!session->internals.ext_data[i].set && !session->internals.ext_data[i].resumed_set)
682 continue;
683
684 ext = gid_to_ext_entry(session, i);
685 if (ext) {
686 unset_ext_data(session, ext, i);
687 unset_resumed_ext_data(session, ext, i);
688 }
689 }
690 }
691
692 /* This function allows an extension to store data in the current session
693 * and retrieve them later on. We use functions instead of a pointer to a
694 * private pointer, to allow API additions by individual extensions.
695 */
696 void
_gnutls_hello_ext_set_priv(gnutls_session_t session,extensions_t id,gnutls_ext_priv_data_t data)697 _gnutls_hello_ext_set_priv(gnutls_session_t session, extensions_t id,
698 gnutls_ext_priv_data_t data)
699 {
700 const struct hello_ext_entry_st *ext;
701
702 assert(id < MAX_EXT_TYPES);
703
704 ext = gid_to_ext_entry(session, id);
705 assert(ext != NULL);
706
707 if (session->internals.ext_data[id].set != 0) {
708 unset_ext_data(session, ext, id);
709 }
710 session->internals.ext_data[id].priv = data;
711 session->internals.ext_data[id].set = 1;
712
713 return;
714 }
715
716 int
_gnutls_hello_ext_get_priv(gnutls_session_t session,extensions_t id,gnutls_ext_priv_data_t * data)717 _gnutls_hello_ext_get_priv(gnutls_session_t session,
718 extensions_t id, gnutls_ext_priv_data_t * data)
719 {
720 if (session->internals.ext_data[id].set != 0) {
721 *data =
722 session->internals.ext_data[id].priv;
723 return 0;
724 }
725
726 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
727 }
728
729 int
_gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,extensions_t id,gnutls_ext_priv_data_t * data)730 _gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,
731 extensions_t id,
732 gnutls_ext_priv_data_t * data)
733 {
734 if (session->internals.ext_data[id].resumed_set != 0) {
735 *data =
736 session->internals.ext_data[id].resumed_priv;
737 return 0;
738 }
739
740 return GNUTLS_E_INVALID_REQUEST;
741 }
742
743 /**
744 * gnutls_ext_register:
745 * @name: the name of the extension to register
746 * @id: the numeric TLS id of the extension
747 * @parse_point: the parse type of the extension (see gnutls_ext_parse_type_t)
748 * @recv_func: a function to receive the data
749 * @send_func: a function to send the data
750 * @deinit_func: a function deinitialize any private data
751 * @pack_func: a function which serializes the extension's private data (used on session packing for resumption)
752 * @unpack_func: a function which will deserialize the extension's private data
753 *
754 * This function will register a new extension type. The extension will remain
755 * registered until gnutls_global_deinit() is called. If the extension type
756 * is already registered then %GNUTLS_E_ALREADY_REGISTERED will be returned.
757 *
758 * Each registered extension can store temporary data into the gnutls_session_t
759 * structure using gnutls_ext_set_data(), and they can be retrieved using
760 * gnutls_ext_get_data().
761 *
762 * Any extensions registered with this function are valid for the client
763 * and TLS1.2 server hello (or encrypted extensions for TLS1.3).
764 *
765 * This function is not thread safe.
766 *
767 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
768 *
769 * Since: 3.4.0
770 **/
771 int
gnutls_ext_register(const char * name,int id,gnutls_ext_parse_type_t parse_point,gnutls_ext_recv_func recv_func,gnutls_ext_send_func send_func,gnutls_ext_deinit_data_func deinit_func,gnutls_ext_pack_func pack_func,gnutls_ext_unpack_func unpack_func)772 gnutls_ext_register(const char *name, int id, gnutls_ext_parse_type_t parse_point,
773 gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func,
774 gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func,
775 gnutls_ext_unpack_func unpack_func)
776 {
777 hello_ext_entry_st *tmp_mod;
778 unsigned i;
779 unsigned gid = GNUTLS_EXTENSION_MAX+1;
780
781 for (i = 0; i < MAX_EXT_TYPES; i++) {
782 if (!extfunc[i])
783 continue;
784
785 if (extfunc[i]->tls_id == id)
786 return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
787
788 if (extfunc[i]->gid >= gid)
789 gid = extfunc[i]->gid + 1;
790 }
791
792 if (gid > GNUTLS_EXTENSION_MAX_VALUE || gid >= sizeof(extfunc)/sizeof(extfunc[0]))
793 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
794
795 tmp_mod = gnutls_calloc(1, sizeof(*tmp_mod));
796 if (tmp_mod == NULL)
797 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
798
799 tmp_mod->name = gnutls_strdup(name);
800 tmp_mod->free_struct = 1;
801 tmp_mod->tls_id = id;
802 tmp_mod->gid = gid;
803 tmp_mod->client_parse_point = parse_point;
804 tmp_mod->server_parse_point = parse_point;
805 tmp_mod->recv_func = recv_func;
806 tmp_mod->send_func = send_func;
807 tmp_mod->deinit_func = deinit_func;
808 tmp_mod->pack_func = pack_func;
809 tmp_mod->unpack_func = unpack_func;
810 tmp_mod->validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
811 GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS;
812
813 assert(extfunc[gid] == NULL);
814 extfunc[gid] = tmp_mod;
815
816 return 0;
817 }
818
819 #define VALIDITY_MASK (GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | \
820 GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | \
821 GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_HRR)
822
823 /**
824 * gnutls_session_ext_register:
825 * @session: the session for which this extension will be set
826 * @name: the name of the extension to register
827 * @id: the numeric id of the extension
828 * @parse_point: the parse type of the extension (see gnutls_ext_parse_type_t)
829 * @recv_func: a function to receive the data
830 * @send_func: a function to send the data
831 * @deinit_func: a function deinitialize any private data
832 * @pack_func: a function which serializes the extension's private data (used on session packing for resumption)
833 * @unpack_func: a function which will deserialize the extension's private data
834 * @flags: must be zero or flags from %gnutls_ext_flags_t
835 *
836 * This function will register a new extension type. The extension will be
837 * only usable within the registered session. If the extension type
838 * is already registered then %GNUTLS_E_ALREADY_REGISTERED will be returned,
839 * unless the flag %GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL is specified. The latter
840 * flag when specified can be used to override certain extensions introduced
841 * after 3.6.0. It is expected to be used by applications which handle
842 * custom extensions that are not currently supported in GnuTLS, but direct
843 * support for them may be added in the future.
844 *
845 * Each registered extension can store temporary data into the gnutls_session_t
846 * structure using gnutls_ext_set_data(), and they can be retrieved using
847 * gnutls_ext_get_data().
848 *
849 * The validity of the extension registered can be given by the appropriate flags
850 * of %gnutls_ext_flags_t. If no validity is given, then the registered extension
851 * will be valid for client and TLS1.2 server hello (or encrypted extensions for TLS1.3).
852 *
853 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
854 *
855 * Since: 3.5.5
856 **/
857 int
gnutls_session_ext_register(gnutls_session_t session,const char * name,int id,gnutls_ext_parse_type_t parse_point,gnutls_ext_recv_func recv_func,gnutls_ext_send_func send_func,gnutls_ext_deinit_data_func deinit_func,gnutls_ext_pack_func pack_func,gnutls_ext_unpack_func unpack_func,unsigned flags)858 gnutls_session_ext_register(gnutls_session_t session,
859 const char *name, int id, gnutls_ext_parse_type_t parse_point,
860 gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func,
861 gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func,
862 gnutls_ext_unpack_func unpack_func, unsigned flags)
863 {
864 hello_ext_entry_st tmp_mod;
865 hello_ext_entry_st *exts;
866 unsigned i;
867 unsigned gid = GNUTLS_EXTENSION_MAX+1;
868
869 /* reject handling any extensions which modify the TLS handshake
870 * in any way, or are mapped to an exported API. */
871 for (i = 0; i < GNUTLS_EXTENSION_MAX; i++) {
872 if (!extfunc[i])
873 continue;
874
875 if (extfunc[i]->tls_id == id) {
876 if (!(flags & GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL)) {
877 return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
878 } else if (extfunc[i]->cannot_be_overriden) {
879 return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
880 }
881 break;
882 }
883
884 if (extfunc[i]->gid >= gid)
885 gid = extfunc[i]->gid + 1;
886 }
887
888 for (i=0;i<session->internals.rexts_size;i++) {
889 if (session->internals.rexts[i].tls_id == id) {
890 return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
891 }
892
893 if (session->internals.rexts[i].gid >= gid)
894 gid = session->internals.rexts[i].gid + 1;
895 }
896
897 if (gid > GNUTLS_EXTENSION_MAX_VALUE)
898 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
899
900 memset(&tmp_mod, 0, sizeof(hello_ext_entry_st));
901 tmp_mod.name = gnutls_strdup(name);
902 tmp_mod.free_struct = 1;
903 tmp_mod.tls_id = id;
904 tmp_mod.gid = gid;
905 tmp_mod.client_parse_point = parse_point;
906 tmp_mod.server_parse_point = parse_point;
907 tmp_mod.recv_func = recv_func;
908 tmp_mod.send_func = send_func;
909 tmp_mod.deinit_func = deinit_func;
910 tmp_mod.pack_func = pack_func;
911 tmp_mod.unpack_func = unpack_func;
912 tmp_mod.validity = flags;
913
914 if ((tmp_mod.validity & VALIDITY_MASK) == 0) {
915 tmp_mod.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
916 GNUTLS_EXT_FLAG_EE;
917 }
918
919 if ((tmp_mod.validity & (GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)) == 0) {
920 if (IS_DTLS(session))
921 tmp_mod.validity |= GNUTLS_EXT_FLAG_DTLS;
922 else
923 tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS;
924 }
925
926 exts = gnutls_realloc(session->internals.rexts, (session->internals.rexts_size+1)*sizeof(*exts));
927 if (exts == NULL) {
928 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
929 }
930
931 session->internals.rexts = exts;
932
933 memcpy(&session->internals.rexts[session->internals.rexts_size], &tmp_mod, sizeof(hello_ext_entry_st));
934 session->internals.rexts_size++;
935
936 return 0;
937 }
938
939 /**
940 * gnutls_ext_set_data:
941 * @session: a #gnutls_session_t opaque pointer
942 * @tls_id: the numeric id of the extension
943 * @data: the private data to set
944 *
945 * This function allows an extension handler to store data in the current session
946 * and retrieve them later on. The set data will be deallocated using
947 * the gnutls_ext_deinit_data_func.
948 *
949 * Since: 3.4.0
950 **/
951 void
gnutls_ext_set_data(gnutls_session_t session,unsigned tls_id,gnutls_ext_priv_data_t data)952 gnutls_ext_set_data(gnutls_session_t session, unsigned tls_id,
953 gnutls_ext_priv_data_t data)
954 {
955 unsigned id = tls_id_to_gid(session, tls_id);
956 if (id == GNUTLS_EXTENSION_INVALID)
957 return;
958
959 _gnutls_hello_ext_set_priv(session, id, data);
960 }
961
962 /**
963 * gnutls_ext_get_data:
964 * @session: a #gnutls_session_t opaque pointer
965 * @tls_id: the numeric id of the extension
966 * @data: a pointer to the private data to retrieve
967 *
968 * This function retrieves any data previously stored with gnutls_ext_set_data().
969 *
970 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
971 *
972 * Since: 3.4.0
973 **/
974 int
gnutls_ext_get_data(gnutls_session_t session,unsigned tls_id,gnutls_ext_priv_data_t * data)975 gnutls_ext_get_data(gnutls_session_t session,
976 unsigned tls_id, gnutls_ext_priv_data_t *data)
977 {
978 unsigned id = tls_id_to_gid(session, tls_id);
979 if (id == GNUTLS_EXTENSION_INVALID)
980 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
981
982 return _gnutls_hello_ext_get_priv(session, id, data);
983 }
984
985 /**
986 * gnutls_ext_get_current_msg:
987 * @session: a #gnutls_session_t opaque pointer
988 *
989 * This function allows an extension handler to obtain the message
990 * this extension is being called from. The returned value is a single
991 * entry of the %gnutls_ext_flags_t enumeration. That is, if an
992 * extension was registered with the %GNUTLS_EXT_FLAG_HRR and
993 * %GNUTLS_EXT_FLAG_EE flags, the value when called during parsing of the
994 * encrypted extensions message will be %GNUTLS_EXT_FLAG_EE.
995 *
996 * If not called under an extension handler, its value is undefined.
997 *
998 * Since: 3.6.3
999 **/
gnutls_ext_get_current_msg(gnutls_session_t session)1000 unsigned gnutls_ext_get_current_msg(gnutls_session_t session)
1001 {
1002 return _gnutls_ext_get_msg(session);
1003 }
1004
1005 /**
1006 * gnutls_ext_get_name2:
1007 * @session: a #gnutls_session_t opaque pointer
1008 * @tls_id: is a TLS extension numeric ID
1009 * @parse_point: the parse type of the extension
1010 *
1011 * Convert a TLS extension numeric ID to a printable string.
1012 *
1013 * Returns: a pointer to a string that contains the name of the
1014 * specified cipher, or %NULL.
1015 **/
gnutls_ext_get_name2(gnutls_session_t session,unsigned int tls_id,gnutls_ext_parse_type_t parse_point)1016 const char *gnutls_ext_get_name2(gnutls_session_t session, unsigned int tls_id,
1017 gnutls_ext_parse_type_t parse_point)
1018 {
1019 const struct hello_ext_entry_st *ext;
1020
1021 ext = tls_id_to_ext_entry(session, tls_id, parse_point);
1022 if (ext)
1023 return ext->name;
1024
1025 return NULL;
1026 }
1027
1028