Coverage Report

Created: 2026-09-28 07:30

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