Coverage Report

Created: 2025-01-28 06:58

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