Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/algorithms/protocols.c
Line
Count
Source (jump to first uncovered line)
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
0
{
163
0
  const version_entry_st *p;
164
165
0
  for (p = sup_versions; p->name != NULL; p++)
166
0
    if (p->id == version)
167
0
      return p;
168
0
  return NULL;
169
0
}
170
171
const version_entry_st *nversion_to_entry(uint8_t major, uint8_t minor)
172
0
{
173
0
  const version_entry_st *p;
174
175
0
  for (p = sup_versions; p->name != NULL; p++) {
176
0
    if ((p->major == major) && (p->minor == minor))
177
0
      return p;
178
0
  }
179
0
  return NULL;
180
0
}
181
182
static int version_is_valid_for_session(gnutls_session_t session,
183
          const version_entry_st *v)
184
0
{
185
0
  if (!v->supported &&
186
0
      !(v->supported_revertible && _gnutls_allowlisting_mode()))
187
0
    return 0;
188
0
  if (v->transport != session->internals.transport)
189
0
    return 0;
190
0
  return 1;
191
0
}
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
0
{
244
0
  unsigned int i;
245
246
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
247
0
       i++) {
248
0
    if (session->internals.priorities->protocol.priorities[i] ==
249
0
        version)
250
0
      return i;
251
0
  }
252
0
  return -1;
253
0
}
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
0
{
259
0
  unsigned int i;
260
0
  gnutls_protocol_t cur_prot;
261
0
  const version_entry_st *v, *min_v = NULL;
262
0
  const version_entry_st *backup = NULL;
263
264
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
265
0
       i++) {
266
0
    cur_prot =
267
0
      session->internals.priorities->protocol.priorities[i];
268
0
    v = version_to_entry(cur_prot);
269
270
0
    if (v != NULL && version_is_valid_for_session(session, v)) {
271
0
      if (min_v == NULL) {
272
0
        if (v->obsolete != 0)
273
0
          backup = v;
274
0
        else
275
0
          min_v = v;
276
0
      } else if (v->obsolete == 0 && v->age < min_v->age) {
277
0
        min_v = v;
278
0
      }
279
0
    }
280
0
  }
281
282
0
  if (min_v == NULL)
283
0
    return backup;
284
285
0
  return min_v;
286
0
}
287
288
/* Returns the maximum version in the priorities
289
 */
290
const version_entry_st *_gnutls_version_max(gnutls_session_t session)
291
0
{
292
0
  unsigned int i;
293
0
  gnutls_protocol_t cur_prot;
294
0
  const version_entry_st *p, *max = NULL;
295
296
0
  if (!session->internals.priorities) {
297
0
    gnutls_assert();
298
0
    return NULL;
299
0
  }
300
301
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
302
0
       i++) {
303
0
    cur_prot =
304
0
      session->internals.priorities->protocol.priorities[i];
305
306
0
    for (p = sup_versions; p->name != NULL; p++) {
307
0
      if (p->id == cur_prot) {
308
0
#ifndef ENABLE_SSL3
309
0
        if (p->obsolete != 0)
310
0
          break;
311
0
#endif
312
0
        if (!p->supported &&
313
0
            !(p->supported_revertible &&
314
0
              _gnutls_allowlisting_mode()))
315
0
          break;
316
317
0
        if (p->transport !=
318
0
            session->internals.transport)
319
0
          break;
320
321
0
        if (p->tls13_sem && (session->internals.flags &
322
0
                 INT_FLAG_NO_TLS13))
323
0
          break;
324
325
0
        if (max == NULL || cur_prot > max->id) {
326
0
          max = p;
327
0
        }
328
329
0
        break;
330
0
      }
331
0
    }
332
0
  }
333
334
0
  return max;
