Coverage Report

Created: 2023-03-26 08:33

/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
183
version_is_valid_for_session(gnutls_session_t session,
184
           const version_entry_st * v)
185
0
{
186
0
  if (!v->supported
187
0
      && !(v->supported_revertible && _gnutls_allowlisting_mode()))
188
0
    return 0;
189
0
  if (v->transport != session->internals.transport)
190
0
    return 0;
191
0
  return 1;
192
0
}
193
194
/* This is only called by cfg_apply in priority.c, in blocklisting mode. */
195
int _gnutls_version_mark_disabled(gnutls_protocol_t version)
196
0
{
197
0
#ifndef DISABLE_SYSTEM_CONFIG
198
0
  version_entry_st *p;
199
200
0
  for (p = sup_versions; p->name != NULL; p++)
201
0
    if (p->id == version) {
202
0
      p->supported = false;
203
0
      return 0;
204
0
    }
205
0
#endif
206
0
  return GNUTLS_E_INVALID_REQUEST;
207
0
}
208
209
/* This is only called by cfg_apply in priority.c, in allowlisting mode. */
210
void _gnutls_version_mark_disabled_all(void)
211
0
{
212
0
#ifndef DISABLE_SYSTEM_CONFIG
213
0
  version_entry_st *p;
214
215
0
  for (p = sup_versions; p->name != NULL; p++) {
216
0
    p->supported = false;
217
0
    p->supported_revertible = true;
218
0
  }
219
0
#endif
220
0
}
221
222
int
223
_gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled)
224
0
{
225
0
#ifndef DISABLE_SYSTEM_CONFIG
226
0
  version_entry_st *p;
227
228
0
  for (p = sup_versions; p->name != NULL; p++)
229
0
    if (p->id == version) {
230
0
      if (!p->supported_revertible) {
231
0
        return
232
0
            gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
233
0
      }
234
0
      p->supported = enabled;
235
0
      return 0;
236
0
    }
237
0
#endif
238
0
  return GNUTLS_E_INVALID_REQUEST;
239
0
}
240
241
/* Return the priority of the provided version number */
242
int
243
_gnutls_version_priority(gnutls_session_t session, gnutls_protocol_t version)
244
0
{
245
0
  unsigned int i;
246
247
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
248
0
       i++) {
249
0
    if (session->internals.priorities->protocol.priorities[i] ==
250
0
        version)
251
0
      return i;
252
0
  }
253
0
  return -1;
254
0
}
255
256
/* Returns the lowest TLS version number in the priorities.
257
 */
258
const version_entry_st *_gnutls_version_lowest(gnutls_session_t session)
259
0
{
260
0
  unsigned int i;
261
0
  gnutls_protocol_t cur_prot;
262
0
  const version_entry_st *v, *min_v = NULL;
263
0
  const version_entry_st *backup = NULL;
264
265
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
266
0
       i++) {
267
0
    cur_prot =
268
0
        session->internals.priorities->protocol.priorities[i];
269
0
    v = version_to_entry(cur_prot);
270
271
0
    if (v != NULL && version_is_valid_for_session(session, v)) {
272
0
      if (min_v == NULL) {
273
0
        if (v->obsolete != 0)
274
0
          backup = v;
275
0
        else
276
0
          min_v = v;
277
0
      } else if (v->obsolete == 0 && v->age < min_v->age) {
278
0
        min_v = v;
279
0
      }
280
0
    }
281
0
  }
282
283
0
  if (min_v == NULL)
284
0
    return backup;
285
286
0
  return min_v;
287
0
}
288
289
/* Returns the maximum version in the priorities
290
 */
291
const version_entry_st *_gnutls_version_max(gnutls_session_t session)
292
0
{
293
0
  unsigned int i;
294
0
  gnutls_protocol_t cur_prot;
295
0
  const version_entry_st *p, *max = NULL;
296
297
0
  if (!session->internals.priorities) {
298
0
    gnutls_assert();
299
0
    return NULL;
300
0
  }
301
302
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
303
0
       i++) {
304
0
    cur_prot =
305
0
        session->internals.priorities->protocol.priorities[i];
306
307
0
    for (p = sup_versions; p->name != NULL; p++) {
308
0
      if (p->id == cur_prot) {
309
0
#ifndef ENABLE_SSL3
310
0
        if (p->obsolete != 0)
311
0
          break;
312
0
#endif
313
0
        if (!p->supported
314
0
            && !(p->supported_revertible
315
0
           && _gnutls_allowlisting_mode()))
316
0
          break;
317
318
0
        if (p->transport !=
319
0
            session->internals.transport)
320
0
          break;
321
322
0
        if (p->tls13_sem
323
0
            && (session->
324
0
          internals.flags & INT_FLAG_NO_TLS13))
325
0
          break;
326
327
0
        if (max == NULL || cur_prot > max->id) {
328
0
          max = p;
329
0
        }
330
331
0
        break;
332
0
      }
333
0
    }
334
0
  }
