Coverage Report

Created: 2026-10-14 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/algorithms/protocols.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
#include "gnutls_int.h"
24
#include "algorithms.h"
25
#include "errors.h"
26
#include "x509/common.h"
27
#include "c-strcase.h"
28
29
/* TLS Versions */
30
31
static SYSTEM_CONFIG_OR_CONST version_entry_st sup_versions[] = {
32
  { .name = "SSL3.0",
33
    .id = GNUTLS_SSL3,
34
    .age = 0,
35
    .major = 3,
36
    .minor = 0,
37
    .transport = GNUTLS_STREAM,
38
#ifdef ENABLE_SSL3
39
    .supported = 1,
40
#endif
41
    .explicit_iv = 0,
42
    .extensions = 0,
43
    .selectable_sighash = 0,
44
    .selectable_prf = 0,
45
    .obsolete = 1,
46
    .only_extension = 0,
47
    .tls_sig_sem = SIG_SEM_PRE_TLS12,
48
    .false_start = 0 },
49
  { .name = "TLS1.0",
50
    .id = GNUTLS_TLS1,
51
    .age = 1,
52
    .major = 3,
53
    .minor = 1,
54
    .transport = GNUTLS_STREAM,
55
#ifdef ENABLE_TLS1_1
56
    .supported = 1,
57
#endif
58
    .explicit_iv = 0,
59
    .extensions = 1,
60
    .selectable_sighash = 0,
61
    .selectable_prf = 0,
62
    .obsolete = 1,
63
    .only_extension = 0,
64
    .tls_sig_sem = SIG_SEM_PRE_TLS12,
65
    .false_start = 0 },
66
  { .name = "TLS1.1",
67
    .id = GNUTLS_TLS1_1,
68
    .age = 2,
69
    .major = 3,
70
    .minor = 2,
71
    .transport = GNUTLS_STREAM,
72
#ifdef ENABLE_TLS1_1
73
    .supported = 1,
74
#endif
75
    .explicit_iv = 1,
76
    .extensions = 1,
77
    .selectable_sighash = 0,
78
    .selectable_prf = 0,
79
    .obsolete = 1,
80
    .only_extension = 0,
81
    .tls_sig_sem = SIG_SEM_PRE_TLS12,
82
    .false_start = 0 },
83
  { .name = "TLS1.2",
84
    .id = GNUTLS_TLS1_2,
85
    .age = 3,
86
    .major = 3,
87
    .minor = 3,
88
    .transport = GNUTLS_STREAM,
89
    .supported = 1,
90
    .explicit_iv = 1,
91
    .extensions = 1,
92
    .selectable_sighash = 1,
93
    .selectable_prf = 1,
94
    .obsolete = 0,
95
    .only_extension = 0,
96
    .tls_sig_sem = SIG_SEM_PRE_TLS12,
97
    .false_start = 1 },
98
  { .name = "TLS1.3",
99
    .id = GNUTLS_TLS1_3,
100
    .age = 5,
101
    .major = 3,
102
    .minor = 4,
103
    .transport = GNUTLS_STREAM,
104
    .supported = 1,
105
    .explicit_iv = 0,
106
    .extensions = 1,
107
    .selectable_sighash = 1,
108
    .selectable_prf = 1,
109
    .tls13_sem = 1,
110
    .obsolete = 0,
111
    .only_extension = 1,
112
    .post_handshake_auth = 1,
113
    .multi_ocsp = 1,
114
    .key_shares = 1,
115
    .false_start = 0, /* doesn't make sense */
116
    .tls_sig_sem = SIG_SEM_TLS13 },
117
  { .name = "DTLS0.9", /* Cisco AnyConnect (based on about OpenSSL 0.9.8e) */
118
    .id = GNUTLS_DTLS0_9,
119
    .age = 200,
120
    .major = 1,
121
    .minor = 0,
122
    .transport = GNUTLS_DGRAM,
123
#ifdef ENABLE_TLS1_1
124
    .supported = 1,
125
#endif
126
    .explicit_iv = 1,
127
    .extensions = 1,
128
    .selectable_sighash = 0,
129
    .selectable_prf = 0,
130
    .obsolete = 1,
131
    .only_extension = 0,
132
    .tls_sig_sem = SIG_SEM_PRE_TLS12,
133
    .false_start = 0 },
134
  { .name = "DTLS1.0",
135
    .id = GNUTLS_DTLS1_0,
136
    .age = 201,
137
    .major = 254,
138
    .minor = 255,
139
    .transport = GNUTLS_DGRAM,
140
#ifdef ENABLE_TLS1_1
141
    .supported = 1,
142
#endif
143
    .explicit_iv = 1,
144
    .extensions = 1,
145
    .selectable_sighash = 0,
146
    .selectable_prf = 0,
147
    .obsolete = 1,
148
    .only_extension = 0,
149
    .tls_sig_sem = SIG_SEM_PRE_TLS12,
150
    .false_start = 0 },
151
  { .name = "DTLS1.2",
152
    .id = GNUTLS_DTLS1_2,
153
    .age = 202,
154
    .major = 254,
155
    .minor = 253,
156
    .transport = GNUTLS_DGRAM,
157
    .supported = 1,
158
    .explicit_iv = 1,
159
    .extensions = 1,
160
    .selectable_sighash = 1,
161
    .selectable_prf = 1,
162
    .obsolete = 0,
163
    .only_extension = 0,
164
    .tls_sig_sem = SIG_SEM_PRE_TLS12,
165
    .false_start = 1 },
166
  { NULL, 0, 0, 0, 0 }
167
};
168
169
const version_entry_st *version_to_entry(gnutls_protocol_t version)
170
0
{
171
0
  const version_entry_st *p;
172
173
0
  for (p = sup_versions; p->name != NULL; p++)
174
0
    if (p->id == version)
175
0
      return p;
176
0
  return NULL;
177
0
}
178
179
const version_entry_st *nversion_to_entry(uint8_t major, uint8_t minor)
180
0
{
181
0
  const version_entry_st *p;
182
183
0
  for (p = sup_versions; p->name != NULL; p++) {
184
0
    if ((p->major == major) && (p->minor == minor))
185
0
      return p;
186
0
  }
187
0
  return NULL;
188
0
}
189
190
static int version_is_valid_for_session(gnutls_session_t session,
191
          const version_entry_st *v)