335
0
}
336
337
const version_entry_st *_gnutls_legacy_version_max(gnutls_session_t session)
338
0
{
339
0
  const version_entry_st *max = _gnutls_version_max(session);
340
341
0
  if (max && max->only_extension != 0) {
342
    /* TLS 1.3 or later found */
343
0
    if (max->transport == GNUTLS_STREAM) {
344
0
      return version_to_entry(GNUTLS_TLS1_2);
345
0
    } else {
346
0
      return version_to_entry(GNUTLS_DTLS1_2);
347
0
    }
348
0
  }
349
350
0
  return max;
351
0
}
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
0
{
360
0
  gnutls_protocol_t cur_prot;
361
0
  size_t written_bytes = 0;
362
0
  unsigned at_least_one_new = 0;
363
0
  unsigned i;
364
0
  const version_entry_st *p;
365
366
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
367
0
       i++) {
368
0
    cur_prot =
369
0
      session->internals.priorities->protocol.priorities[i];
370
371
0
    for (p = sup_versions; p->name != NULL; p++) {
372
0
      if (p->id == cur_prot) {
373
0
        if (p->obsolete != 0)
374
0
          break;
375
376
0
        if (!p->supported &&
377
0
            !(p->supported_revertible &&
378
0
              _gnutls_allowlisting_mode()))
379
0
          break;
380
381
0
        if (p->transport !=
382
0
            session->internals.transport)
383
0
          break;
384
385
0
        if (p->only_extension)
386
0
          at_least_one_new = 1;
387
388
0
        if (buffer_size > 2) {
389
0
          _gnutls_debug_log(
390
0
            "Advertizing version %d.%d\n",
391
0
            (int)p->major, (int)p->minor);
392
0
          buffer[0] = p->major;
393
0
          buffer[1] = p->minor;
394
0
          written_bytes += 2;
395
0
          buffer += 2;
396
0
        }
397
398
0
        buffer_size -= 2;
399
400
0
        if (buffer_size <= 0)
401
0
          goto finish;
402
403
0
        break;
404
0
      }
405
0
    }
406
0
  }
407
408
0
finish:
409
0
  if (written_bytes == 0)
410
0
    return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
411
412
0
  if (at_least_one_new == 0)
413
0
    return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
414
415
0
  return written_bytes;
416
0
}
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
0
{
423
0
  const version_entry_st *e;
424
425
0
  e = _gnutls_legacy_version_max(session);
426
0
  if (e ==
427
0
      NULL) /* we don't know; but that means something is unconfigured */
428
0
    return 1;
429
430
0
  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
0
  } else {
437
0
    if (major > e->major)
438
0
      return 1;
439
440
0
    if (e->major == major && minor > e->minor)
441
0
      return 1;
442
0
  }
443
444
0
  return 0;
445
0
}
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
0
{
477
0
  const version_entry_st *p;
478
0
  gnutls_protocol_t ret = GNUTLS_VERSION_UNKNOWN;
479
480
0
  for (p = sup_versions; p->name != NULL; p++) {
481
0
    if (c_strcasecmp(p->name, name) == 0) {
482
0
      ret = p->id;
483
0
      break;
484
0
    }
485
0
  }
486
487
0
  return ret;
488
0
}
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
0
{
557
0
  const version_entry_st *p;
558
0
  int version = 0;
559
560
0
  for (p = sup_versions; p->name != NULL; p++) {
561
0
    if (p->major == major && p->minor == minor) {
562
0
#ifndef ENABLE_SSL3
563
0
      if (p->obsolete != 0)
564
0
        return 0;
565
0
#endif
566
0
      if (p->tls13_sem &&
567
0
          (session->internals.flags & INT_FLAG_NO_TLS13))
568
0
        return 0;
569
570
0
      if (!p->supported && !(p->supported_revertible &&
571
0
                 _gnutls_allowlisting_mode()))
572
0
        return 0;
573
574
0
      if (p->transport != session->internals.transport)
575
0
        return 0;
576
577
0
      version = p->id;
578
0
      break;
579
0
    }
580
0
  }
581
582
0
  if (version == 0)
583
0
    return 0;
584
585
0
  if (_gnutls_version_priority(session, version) < 0)
586
0
    return 0; /* disabled by the user */
587
0
  else
588
0
    return 1;
589
0
}