335
336
0
  return max;
337
0
}
338
339
const version_entry_st *_gnutls_legacy_version_max(gnutls_session_t session)
340
0
{
341
0
  const version_entry_st *max = _gnutls_version_max(session);
342
343
0
  if (max && max->only_extension != 0) {
344
    /* TLS 1.3 or later found */
345
0
    if (max->transport == GNUTLS_STREAM) {
346
0
      return version_to_entry(GNUTLS_TLS1_2);
347
0
    } else {
348
0
      return version_to_entry(GNUTLS_DTLS1_2);
349
0
    }
350
0
  }
351
352
0
  return max;
353
0
}
354
355
/* Returns the number of bytes written to buffer or a negative
356
 * error code. It will return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
357
 * if there is no version >= TLS 1.3.
358
 */
359
int _gnutls_write_supported_versions(gnutls_session_t session, uint8_t * buffer,
360
             ssize_t buffer_size)
361
0
{
362
0
  gnutls_protocol_t cur_prot;
363
0
  size_t written_bytes = 0;
364
0
  unsigned at_least_one_new = 0;
365
0
  unsigned i;
366
0
  const version_entry_st *p;
367
368
0
  for (i = 0; i < session->internals.priorities->protocol.num_priorities;
369
0
       i++) {
370
0
    cur_prot =
371
0
        session->internals.priorities->protocol.priorities[i];
372
373
0
    for (p = sup_versions; p->name != NULL; p++) {
374
0
      if (p->id == cur_prot) {
375
0
        if (p->obsolete != 0)
376
0
          break;
377
378
0
        if (!p->supported
379
0
            && !(p->supported_revertible
380
0
           && _gnutls_allowlisting_mode()))
381
0
          break;
382
383
0
        if (p->transport !=
384
0
            session->internals.transport)
385
0
          break;
386
387
0
        if (p->only_extension)
388
0
          at_least_one_new = 1;
389
390
0
        if (buffer_size > 2) {
391
0
          _gnutls_debug_log
392
0
              ("Advertizing version %d.%d\n",
393
0
               (int)p->major, (int)p->minor);
394
0
          buffer[0] = p->major;
395
0
          buffer[1] = p->minor;
396
0
          written_bytes += 2;
397
0
          buffer += 2;
398
0
        }
399
400
0
        buffer_size -= 2;
401
402
0
        if (buffer_size <= 0)
403
0
          goto finish;
404
405
0
        break;
406
0
      }
407
0
    }
408
0
  }
409
410
0
 finish:
411
0
  if (written_bytes == 0)
412
0
    return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
413
414
0
  if (at_least_one_new == 0)
415
0
    return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
416
417
0
  return written_bytes;
418
0
}
419
420
/* Returns true (1) if the given version is higher than the highest supported
421
 * and (0) otherwise */
422
unsigned _gnutls_version_is_too_high(gnutls_session_t session, uint8_t major,
423
             uint8_t minor)
424
0
{
425
0
  const version_entry_st *e;
426
427
0
  e = _gnutls_legacy_version_max(session);
428
0
  if (e == NULL)   /* we don't know; but that means something is unconfigured */
429
0
    return 1;
430
431
0
  if (e->transport == GNUTLS_DGRAM) {
432
0
    if (major < e->major)
433
0
      return 1;
434
435
0
    if (e->major == major && minor < e->minor)
436
0
      return 1;
437
0
  } else {
438
0
    if (major > e->major)
439
0
      return 1;
440
441
0
    if (e->major == major && minor > e->minor)
442
0
      return 1;
443
0
  }
444
445
0
  return 0;
446
0
}
447
448
/**
449
 * gnutls_protocol_get_name:
450
 * @version: is a (gnutls) version number
451
 *
452
 * Convert a #gnutls_protocol_t value to a string.
453
 *
454
 * Returns: a string that contains the name of the specified TLS
455
 *   version (e.g., "TLS1.0"), or %NULL.
456
 **/