192
0
{
193
0
  if (!v->supported &&
194
0
      !(v->supported_revertible && _gnutls_allowlisting_mode()))
195
0
    return 0;
196
0
  if (v->transport != session->internals.transport)
197
0
    return 0;
198
0
  return 1;
199
0
}
200
201
/* This is only called by cfg_apply in priority.c, in blocklisting mode. */
202
int _gnutls_version_mark_disabled(gnutls_protocol_t version)
203
0
{
204
0
#ifndef DISABLE_SYSTEM_CONFIG
205
0
  version_entry_st *p;
206
207
0
  for (p = sup_versions; p->name != NULL; p++)
208
0
    if (p->id == version) {
209
0
      p->supported = false;
210
0
      return 0;
211
0
    }
212
0
#endif
213
0
  return GNUTLS_E_INVALID_REQUEST;
214
0
}
215
216
/* This is only called by cfg_apply in priority.c, in allowlisting mode. */
217
void _gnutls_version_mark_disabled_all(void)
218
0
{
219
0
#ifndef DISABLE_SYSTEM_CONFIG
220
0
  version_entry_st *p;
221
222
0
  for (p = sup_versions; p->name != NULL; p++) {
223
0
    p->supported = false;
224
0
    p->supported_revertible = true;
225
0
  }
226
0
#endif
227
0
}
228
229
int _gnutls_protocol_set_enabled(gnutls_protocol_t version,
230
         unsigned int enabled)
