Line data Source code
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 *
107 156769 : gid_to_ext_entry(gnutls_session_t session, extensions_t id)
108 : {
109 156769 : unsigned i;
110 :
111 156769 : assert(id < MAX_EXT_TYPES);
112 :
113 157283 : for (i=0;i<session->internals.rexts_size;i++) {
114 532 : if (session->internals.rexts[i].gid == id) {
115 : return &session->internals.rexts[i];
116 : }
117 : }
118 :
119 156751 : return extfunc[id];
120 : }
121 :
122 : static const hello_ext_entry_st *
123 1392050 : tls_id_to_ext_entry(gnutls_session_t session, uint16_t tls_id, gnutls_ext_parse_type_t parse_point)
124 : {
125 1392050 : unsigned i;
126 1392050 : const hello_ext_entry_st *e;
127 :
128 1395230 : for (i=0;i<session->internals.rexts_size;i++) {
129 3526 : if (session->internals.rexts[i].tls_id == tls_id) {
130 341 : e = &session->internals.rexts[i];
131 341 : goto done;
132 : }
133 : }
134 :
135 64549900 : for (i = 0; i < MAX_EXT_TYPES; i++) {
136 63655900 : if (!extfunc[i])
137 35343500 : continue;
138 :
139 28312400 : if (extfunc[i]->tls_id == tls_id) {
140 497768 : e = extfunc[i];
141 497768 : goto done;
142 : }
143 : }
144 :
145 : return NULL;
146 498109 : done:
147 498109 : if (parse_point == GNUTLS_EXT_ANY || (IS_SERVER(session) && e->server_parse_point == parse_point) ||
148 49378 : (!IS_SERVER(session) && e->client_parse_point == parse_point)) {
149 : return e;
150 : } else {
151 395819 : 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 : **/
165 15 : const char *gnutls_ext_get_name(unsigned int ext)
166 : {
167 15 : size_t i;
168 :
169 463 : for (i = 0; i < MAX_EXT_TYPES; i++) {
170 456 : if (!extfunc[i])
171 273 : continue;
172 :
173 183 : if (extfunc[i]->tls_id == ext)
174 8 : return extfunc[i]->name;
175 : }
176 :
177 : return NULL;
178 : }
179 :
180 : /* Returns %GNUTLS_EXTENSION_INVALID on error
181 : */
182 10 : static unsigned tls_id_to_gid(gnutls_session_t session, unsigned tls_id)
183 : {
184 10 : unsigned i;
185 :
186 10 : for (i=0; i < session->internals.rexts_size; i++) {
187 4 : if (session->internals.rexts[i].tls_id == tls_id)
188 4 : return session->internals.rexts[i].gid;
189 : }
190 :
191 168 : for (i = 0; i < MAX_EXT_TYPES; i++) {
192 168 : if (!extfunc[i])
193 12 : continue;
194 :
195 156 : if (extfunc[i]->tls_id == tls_id)
196 6 : 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
211 1392050 : int hello_ext_parse(void *_ctx, unsigned tls_id, const uint8_t *data, unsigned data_size)
212 : {
213 1392050 : hello_ext_ctx_st *ctx = _ctx;
214 1392050 : gnutls_session_t session = ctx->session;
215 1392050 : const hello_ext_entry_st *ext;
216 1392050 : int ret;
217 :
218 1392050 : if (tls_id == PRE_SHARED_KEY_TLS_ID) {
219 10838 : ctx->seen_pre_shared_key = 1;
220 1381220 : } 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 4 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
224 : }
225 :
226 1392050 : ext = tls_id_to_ext_entry(session, tls_id, ctx->parse_point);
227 1392050 : if (ext == NULL || ext->recv_func == NULL) {
228 1289850 : 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 102198 : if (IS_DTLS(session)) {
234 3282 : if (!(ext->validity & GNUTLS_EXT_FLAG_DTLS)) {
235 0 : gnutls_assert();
236 0 : goto ignore;
237 : }
238 : } else {
239 98916 : if (!(ext->validity & GNUTLS_EXT_FLAG_TLS)) {
240 0 : gnutls_assert();
241 0 : goto ignore;
242 : }
243 : }
244 :
245 102198 : if (session->security_parameters.entity == GNUTLS_CLIENT) {
246 10717 : if (!(ext->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) &&
247 10716 : !_gnutls_hello_ext_is_present(session, ext->gid)) {
248 6 : _gnutls_debug_log("EXT[%p]: Received unexpected extension '%s/%d'\n", session,
249 : ext->name, (int)tls_id);
250 6 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
251 : }
252 : }
253 :
254 102192 : if ((ext->validity & ctx->msg) == 0) {
255 4 : _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 4 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
259 : }
260 :
261 102188 : if (session->security_parameters.entity == GNUTLS_SERVER) {
262 91480 : ret = _gnutls_hello_ext_save(session, ext->gid, 1);
263 91421 : if (ret == 0)
264 59 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
265 : }
266 :
267 102129 : _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 102129 : _gnutls_ext_set_msg(session, ctx->msg);
273 102129 : if ((ret = ext->recv_func(session, data, data_size)) < 0) {
274 1826 : gnutls_assert();
275 1826 : return ret;
276 : }
277 :
278 : return 0;
279 :
280 1289850 : ignore:
281 1289850 : if (ext) {
282 92 : _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
290 100214 : _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 100214 : int ret;
296 100214 : hello_ext_ctx_st ctx;
297 :
298 100214 : msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
299 :
300 100214 : ctx.session = session;
301 100214 : ctx.msg = msg;
302 100214 : ctx.parse_point = parse_point;
303 100214 : ctx.seen_pre_shared_key = 0;
304 :
305 100214 : ret = _gnutls_extv_parse(&ctx, hello_ext_parse, data, data_size);
306 100214 : if (ret < 0)
307 3144 : return gnutls_assert_val(ret);
308 :
309 : return 0;
310 : }
311 :
312 : static
313 622589 : int hello_ext_send(void *_ctx, gnutls_buffer_st *buf)
314 : {
315 622589 : hello_ext_ctx_st *ctx = _ctx;
316 622589 : int ret;
317 622589 : const hello_ext_entry_st *p = ctx->ext;
318 622589 : gnutls_session_t session = ctx->session;
319 622589 : int appended;
320 622589 : size_t size_prev;
321 :
322 622589 : if (unlikely(p->send_func == NULL))
323 : return 0;
324 :
325 622589 : if (ctx->parse_point != GNUTLS_EXT_ANY &&
326 19550 : ((IS_SERVER(session) && p->server_parse_point != ctx->parse_point) ||
327 0 : (!IS_SERVER(session) && p->client_parse_point != ctx->parse_point))) {
328 : return 0;
329 : }
330 :
331 609295 : if (IS_DTLS(session)) {
332 15073 : if (!(p->validity & GNUTLS_EXT_FLAG_DTLS)) {
333 4806 : gnutls_assert();
334 4806 : goto skip;
335 : }
336 : } else {
337 594222 : if (!(p->validity & GNUTLS_EXT_FLAG_TLS)) {
338 0 : gnutls_assert();
339 0 : goto skip;
340 : }
341 : }
342 :
343 604489 : if ((ctx->msg & p->validity) == 0) {
344 276903 : goto skip;
345 : } else {
346 454018 : _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 327586 : ret = _gnutls_hello_ext_is_present(session, p->gid);
354 :
355 327586 : if (session->security_parameters.entity == GNUTLS_SERVER) {
356 : /* if client didn't advertise and the override flag is not present */
357 236541 : if (!(p->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) && ret == 0)
358 : return 0;
359 : } else {
360 91045 : if (ret != 0) /* already sent */
361 : return 0;
362 : }
363 :
364 :
365 150224 : size_prev = buf->length;
366 :
367 150224 : _gnutls_ext_set_msg(session, ctx->msg);
368 150224 : ret = p->send_func(session, buf);
369 150224 : if (ret < 0 && ret != GNUTLS_E_INT_RET_0) {
370 162 : return gnutls_assert_val(ret);
371 : }
372 :
373 150068 : appended = buf->length - size_prev;
374 :
375 : /* add this extension to the extension list, to know which extensions
376 : * to expect.
377 : */
378 150068 : if ((appended > 0 || ret == GNUTLS_E_INT_RET_0) &&
379 74269 : session->security_parameters.entity == GNUTLS_CLIENT) {
380 :
381 37511 : _gnutls_hello_ext_save(session, p->gid, 0);
382 : }
383 :
384 : return ret;
385 :
386 281709 : skip:
387 439451 : _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
394 24968 : _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 24968 : int pos, ret;
400 24968 : size_t i;
401 24968 : hello_ext_ctx_st ctx;
402 :
403 24968 : msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
404 :
405 24968 : ctx.session = session;
406 24968 : ctx.msg = msg;
407 24968 : ctx.parse_point = parse_point;
408 :
409 24968 : ret = _gnutls_extv_append_init(buf);
410 24968 : if (ret < 0)
411 0 : return gnutls_assert_val(ret);
412 :
413 24968 : pos = ret;
414 24968 : _gnutls_ext_set_extensions_offset(session, pos);
415 :
416 25065 : for (i=0; i < session->internals.rexts_size; i++) {
417 97 : ctx.ext = &session->internals.rexts[i];
418 97 : ret = _gnutls_extv_append(buf, session->internals.rexts[i].tls_id,
419 : &ctx, hello_ext_send);
420 97 : if (ret < 0)
421 0 : return gnutls_assert_val(ret);
422 :
423 97 : if (ret > 0)
424 97 : _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 1615120 : for (i = 0; i < MAX_EXT_TYPES; i++) {
432 1590310 : if (!extfunc[i])
433 967816 : continue;
434 :
435 622492 : ctx.ext = extfunc[i];
436 622492 : ret = _gnutls_extv_append(buf, extfunc[i]->tls_id,
437 : &ctx, hello_ext_send);
438 622492 : if (ret < 0)
439 162 : return gnutls_assert_val(ret);
440 :
441 622336 : if (ret > 0)
442 1590150 : _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 24812 : ret = _gnutls_extv_append_final(buf, pos, !(msg & GNUTLS_EXT_FLAG_EE));
448 24812 : if (ret < 0)
449 0 : return gnutls_assert_val(ret);
450 :
451 : return 0;
452 : }
453 :
454 : /* Global deinit and init of global extensions */
455 3384 : int _gnutls_hello_ext_init(void)
456 : {
457 3384 : return GNUTLS_E_SUCCESS;
458 : }
459 :
460 2185 : void _gnutls_hello_ext_deinit(void)
461 : {
462 2185 : unsigned i;
463 :
464 142025 : for (i = 0; i < MAX_EXT_TYPES; i++) {
465 139840 : if (!extfunc[i])
466 85135 : continue;
467 :
468 54705 : if (extfunc[i]->free_struct != 0) {
469 80 : gnutls_free(((hello_ext_entry_st *)extfunc[i])->name);
470 80 : gnutls_free(extfunc[i]);
471 : }
472 : }
473 2185 : }
474 :
475 : /* Packing of extension data (for use in resumption) */
476 34612 : static int pack_extension(gnutls_session_t session, const hello_ext_entry_st *extp,
477 : gnutls_buffer_st *packed)
478 : {
479 34612 : int ret;
480 34612 : int size_offset;
481 34612 : int cur_size;
482 34612 : gnutls_ext_priv_data_t data;
483 34612 : int rval = 0;
484 :
485 34612 : ret =
486 34612 : _gnutls_hello_ext_get_priv(session, extp->gid,
487 : &data);
488 34612 : if (ret >= 0 && extp->pack_func != NULL) {
489 5125 : BUFFER_APPEND_NUM(packed, extp->gid);
490 :
491 5125 : size_offset = packed->length;
492 5125 : BUFFER_APPEND_NUM(packed, 0);
493 :
494 5125 : cur_size = packed->length;
495 :
496 5125 : ret = extp->pack_func(data, packed);
497 5125 : if (ret < 0) {
498 0 : gnutls_assert();
499 0 : return ret;
500 : }
501 :
502 5125 : rval = 1;
503 : /* write the actual size */
504 39737 : _gnutls_write_uint32(packed->length - cur_size,
505 5125 : packed->data + size_offset);
506 : }
507 :
508 : return rval;
509 : }
510 :
511 6564 : int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed)
512 : {
513 6564 : unsigned int i;
514 6564 : int ret;
515 6564 : int total_exts_pos;
516 6564 : int n_exts = 0;
517 6564 : const struct hello_ext_entry_st *ext;
518 :
519 6564 : total_exts_pos = packed->length;
520 6564 : BUFFER_APPEND_NUM(packed, 0);
521 :
522 426660 : for (i = 0; i <= GNUTLS_EXTENSION_MAX_VALUE; i++) {
523 420096 : if (session->internals.used_exts & ((ext_track_t)1 << i)) {
524 :
525 34612 : ext = gid_to_ext_entry(session, i);
526 34612 : if (ext == NULL)
527 0 : continue;
528 :
529 34612 : ret = pack_extension(session, ext, packed);
530 34612 : if (ret < 0)
531 0 : return gnutls_assert_val(ret);
532 :
533 34612 : if (ret > 0)
534 5125 : n_exts++;
535 : }
536 : }
537 :
538 6564 : _gnutls_write_uint32(n_exts, packed->data + total_exts_pos);
539 :
540 6564 : return 0;
541 : }
542 :
543 18660 : int _gnutls_ext_set_full_client_hello(gnutls_session_t session,
544 : handshake_buffer_st *recv_buf)
545 : {
546 18660 : int ret;
547 18660 : gnutls_buffer_st *buf = &session->internals.full_client_hello;
548 :
549 18660 : _gnutls_buffer_clear(buf);
550 :
551 18660 : if ((ret = _gnutls_buffer_append_prefix(buf, 8, recv_buf->htype)) < 0)
552 0 : return gnutls_assert_val(ret);
553 18660 : if ((ret = _gnutls_buffer_append_prefix(buf, 24, recv_buf->data.length)) < 0)
554 0 : return gnutls_assert_val(ret);
555 18660 : if ((ret = _gnutls_buffer_append_data(buf, recv_buf->data.data, recv_buf->data.length)) < 0)
556 0 : return gnutls_assert_val(ret);
557 :
558 : return 0;
559 : }
560 :
561 2077 : unsigned _gnutls_ext_get_full_client_hello(gnutls_session_t session,
562 : gnutls_datum_t *d)
563 : {
564 2077 : gnutls_buffer_st *buf = &session->internals.full_client_hello;
565 :
566 2077 : if (!buf->length)
567 : return 0;
568 :
569 2077 : d->data = buf->data;
570 2077 : d->size = buf->length;
571 :
572 2077 : return 1;
573 : }
574 :
575 : static void
576 1340 : _gnutls_ext_set_resumed_session_data(gnutls_session_t session,
577 : extensions_t id,
578 : gnutls_ext_priv_data_t data)
579 : {
580 1340 : const struct hello_ext_entry_st *ext;
581 :
582 : /* If this happens we need to increase the max */
583 1340 : assert(id < MAX_EXT_TYPES);
584 :
585 1340 : ext = gid_to_ext_entry(session, id);
586 1340 : assert(ext != NULL);
587 :
588 1340 : if (session->internals.ext_data[id].resumed_set != 0)
589 0 : unset_resumed_ext_data(session, ext, id);
590 :
591 1340 : session->internals.ext_data[id].resumed_priv = data;
592 1340 : session->internals.ext_data[id].resumed_set = 1;
593 1340 : return;
594 : }
595 :
596 1322 : int _gnutls_hello_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed)
597 : {
598 1322 : int i, ret;
599 1322 : gnutls_ext_priv_data_t data;
600 1322 : int max_exts = 0;
601 1322 : extensions_t id;
602 1322 : int size_for_id, cur_pos;
603 1322 : const struct hello_ext_entry_st *ext;
604 :
605 1322 : BUFFER_POP_NUM(packed, max_exts);
606 2662 : for (i = 0; i < max_exts; i++) {
607 1340 : BUFFER_POP_NUM(packed, id);
608 1340 : BUFFER_POP_NUM(packed, size_for_id);
609 :
610 1340 : cur_pos = packed->length;
611 :
612 1340 : ext = gid_to_ext_entry(session, id);
613 1340 : if (ext == NULL || ext->unpack_func == NULL) {
614 0 : gnutls_assert();
615 0 : return GNUTLS_E_PARSING_ERROR;
616 : }
617 :
618 1340 : ret = ext->unpack_func(packed, &data);
619 1340 : if (ret < 0) {
620 0 : gnutls_assert();
621 0 : return ret;
622 : }
623 :
624 : /* verify that unpack read the correct bytes */
625 1340 : cur_pos = cur_pos - packed->length;
626 1340 : if (cur_pos /* read length */ != size_for_id) {
627 0 : gnutls_assert();
628 0 : return GNUTLS_E_PARSING_ERROR;
629 : }
630 :
631 1340 : _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
641 61047 : unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
642 : {
643 61047 : if (session->internals.ext_data[idx].set == 0)
644 : return;
645 :
646 58604 : if (ext && ext->deinit_func && session->internals.ext_data[idx].priv != NULL)
647 52678 : ext->deinit_func(session->internals.ext_data[idx].priv);
648 58604 : session->internals.ext_data[idx].set = 0;
649 : }
650 :
651 : void
652 1918 : _gnutls_hello_ext_unset_priv(gnutls_session_t session,
653 : extensions_t id)
654 : {
655 1918 : const struct hello_ext_entry_st *ext;
656 :
657 1918 : ext = gid_to_ext_entry(session, id);
658 1918 : if (ext)
659 1918 : unset_ext_data(session, ext, id);
660 1918 : }
661 :
662 58715 : static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
663 : {
664 58715 : if (session->internals.ext_data[idx].resumed_set == 0)
665 : return;
666 :
667 1329 : if (ext && ext->deinit_func && session->internals.ext_data[idx].resumed_priv) {
668 1329 : ext->deinit_func(session->internals.ext_data[idx].resumed_priv);
669 : }
670 1329 : session->internals.ext_data[idx].resumed_set = 0;
671 : }
672 :
673 : /* Deinitializes all data that are associated with TLS extensions.
674 : */
675 23001 : void _gnutls_hello_ext_priv_deinit(gnutls_session_t session)
676 : {
677 23001 : unsigned int i;
678 23001 : const struct hello_ext_entry_st *ext;
679 :
680 1495060 : for (i = 0; i < MAX_EXT_TYPES; i++) {
681 1472060 : if (!session->internals.ext_data[i].set && !session->internals.ext_data[i].resumed_set)
682 1413350 : continue;
683 :
684 58715 : ext = gid_to_ext_entry(session, i);
685 58715 : if (ext) {
686 58715 : unset_ext_data(session, ext, i);
687 58715 : unset_resumed_ext_data(session, ext, i);
688 : }
689 : }
690 23001 : }
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
697 58844 : _gnutls_hello_ext_set_priv(gnutls_session_t session, extensions_t id,
698 : gnutls_ext_priv_data_t data)
699 : {
700 58844 : const struct hello_ext_entry_st *ext;
701 :
702 58844 : assert(id < MAX_EXT_TYPES);
703 :
704 58844 : ext = gid_to_ext_entry(session, id);
705 58844 : assert(ext != NULL);
706 :
707 58844 : if (session->internals.ext_data[id].set != 0) {
708 414 : unset_ext_data(session, ext, id);
709 : }
710 58844 : session->internals.ext_data[id].priv = data;
711 58844 : session->internals.ext_data[id].set = 1;
712 :
713 58844 : return;
714 : }
715 :
716 : int
717 216761 : _gnutls_hello_ext_get_priv(gnutls_session_t session,
718 : extensions_t id, gnutls_ext_priv_data_t * data)
719 : {
720 216761 : if (session->internals.ext_data[id].set != 0) {
721 105880 : *data =
722 105880 : session->internals.ext_data[id].priv;
723 105880 : return 0;
724 : }
725 :
726 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
727 : }
728 :
729 : int
730 4443 : _gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,
731 : extensions_t id,
732 : gnutls_ext_priv_data_t * data)
733 : {
734 4443 : if (session->internals.ext_data[id].resumed_set != 0) {
735 143 : *data =
736 143 : session->internals.ext_data[id].resumed_priv;
737 143 : 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
772 82 : 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 82 : hello_ext_entry_st *tmp_mod;
778 82 : unsigned i;
779 82 : unsigned gid = GNUTLS_EXTENSION_MAX+1;
780 :
781 5330 : for (i = 0; i < MAX_EXT_TYPES; i++) {
782 5248 : if (!extfunc[i])
783 1792 : continue;
784 :
785 3456 : if (extfunc[i]->tls_id == id)
786 0 : return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
787 :
788 3456 : if (extfunc[i]->gid >= gid)
789 1406 : gid = extfunc[i]->gid + 1;
790 : }
791 :
792 82 : if (gid > GNUTLS_EXTENSION_MAX_VALUE || gid >= sizeof(extfunc)/sizeof(extfunc[0]))
793 2 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
794 :
795 80 : tmp_mod = gnutls_calloc(1, sizeof(*tmp_mod));
796 80 : if (tmp_mod == NULL)
797 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
798 :
799 80 : tmp_mod->name = gnutls_strdup(name);
800 80 : tmp_mod->free_struct = 1;
801 80 : tmp_mod->tls_id = id;
802 80 : tmp_mod->gid = gid;
803 80 : tmp_mod->client_parse_point = parse_point;
804 80 : tmp_mod->server_parse_point = parse_point;
805 80 : tmp_mod->recv_func = recv_func;
806 80 : tmp_mod->send_func = send_func;
807 80 : tmp_mod->deinit_func = deinit_func;
808 80 : tmp_mod->pack_func = pack_func;
809 80 : tmp_mod->unpack_func = unpack_func;
810 80 : 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 80 : assert(extfunc[gid] == NULL);
814 80 : extfunc[gid] = tmp_mod;
815 :
816 80 : 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
858 90 : 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 90 : hello_ext_entry_st tmp_mod;
865 90 : hello_ext_entry_st *exts;
866 90 : unsigned i;
867 90 : 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 2381 : for (i = 0; i < GNUTLS_EXTENSION_MAX; i++) {
872 2304 : if (!extfunc[i])
873 90 : continue;
874 :
875 2214 : if (extfunc[i]->tls_id == id) {
876 13 : if (!(flags & GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL)) {
877 5 : return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
878 8 : } else if (extfunc[i]->cannot_be_overriden) {
879 2 : return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
880 : }
881 : break;
882 : }
883 :
884 2201 : if (extfunc[i]->gid >= gid)
885 0 : gid = extfunc[i]->gid + 1;
886 : }
887 :
888 223 : for (i=0;i<session->internals.rexts_size;i++) {
889 140 : if (session->internals.rexts[i].tls_id == id) {
890 0 : return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
891 : }
892 :
893 140 : if (session->internals.rexts[i].gid >= gid)
894 140 : gid = session->internals.rexts[i].gid + 1;
895 : }
896 :
897 83 : if (gid > GNUTLS_EXTENSION_MAX_VALUE)
898 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
899 :
900 83 : memset(&tmp_mod, 0, sizeof(hello_ext_entry_st));
901 83 : tmp_mod.name = gnutls_strdup(name);
902 83 : tmp_mod.free_struct = 1;
903 83 : tmp_mod.tls_id = id;
904 83 : tmp_mod.gid = gid;
905 83 : tmp_mod.client_parse_point = parse_point;
906 83 : tmp_mod.server_parse_point = parse_point;
907 83 : tmp_mod.recv_func = recv_func;
908 83 : tmp_mod.send_func = send_func;
909 83 : tmp_mod.deinit_func = deinit_func;
910 83 : tmp_mod.pack_func = pack_func;
911 83 : tmp_mod.unpack_func = unpack_func;
912 83 : tmp_mod.validity = flags;
913 :
914 83 : if ((tmp_mod.validity & VALIDITY_MASK) == 0) {
915 76 : tmp_mod.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
916 : GNUTLS_EXT_FLAG_EE;
917 : }
918 :
919 83 : if ((tmp_mod.validity & (GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)) == 0) {
920 83 : if (IS_DTLS(session))
921 0 : tmp_mod.validity |= GNUTLS_EXT_FLAG_DTLS;
922 : else
923 83 : tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS;
924 : }
925 :
926 83 : exts = gnutls_realloc(session->internals.rexts, (session->internals.rexts_size+1)*sizeof(*exts));
927 83 : if (exts == NULL) {
928 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
929 : }
930 :
931 83 : session->internals.rexts = exts;
932 :
933 83 : memcpy(&session->internals.rexts[session->internals.rexts_size], &tmp_mod, sizeof(hello_ext_entry_st));
934 83 : session->internals.rexts_size++;
935 :
936 83 : 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
952 5 : gnutls_ext_set_data(gnutls_session_t session, unsigned tls_id,
953 : gnutls_ext_priv_data_t data)
954 : {
955 5 : unsigned id = tls_id_to_gid(session, tls_id);
956 5 : if (id == GNUTLS_EXTENSION_INVALID)
957 : return;
958 :
959 5 : _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
975 5 : gnutls_ext_get_data(gnutls_session_t session,
976 : unsigned tls_id, gnutls_ext_priv_data_t *data)
977 : {
978 5 : unsigned id = tls_id_to_gid(session, tls_id);
979 5 : if (id == GNUTLS_EXTENSION_INVALID)
980 0 : return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
981 :
982 5 : 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 : **/
1000 1 : unsigned gnutls_ext_get_current_msg(gnutls_session_t session)
1001 : {
1002 1 : 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 : **/
1016 0 : const char *gnutls_ext_get_name2(gnutls_session_t session, unsigned int tls_id,
1017 : gnutls_ext_parse_type_t parse_point)
1018 : {
1019 0 : const struct hello_ext_entry_st *ext;
1020 :
1021 0 : ext = tls_id_to_ext_entry(session, tls_id, parse_point);
1022 0 : if (ext)
1023 0 : return ext->name;
1024 :
1025 : return NULL;
1026 : }
1027 :
|