457
const char *gnutls_protocol_get_name(gnutls_protocol_t version)
458
0
{
459
0
  const version_entry_st *p;
460
  /* avoid prefix */
461
0
  for (p = sup_versions; p->name != NULL; p++)
462
0
    if (p->id == version)
463
0
      return p->name;
464
0
  return NULL;
465
0
}
466
467
/**
468
 * gnutls_protocol_get_id:
469
 * @name: is a protocol name
470
 *
471
 * The names are compared in a case insensitive way.
472
 *
473
 * Returns: an id of the specified protocol, or
474
 * %GNUTLS_VERSION_UNKNOWN on error.
475
 **/
476
gnutls_protocol_t gnutls_protocol_get_id(const char *name)
477
0
{
478
0
  const version_entry_st *p;
479
0
  gnutls_protocol_t ret = GNUTLS_VERSION_UNKNOWN;
480
481
0
  for (p = sup_versions; p->name != NULL; p++) {
482
0
    if (c_strcasecmp(p->name, name) == 0) {
483
0
      ret = p->id;
484
0
      break;
485
0
    }
486
0
  }
487
488
0
  return ret;
489
0
}
490
491
/**
492
 * gnutls_protocol_list:
493
 *
494
 * Get a list of supported protocols, e.g. SSL 3.0, TLS 1.0 etc.
495
 *
496
 * This function is not thread safe.
497
 *
498
 * Returns: a (0)-terminated list of #gnutls_protocol_t integers
499
 * indicating the available protocols.
500
 *
501
 **/
502
const gnutls_protocol_t *gnutls_protocol_list(void)
503
0
{
504
0
  const version_entry_st *p;
505
0
  static gnutls_protocol_t supported_protocols[MAX_ALGOS] = { 0 };
506
507
0
  if (supported_protocols[0] == 0) {
508
0
    int i = 0;
509
510
0
    for (p = sup_versions; p->name != NULL; p++) {
511
0
      if (!p->supported)
512
0
        continue;
513
0
      supported_protocols[i++] = p->id;
514
0
    }
515
0
    supported_protocols[i++] = 0;
516
0
  }
517
518
0
  return supported_protocols;
519
0
}
520
521
/* Return all versions, including non-supported ones.
522
 */
523
const gnutls_protocol_t *_gnutls_protocol_list(void)
524
0
{
525
0
  const version_entry_st *p;
526
0
  static gnutls_protocol_t protocols[MAX_ALGOS] = { 0 };
527
528
0
  if (protocols[0] == 0) {
529
0
    int i = 0;
530
531
0
    for (p = sup_versions; p->name != NULL; p++) {
532
0
      protocols[i++] = p->id;
533
0
    }
534
0
    protocols[i++] = 0;
535
0
  }
536
537
0
  return protocols;
538
0
}
539
540
/* Returns a version number given the major and minor numbers.
541
 */
542
gnutls_protocol_t _gnutls_version_get(uint8_t major, uint8_t minor)
543
0
{
544
0
  const version_entry_st *p;
545
0
  int ret = GNUTLS_VERSION_UNKNOWN;
546
547
0
  for (p = sup_versions; p->name != NULL; p++)
548
0
    if ((p->major == major) && (p->minor == minor))
549
0
      ret = p->id;
550
0
  return ret;
551
0
}
552
553
/* Version Functions */
554
555
int
556
_gnutls_nversion_is_supported(gnutls_session_t session,
557
            unsigned char major, unsigned char minor)
558
0
{
559
0
  const version_entry_st *p;
560
0
  int version = 0;
561
562
0
  for (p = sup_versions; p->name != NULL; p++) {
563
0
    if (p->major == major && p->minor == minor) {
564
0
#ifndef ENABLE_SSL3
565
0
      if (p->obsolete != 0)
566
0
        return 0;
567
0
#endif
568
0
      if (p->tls13_sem
569
0
          && (session->internals.flags & INT_FLAG_NO_TLS13))
570
0
        return 0;
571
572
0
      if (!p->supported
573
0
          && !(p->supported_revertible
574
0
         && _gnutls_allowlisting_mode()))
575
0
        return 0;
576
577
0
      if (p->transport != session->internals.transport)
578
0
        return 0;
579
580
0
      version = p->id;
581
0
      break;
582
0
    }
583
0
  }
584
585
0
  if (version == 0)
586
0
    return 0;
587
588
0
  if (_gnutls_version_priority(session, version) < 0)
589
0
    return 0; /* disabled by the user */
590
0
  else
591
0
    return 1;
592
0
}