231
0
{
232
0
#ifndef DISABLE_SYSTEM_CONFIG
233
0
  version_entry_st *p;
234
235
0
  for (p = sup_versions; p->name != NULL; p++)
236
0
    if (p->id == version) {
237
0
      if (!p->supported_revertible) {
238
0
        return gnutls_assert_val(
239
0
          GNUTLS_E_INVALID_REQUEST);
240
0
      }
241
0
      p->supported = enabled;
242
0
      return 0;
243
0
    }
244
0
#endif
245
0
  return GNUTLS_E_INVALID_REQUEST;
246
0
}
247
248
/* Return the priority of the provided version number */
249
int _gnutls_version_priority(gnutls_session_t session,
250
           gnutls_protocol_t version)
251
0
{
252
0
  unsigned int i;
253
254
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
255
0
       i++) {
256
0
    if (session->internals.priorities->protocol.priorities[i] ==
257
0
        version)
258
0
      return i;
259
0
  }
260
0
  return -1;
261
0
}
262
263
/* Returns the lowest TLS version number in the priorities.
264
 */
265
const version_entry_st *_gnutls_version_lowest(gnutls_session_t session)
266
0
{
267
0
  unsigned int i;
268
0
  gnutls_protocol_t cur_prot;
269
0
  const version_entry_st *v, *min_v = NULL;
270
0
  const version_entry_st *backup = NULL;
271
272
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
273
0
       i++) {
274
0
    cur_prot =
275
0
      session->internals.priorities->protocol.priorities[i];
276
0
    v = version_to_entry(cur_prot);
277
278
0
    if (v != NULL && version_is_valid_for_session(session, v)) {
279
0
      if (min_v == NULL) {
280
0
        if (v->obsolete != 0)
281
0
          backup = v;
282
0
        else
283
0
          min_v = v;
284
0
      } else if (v->obsolete == 0 && v->age < min_v->age) {
285
0
        min_v = v;
286
0
      }
287
0
    }
288
0
  }
289
290
0
  if (min_v == NULL)
291
0
    return backup;
292
293
0
  return min_v;
294
0
}
295
296
/* Returns the maximum version in the priorities
297
 */
298
const version_entry_st *_gnutls_version_max(gnutls_session_t session)
299
0
{
300
0
  unsigned int i;
301
0
  gnutls_protocol_t cur_prot;
302
0
  const version_entry_st *p, *max = NULL;
303
304
0
  if (!session->internals.priorities) {
305
0
    gnutls_assert();
306
0
    return NULL;
307
0
  }
308
309
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
310
0
       i++) {
311
0
    cur_prot =
312
0
      session->internals.priorities->protocol.priorities[i];
313
314
0
    for (p = sup_versions; p->name != NULL; p++) {
315
0
      if (p->id == cur_prot) {
316
#if !defined(ENABLE_SSL3) && !defined(ENABLE_TLS1_1)
317
        if (p->obsolete != 0)
318
          break;
319
#endif
320
0
        if (!p->supported &&
321
0
            !(p->supported_revertible &&
322
0
              _gnutls_allowlisting_mode()))
323
0
          break;
324
325
0
        if (p->transport !=
326
0
            session->internals.transport)
327
0
          break;
328
329
0
        if (p->tls13_sem && (session->internals.flags &
330
0
                 INT_FLAG_NO_TLS13))
331
0
          break;
332
333
0
        if (max == NULL || cur_prot > max->id) {
334
0
          max = p;
335
0
        }
336
337
0
        break;
338
0
      }
339
0
    }
340
0
  }
341
342
0
  return max;
343
0
}
344
345
const version_entry_st *_gnutls_legacy_version_max(gnutls_session_t session)
346
0
{
347
0
  const version_entry_st *max = _gnutls_version_max(session);
348
349
0
  if (max && max->only_extension != 0) {
350
    /* TLS 1.3 or later found */
351
0
    if (max->transport == GNUTLS_STREAM) {
352
0
      return version_to_entry(GNUTLS_TLS1_2);
353
0
    } else {
354
0
      return version_to_entry(GNUTLS_DTLS1_2);
355
0
    }
356
0
  }
357
358
0
  return max;
359
0
}
360
361
/* Returns the number of bytes written to buffer or a negative
362
 * error code. It will return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
363
 * if there is no version >= TLS 1.3.
364
 */
