Coverage Report

Created: 2023-03-26 07:33

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