Coverage Report

Created: 2025-12-31 06:37

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