365
int _gnutls_write_supported_versions(gnutls_session_t session, uint8_t *buffer,
366
             ssize_t buffer_size)
367
0
{
368
0
  gnutls_protocol_t cur_prot;
369
0
  size_t written_bytes = 0;
370
0
  unsigned at_least_one_new = 0;
371
0
  unsigned i;
372
0
  const version_entry_st *p;
373
374
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
375
0
       i++) {
376
0
    cur_prot =
377
0
      session->internals.priorities->protocol.priorities[i];
378
379
0
    for (p = sup_versions; p->name != NULL; p++) {
380
0
      if (p->id == cur_prot) {
381
#if !defined(ENABLE_SSL3) && !defined(ENABLE_TLS1_1)
382
        if (p->obsolete != 0)
383
          break;
384
#endif
385
386
0
        if (!p->supported &&
387
0
            !(p->supported_revertible &&
388
0
              _gnutls_allowlisting_mode()))
389
0
          break;
390
391
0
        if (p->transport !=
392
0
            session->internals.transport)
393
0
          break;
394
395
0
        if (p->only_extension)
396
0
          at_least_one_new = 1;
397
398
0
        if (buffer_size > 2) {
399
0
          _gnutls_debug_log(
400
0
            "Advertizing version %d.%d\n",
401
0
            (int)p->major, (int)p->minor);
402
0
          buffer[0] = p->major;
403
0
          buffer[1] = p->minor;
404
0
          written_bytes += 2;
405
0
          buffer += 2;
406
0
        }
407
408
0
        buffer_size -= 2;
409
410
0
        if (buffer_size <= 0)
411
0
          goto finish;
412
413
0
        break;
414
0
      }
415
0
    }
416
0
  }
417
418
0
finish:
419
0
  if (written_bytes == 0)
420
0
    return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
421
422
0
  if (at_least_one_new == 0)
423
0
    return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
424
425
0
  return written_bytes;
426
0
}
427
428
/* Returns true (1) if the given version is higher than the highest supported
429
 * and (0) otherwise */
430
unsigned _gnutls_version_is_too_high(gnutls_session_t session, uint8_t major,
431
             uint8_t minor)
432
0
{
433
0
  const version_entry_st *e;
434
435
0
  e = _gnutls_legacy_version_max(session);
436
0
  if (e ==
437
0
      NULL) /* we don't know; but that means something is unconfigured */
438
0
    return 1;
439
440
0
  if (e->transport == GNUTLS_DGRAM) {
441
0
    if (major < e->major)
442
0
      return 1;
443
444
0
    if (e->major == major && minor < e->minor)
445
0
      return 1;
446
0
  } else {
447
0
    if (major > e->major)
448
0
      return 1;
449
450
0
    if (e->major == major && minor > e->minor)
451
0
      return 1;
452
0
  }
453
454
0
  return 0;
455
0
}
456
457
/**
458
 * gnutls_protocol_get_name:
459
 * @version: is a (gnutls) version number
460
 *
461
 * Convert a #gnutls_protocol_t value to a string.
462
 *
463
 * Returns: a string that contains the name of the specified TLS
464
 *   version (e.g., "TLS1.0"), or %NULL.
465
 **/
466
const char *gnutls_protocol_get_name(gnutls_protocol_t version)
467
0
{
468
0
  const version_entry_st *p;
469
  /* avoid prefix */
470
0
  for (p = sup_versions; p->name != NULL; p++)
471
0
    if (p->id == version)
472
0
      return p->name;
473
0
  return NULL;
474
0
}
475
476
/**
477
 * gnutls_protocol_get_id:
478
 * @name: is a protocol name
479
 *
480
 * The names are compared in a case insensitive way.
481
 *
482
 * Returns: an id of the specified protocol, or
483
 * %GNUTLS_VERSION_UNKNOWN on error.
484
 **/
485
gnutls_protocol_t gnutls_protocol_get_id(const char *name)
486
0
{
487
0
  const version_entry_st *p;
488
0
  gnutls_protocol_t ret = GNUTLS_VERSION_UNKNOWN;
489
490
0
  for (p = sup_versions; p->name != NULL; p++) {
491
0
    if (c_strcasecmp(p->name, name) == 0) {
492
0
      ret = p->id;
493
0
      break;
494
0
    }
495
0
  }
496
497
0
  return ret;
498
0
}
499
500
/**
501
 * gnutls_protocol_list:
502
 *
503
 * Get a list of supported protocols, e.g. SSL 3.0, TLS 1.0 etc.
504
 *
505
 * This function is not thread safe.
506
 *
507
 * Returns: a (0)-terminated list of #gnutls_protocol_t integers
508
 * indicating the available protocols.
509
 *
510
 **/
511
const gnutls_protocol_t *gnutls_protocol_list(void)
512
0
{
513
0
  const version_entry_st *p;
514
0
  static gnutls_protocol_t supported_protocols[MAX_ALGOS] = { 0 };
515
516
0
  if (supported_protocols[0] == 0) {
517
0
    int i = 0;
518
519
0
    for (p = sup_versions; p->name != NULL; p++) {
520
0
      if (!p->supported)
521
0
        continue;
522
0
      supported_protocols[i++] = p->id;
523
0
    }
524
0
    supported_protocols[i++] = 0;
525
0
  }
526
527
0
  return supported_protocols;
528
0
}
529
530
/* Return all versions, including non-supported ones.
531
 */
532
const gnutls_protocol_t *_gnutls_protocol_list(void)
533
0
{
534
0
  const version_entry_st *p;
535
0
  static gnutls_protocol_t protocols[MAX_ALGOS] = { 0 };
536
537
0
  if (protocols[0] == 0) {
538
0
    int i = 0;
539
540
0
    for (p = sup_versions; p->name != NULL; p++) {
541
0
      protocols[i++] = p->id;
542
0
    }
543
0
    protocols[i++] = 0;
544
0
  }
545
546
0
  return protocols;
547
0
}
548
549
/* Returns a version number given the major and minor numbers.
550
 */
551
gnutls_protocol_t _gnutls_version_get(uint8_t major, uint8_t minor)
552
0
{
553
0
  const version_entry_st *p;
554
0
  int ret = GNUTLS_VERSION_UNKNOWN;
555
556
0
  for (p = sup_versions; p->name != NULL; p++)
557
0
    if ((p->major == major) && (p->minor == minor))
558
0
      ret = p->id;
559
0
  return ret;
560
0
}
561
562
/* Version Functions */
563
564
int _gnutls_nversion_is_supported(gnutls_session_t session, unsigned char major,
565
          unsigned char minor)
566
0
{
567
0
  const version_entry_st *p;
568
0
  int version = 0;
569
570
0
  for (p = sup_versions; p->name != NULL; p++) {
571
0
    if (p->major == major && p->minor == minor) {
572
#if !defined(ENABLE_SSL3) && !defined(ENABLE_TLS1_1)
573
      if (p->obsolete != 0)
574
        return 0;
575
#endif
576
0
      if (p->tls13_sem &&
577
0
          (session->internals.flags & INT_FLAG_NO_TLS13))
578
0
        return 0;
579
580
0
      if (!p->supported && !(p->supported_revertible &&
581
0
                 _gnutls_allowlisting_mode()))
582
0
        return 0;
583
584
0
      if (p->transport != session->internals.transport)
585
0
        return 0;
586
587
0
      version = p->id;
588
0
      break;
589
0
    }
590
0
  }
591
592
0
  if (version == 0)
593
0
    return 0;
594
595
0
  if (_gnutls_version_priority(session, version) < 0)
596
0
    return 0; /* disabled by the user */
597
0
  else
598
0
    return 1;
599
0
}