Coverage Report

Created: 2025-03-06 06:58

/src/gnutls/lib/priority.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2004-2015 Free Software Foundation, Inc.
3
 * Copyright (C) 2015-2019 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
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
/* Here lies the code of the gnutls_*_set_priority() functions.
25
 */
26
27
#include "gnutls_int.h"
28
#include "algorithms.h"
29
#include "errors.h"
30
#include "num.h"
31
#include <gnutls/x509.h>
32
#include <c-ctype.h>
33
#include "hello_ext.h"
34
#include <c-strcase.h>
35
#include "fips.h"
36
#include <errno.h>
37
#include "ext/srp.h"
38
#include <gnutls/gnutls.h>
39
#include "profiles.h"
40
#include "c-strcase.h"
41
#include "inih/ini.h"
42
#include "locks.h"
43
#include "profiles.h"
44
#include "name_val_array.h"
45
46
0
#define MAX_ELEMENTS GNUTLS_MAX_ALGORITHM_NUM
47
48
#define ENABLE_PROFILE(c, profile)                                \
49
0
  do {                                                      \
50
0
    c->additional_verify_flags &= 0x00ffffff;         \
51
0
    c->additional_verify_flags |=                     \
52
0
      GNUTLS_PROFILE_TO_VFLAGS(profile);        \
53
0
    c->level = _gnutls_profile_to_sec_level(profile); \
54
0
  } while (0)
55
56
/* This function is used by the test suite */
57
char *_gnutls_resolve_priorities(const char *priorities);
58
59
/* This variable points to either a constant value (DEFAULT_PRIORITY_STRING or
60
 * externally assigned) or heap-allocated
61
 * system_wide_config.default_priority_string. We can't move this to the
62
 * system_wide_config struct, because this variable is part of (private) ABI
63
 * exported for testing.
64
 */
65
const char *_gnutls_default_priority_string = DEFAULT_PRIORITY_STRING;
66
67
static void prio_remove(priority_st *priority_list, unsigned int algo);
68
static void prio_add(priority_st *priority_list, unsigned int algo);
69
static void break_list(char *etag, char *broken_etag[MAX_ELEMENTS], int *size);
70
71
typedef void(bulk_rmadd_func)(priority_st *priority_list, const int *);
72
73
inline static void _set_priority(priority_st *st, const int *list)
74
0
{
75
0
  int num = 0, i;
76
77
0
  while (list[num] != 0)
78
0
    num++;
79
0
  if (num > MAX_ALGOS)
80
0
    num = MAX_ALGOS;
81
0
  st->num_priorities = num;
82
83
0
  for (i = 0; i < num; i++) {
84
0
    st->priorities[i] = list[i];
85
0
  }
86
87
0
  return;
88
0
}
89
90
inline static void _add_priority(priority_st *st, const int *list)
91
0
{
92
0
  int num, i, j, init;
93
94
0
  init = i = st->num_priorities;
95
96
0
  for (num = 0; list[num] != 0; ++num) {
97
0
    if (i + 1 > MAX_ALGOS) {
98
0
      return;
99
0
    }
100
101
0
    for (j = 0; j < init; j++) {
102
0
      if (st->priorities[j] == (unsigned)list[num]) {
103
0
        break;
104
0
      }
105
0
    }
106
107
0
    if (j == init) {
108
0
      st->priorities[i++] = list[num];
109
0
      st->num_priorities++;
110
0
    }
111
0
  }
112
113
0
  return;
114
0
}
115
116
static void _clear_priorities(priority_st *st, const int *list)
117
0
{
118
0
  memset(st, 0, sizeof(*st));
119
0
}
120
121
static void _clear_given_priorities(priority_st *st, const int *list)
122
0
{
123
0
  unsigned i;
124
125
0
  for (i = 0; list[i] != 0; i++) {
126
0
    prio_remove(st, list[i]);
127
0
  }
128
0
}
129
130
static const int _supported_groups_dh[] = {
131
  GNUTLS_GROUP_FFDHE2048, GNUTLS_GROUP_FFDHE3072, GNUTLS_GROUP_FFDHE4096,
132
  GNUTLS_GROUP_FFDHE6144, GNUTLS_GROUP_FFDHE8192, 0
133
};
134
135
static const int _supported_groups_ecdh[] = { GNUTLS_GROUP_SECP256R1,
136
                GNUTLS_GROUP_SECP384R1,
137
                GNUTLS_GROUP_SECP521R1,
138
                GNUTLS_GROUP_X25519, /* RFC 8422 */
139
                GNUTLS_GROUP_X448, /* RFC 8422 */
140
                0 };
141
142
static const int _supported_groups_gost[] = {
143
#ifdef ENABLE_GOST
144
  GNUTLS_GROUP_GC256A,
145
  GNUTLS_GROUP_GC256B,
146
  GNUTLS_GROUP_GC256C,
147
  GNUTLS_GROUP_GC256D,
148
  GNUTLS_GROUP_GC512A,
149
  GNUTLS_GROUP_GC512B,
150
  GNUTLS_GROUP_GC512C,
151
#endif
152
  0
153
};
154
155
static const int _supported_groups_normal[] = {
156
  GNUTLS_GROUP_SECP256R1, GNUTLS_GROUP_SECP384R1, GNUTLS_GROUP_SECP521R1,
157
  GNUTLS_GROUP_X25519, /* RFC 8422 */
158
  GNUTLS_GROUP_X448, /* RFC 8422 */
159
160
  /* These should stay last as our default behavior
161
   * is to send key shares for two top types (GNUTLS_KEY_SHARE_TOP2)
162
   * and we wouldn't want to have these sent by all clients
163
   * by default as they are quite expensive CPU-wise. */
164
  GNUTLS_GROUP_FFDHE2048, GNUTLS_GROUP_FFDHE3072, GNUTLS_GROUP_FFDHE4096,
165
  GNUTLS_GROUP_FFDHE6144, GNUTLS_GROUP_FFDHE8192, 0
166
};
167
168
static const int *supported_groups_normal = _supported_groups_normal;
169
170
static const int _supported_groups_secure128[] = {
171
  GNUTLS_GROUP_SECP256R1, GNUTLS_GROUP_SECP384R1, GNUTLS_GROUP_SECP521R1,
172
  GNUTLS_GROUP_X25519, /* RFC 8422 */
173
  GNUTLS_GROUP_X448, /* RFC 8422 */
174
  GNUTLS_GROUP_FFDHE2048, GNUTLS_GROUP_FFDHE3072, GNUTLS_GROUP_FFDHE4096,
175
  GNUTLS_GROUP_FFDHE6144, GNUTLS_GROUP_FFDHE8192, 0
176
};
177
178
static const int *supported_groups_secure128 = _supported_groups_secure128;
179
180
static const int _supported_groups_suiteb128[] = { GNUTLS_GROUP_SECP256R1,
181
               GNUTLS_GROUP_SECP384R1, 0 };
182
183
static const int *supported_groups_suiteb128 = _supported_groups_suiteb128;
184
185
static const int _supported_groups_suiteb192[] = { GNUTLS_GROUP_SECP384R1, 0 };
186
187
static const int *supported_groups_suiteb192 = _supported_groups_suiteb192;
188
189
static const int _supported_groups_secure192[] = { GNUTLS_GROUP_SECP384R1,
190
               GNUTLS_GROUP_SECP521R1,
191
               GNUTLS_GROUP_FFDHE8192, 0 };
192
193
static const int *supported_groups_secure192 = _supported_groups_secure192;
194
195
static const int protocol_priority[] = { GNUTLS_TLS1_3,
196
           GNUTLS_TLS1_2,
197
           GNUTLS_TLS1_1,
198
           GNUTLS_TLS1_0,
199
           GNUTLS_DTLS1_2,
200
           GNUTLS_DTLS1_0,
201
           0 };
202
203
/* contains all the supported TLS protocols, intended to be used for eliminating them
204
 */
205
static const int stream_protocol_priority[] = { GNUTLS_TLS1_3, GNUTLS_TLS1_2,
206
            GNUTLS_TLS1_1, GNUTLS_TLS1_0,
207
            0 };
208
209
/* contains all the supported DTLS protocols, intended to be used for eliminating them
210
 */
211
static const int dgram_protocol_priority[] = { GNUTLS_DTLS1_2, GNUTLS_DTLS1_0,
212
                 GNUTLS_DTLS0_9, 0 };
213
214
static const int dtls_protocol_priority[] = { GNUTLS_DTLS1_2, GNUTLS_DTLS1_0,
215
                0 };
216
217
static const int _protocol_priority_suiteb[] = { GNUTLS_TLS1_2, 0 };
218
219
static const int *protocol_priority_suiteb = _protocol_priority_suiteb;
220
221
static const int _kx_priority_performance[] = { GNUTLS_KX_RSA,
222
#ifdef ENABLE_ECDHE
223
            GNUTLS_KX_ECDHE_ECDSA,
224
            GNUTLS_KX_ECDHE_RSA,
225
#endif
226
#ifdef ENABLE_DHE
227
            GNUTLS_KX_DHE_RSA,
228
#endif
229
            0 };
230
231
static const int *kx_priority_performance = _kx_priority_performance;
232
233
static const int _kx_priority_pfs[] = {
234
#ifdef ENABLE_ECDHE
235
  GNUTLS_KX_ECDHE_ECDSA, GNUTLS_KX_ECDHE_RSA,
236
#endif
237
#ifdef ENABLE_DHE
238
  GNUTLS_KX_DHE_RSA,
239
#endif
240
  0
241
};
242
243
static const int *kx_priority_pfs = _kx_priority_pfs;
244
245
static const int _kx_priority_suiteb[] = { GNUTLS_KX_ECDHE_ECDSA, 0 };
246
247
static const int *kx_priority_suiteb = _kx_priority_suiteb;
248
249
static const int _kx_priority_secure[] = {
250
/* The ciphersuites that offer forward secrecy take
251
   * precedence
252
   */
253
#ifdef ENABLE_ECDHE
254
  GNUTLS_KX_ECDHE_ECDSA, GNUTLS_KX_ECDHE_RSA,
255
#endif
256
  GNUTLS_KX_RSA,
257
/* KX-RSA is now ahead of DHE-RSA and DHE-DSS due to the compatibility
258
   * issues the DHE ciphersuites have. That is, one cannot enforce a specific
259
   * security level without dropping the connection.
260
   */
261
#ifdef ENABLE_DHE
262
  GNUTLS_KX_DHE_RSA,
263
#endif
264
  /* GNUTLS_KX_ANON_DH: Man-in-the-middle prone, don't add!
265
   */
266
  0
267
};
268
269
static const int *kx_priority_secure = _kx_priority_secure;
270
271
static const int _kx_priority_gost[] = {
272
#ifdef ENABLE_GOST
273
  GNUTLS_KX_VKO_GOST_12,
274
#endif
275
  0,
276
};
277
278
static const int *kx_priority_gost = _kx_priority_gost;
279
280
static const int _cipher_priority_performance_default[] = {
281
  GNUTLS_CIPHER_AES_128_GCM,   GNUTLS_CIPHER_AES_256_GCM,
282
  GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_CIPHER_AES_128_CCM,
283
  GNUTLS_CIPHER_AES_256_CCM,   GNUTLS_CIPHER_AES_128_CBC,
284
  GNUTLS_CIPHER_AES_256_CBC,   0
285
};
286
287
static const int _cipher_priority_performance_no_aesni[] = {
288
  GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_CIPHER_AES_128_GCM,
289
  GNUTLS_CIPHER_AES_256_GCM,   GNUTLS_CIPHER_AES_128_CCM,
290
  GNUTLS_CIPHER_AES_256_CCM,   GNUTLS_CIPHER_AES_128_CBC,
291
  GNUTLS_CIPHER_AES_256_CBC,   0
292
};
293
294
/* If GCM and AES acceleration is available then prefer
295
 * them over anything else. Overall we prioritise AEAD
296
 * over legacy ciphers, and 256-bit over 128 (for future
297
 * proof).
298
 */
299
static const int _cipher_priority_normal_default[] = {
300
  GNUTLS_CIPHER_AES_256_GCM, GNUTLS_CIPHER_CHACHA20_POLY1305,
301
  GNUTLS_CIPHER_AES_256_CCM,
302
303
  GNUTLS_CIPHER_AES_256_CBC,
304
305
  GNUTLS_CIPHER_AES_128_GCM, GNUTLS_CIPHER_AES_128_CCM,
306
307
  GNUTLS_CIPHER_AES_128_CBC, 0
308
};
309
310
static const int cipher_priority_performance_fips[] = {
311
  GNUTLS_CIPHER_AES_128_GCM,
312
  GNUTLS_CIPHER_AES_128_CCM,
313
  GNUTLS_CIPHER_AES_256_GCM,
314
  GNUTLS_CIPHER_AES_256_CCM,
315
316
  GNUTLS_CIPHER_AES_128_CBC,
317
  GNUTLS_CIPHER_AES_256_CBC,
318
  0
319
};
320
321
static const int cipher_priority_normal_fips[] = {
322
  GNUTLS_CIPHER_AES_256_GCM, GNUTLS_CIPHER_AES_256_CCM,
323
  GNUTLS_CIPHER_AES_256_CBC,
324
325
  GNUTLS_CIPHER_AES_128_GCM, GNUTLS_CIPHER_AES_128_CBC,
326
  GNUTLS_CIPHER_AES_128_CCM, 0
327
};
328
329
static const int _cipher_priority_suiteb128[] = { GNUTLS_CIPHER_AES_256_GCM,
330
              GNUTLS_CIPHER_AES_128_GCM,
331
              0 };
332
333
static const int *cipher_priority_suiteb128 = _cipher_priority_suiteb128;
334
335
static const int _cipher_priority_suiteb192[] = { GNUTLS_CIPHER_AES_256_GCM,
336
              0 };
337
338
static const int *cipher_priority_suiteb192 = _cipher_priority_suiteb192;
339
340
static const int _cipher_priority_secure128[] = {
341
  GNUTLS_CIPHER_AES_256_GCM, GNUTLS_CIPHER_CHACHA20_POLY1305,
342
  GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_256_CCM,
343
344
  GNUTLS_CIPHER_AES_128_GCM, GNUTLS_CIPHER_AES_128_CBC,
345
  GNUTLS_CIPHER_AES_128_CCM, 0
346
};
347
348
static const int *cipher_priority_secure128 = _cipher_priority_secure128;
349
350
static const int _cipher_priority_secure192[] = {
351
  GNUTLS_CIPHER_AES_256_GCM, GNUTLS_CIPHER_CHACHA20_POLY1305,
352
  GNUTLS_CIPHER_AES_256_CBC, GNUTLS_CIPHER_AES_256_CCM, 0
353
};
354
355
static const int *cipher_priority_secure192 = _cipher_priority_secure192;
356
357
static const int _sign_priority_default[] = {
358
  GNUTLS_SIGN_RSA_SHA256,
359
  GNUTLS_SIGN_RSA_PSS_SHA256,
360
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
361
  GNUTLS_SIGN_ECDSA_SHA256,
362
  GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
363
364
  GNUTLS_SIGN_EDDSA_ED25519,
365
366
  GNUTLS_SIGN_RSA_SHA384,
367
  GNUTLS_SIGN_RSA_PSS_SHA384,
368
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
369
  GNUTLS_SIGN_ECDSA_SHA384,
370
  GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
371
372
  GNUTLS_SIGN_EDDSA_ED448,
373
374
  GNUTLS_SIGN_RSA_SHA512,
375
  GNUTLS_SIGN_RSA_PSS_SHA512,
376
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
377
378
  GNUTLS_SIGN_ECDSA_SHA512,
379
  GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
380
381
  GNUTLS_SIGN_RSA_SHA1,
382
  GNUTLS_SIGN_ECDSA_SHA1,
383
384
  0
385
};
386
387
static const int *sign_priority_default = _sign_priority_default;
388
389
static const int _sign_priority_suiteb128[] = {
390
  GNUTLS_SIGN_ECDSA_SHA256, GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
391
  GNUTLS_SIGN_ECDSA_SHA384, GNUTLS_SIGN_ECDSA_SECP384R1_SHA384, 0
392
};
393
394
static const int *sign_priority_suiteb128 = _sign_priority_suiteb128;
395
396
static const int _sign_priority_suiteb192[] = {
397
  GNUTLS_SIGN_ECDSA_SHA384, GNUTLS_SIGN_ECDSA_SECP384R1_SHA384, 0
398
};
399
400
static const int *sign_priority_suiteb192 = _sign_priority_suiteb192;
401
402
static const int _sign_priority_secure128[] = {
403
  GNUTLS_SIGN_RSA_SHA256,
404
  GNUTLS_SIGN_RSA_PSS_SHA256,
405
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
406
  GNUTLS_SIGN_ECDSA_SHA256,
407
  GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
408
409
  GNUTLS_SIGN_EDDSA_ED25519,
410
411
  GNUTLS_SIGN_RSA_SHA384,
412
  GNUTLS_SIGN_RSA_PSS_SHA384,
413
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
414
  GNUTLS_SIGN_ECDSA_SHA384,
415
  GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
416
417
  GNUTLS_SIGN_EDDSA_ED448,
418
419
  GNUTLS_SIGN_RSA_SHA512,
420
  GNUTLS_SIGN_RSA_PSS_SHA512,
421
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
422
  GNUTLS_SIGN_ECDSA_SHA512,
423
  GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
424
425
  0
426
};
427
428
static const int *sign_priority_secure128 = _sign_priority_secure128;
429
430
static const int _sign_priority_secure192[] = {
431
  GNUTLS_SIGN_RSA_SHA384,
432
  GNUTLS_SIGN_RSA_PSS_SHA384,
433
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
434
  GNUTLS_SIGN_ECDSA_SHA384,
435
  GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
436
  GNUTLS_SIGN_EDDSA_ED448,
437
  GNUTLS_SIGN_RSA_SHA512,
438
  GNUTLS_SIGN_RSA_PSS_SHA512,
439
  GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
440
  GNUTLS_SIGN_ECDSA_SHA512,
441
  GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
442
443
  0
444
};
445
446
static const int *sign_priority_secure192 = _sign_priority_secure192;
447
448
static const int _sign_priority_gost[] = {
449
#ifdef ENABLE_GOST
450
  GNUTLS_SIGN_GOST_256, GNUTLS_SIGN_GOST_512,
451
#endif
452
  0
453
};
454
455
static const int *sign_priority_gost = _sign_priority_gost;
456
457
static const int mac_priority_normal_default[] = { GNUTLS_MAC_SHA1,
458
               GNUTLS_MAC_AEAD, 0 };
459
460
static const int mac_priority_normal_fips[] = { GNUTLS_MAC_SHA1,
461
            GNUTLS_MAC_AEAD, 0 };
462
463
static const int *cipher_priority_performance =
464
  _cipher_priority_performance_default;
465
static const int *cipher_priority_normal = _cipher_priority_normal_default;
466
static const int *mac_priority_normal = mac_priority_normal_default;
467
468
static const int _cipher_priority_gost[] = {
469
#ifdef ENABLE_GOST
470
  GNUTLS_CIPHER_GOST28147_TC26Z_CNT,
471
#endif
472
  0
473
};
474
475
static const int *cipher_priority_gost = _cipher_priority_gost;
476
477
static const int _mac_priority_gost[] = {
478
#ifdef ENABLE_GOST
479
  GNUTLS_MAC_GOST28147_TC26Z_IMIT,
480
#endif
481
  0
482
};
483
484
static const int *mac_priority_gost = _mac_priority_gost;
485
486
/* if called with replace the default priorities with the FIPS140 ones */
487
void _gnutls_priority_update_fips(void)
488
0
{
489
0
  cipher_priority_performance = cipher_priority_performance_fips;
490
0
  cipher_priority_normal = cipher_priority_normal_fips;
491
0
  mac_priority_normal = mac_priority_normal_fips;
492
0
}
493
494
void _gnutls_priority_update_non_aesni(void)
495
0
{
496
  /* if we have no AES acceleration in performance mode
497
   * prefer fast stream ciphers */
498
0
  if (_gnutls_fips_mode_enabled() == 0) {
499
0
    cipher_priority_performance =
500
0
      _cipher_priority_performance_no_aesni;
501
0
  }
502
0
}
503
504
static const int _mac_priority_suiteb[] = { GNUTLS_MAC_AEAD, 0 };
505
506
static const int *mac_priority_suiteb = _mac_priority_suiteb;
507
508
static const int _mac_priority_secure128[] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_AEAD,
509
                 0 };
510
511
static const int *mac_priority_secure128 = _mac_priority_secure128;
512
513
static const int _mac_priority_secure192[] = { GNUTLS_MAC_AEAD, 0 };
514
515
static const int *mac_priority_secure192 = _mac_priority_secure192;
516
517
static const int cert_type_priority_default[] = { GNUTLS_CRT_X509, 0 };
518
519
static const int cert_type_priority_all[] = { GNUTLS_CRT_X509, GNUTLS_CRT_RAWPK,
520
                0 };
521
522
typedef void(rmadd_func)(priority_st *priority_list, unsigned int alg);
523
524
static void prio_remove(priority_st *priority_list, unsigned int algo)
525
0
{
526
0
  unsigned int i;
527
528
0
  for (i = 0; i < priority_list->num_priorities; i++) {
529
0
    if (priority_list->priorities[i] == algo) {
530
0
      priority_list->num_priorities--;
531
0
      if ((priority_list->num_priorities - i) > 0)
532
0
        memmove(&priority_list->priorities[i],
533
0
          &priority_list->priorities[i + 1],
534
0
          (priority_list->num_priorities -
535
0
           i) * sizeof(priority_list
536
0
                   ->priorities[0]));
537
0
      priority_list
538
0
        ->priorities[priority_list->num_priorities] = 0;
539
0
      break;
540
0
    }
541
0
  }
542
543
0
  return;
544
0
}
545
546
static void prio_add(priority_st *priority_list, unsigned int algo)
547
0
{
548
0
  unsigned int i, l = priority_list->num_priorities;
549
550
0
  if (l >= MAX_ALGOS)
551
0
    return; /* can't add it anyway */
552
553
0
  for (i = 0; i < l; ++i) {
554
0
    if (algo == priority_list->priorities[i])
555
0
      return; /* if it exists */
556
0
  }
557
558
0
  priority_list->priorities[l] = algo;
559
0
  priority_list->num_priorities++;
560
561
0
  return;
562
0
}
563
564
/**
565
 * gnutls_priority_set:
566
 * @session: is a #gnutls_session_t type.
567
 * @priority: is a #gnutls_priority_t type.
568
 *
569
 * Sets the priorities to use on the ciphers, key exchange methods,
570
 * and macs. Note that this function is expected to be called once
571
 * per session; when called multiple times (e.g., before a re-handshake,
572
 * the caller should make sure that any new settings are not incompatible
573
 * with the original session).
574
 *
575
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code on error.
576
 **/
577
int gnutls_priority_set(gnutls_session_t session, gnutls_priority_t priority)
578
0
{
579
0
  int ret;
580
581
0
  if (priority == NULL || priority->protocol.num_priorities == 0 ||
582
0
      priority->cs.size == 0)
583
0
    return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
584
585
  /* set the current version to the first in the chain, if this is
586
   * the call before the initial handshake. During a re-handshake
587
   * we do not set the version to avoid overriding the currently
588
   * negotiated version. */
589
0
  if (!session->internals.handshake_in_progress &&
590
0
      !session->internals.initial_negotiation_completed) {
591
0
    ret = _gnutls_set_current_version(
592
0
      session, priority->protocol.priorities[0]);
593
0
    if (ret < 0)
594
0
      return gnutls_assert_val(ret);
595
0
  }
596
597
  /* At this point the provided priorities passed the sanity tests */
598
599
0
  if (session->internals.priorities)
600
0
    gnutls_priority_deinit(session->internals.priorities);
601
602
0
  gnutls_atomic_increment(&priority->usage_cnt);
603
0
  session->internals.priorities = priority;
604
605
0
  if (priority->no_tickets != 0) {
606
0
    session->internals.flags |= GNUTLS_NO_TICKETS;
607
0
  }
608
609
0
  if (priority->no_tickets_tls12 != 0) {
610
    /* when PFS is explicitly requested, disable session tickets for TLS 1.2 */
611
0
    session->internals.flags |= GNUTLS_NO_TICKETS_TLS12;
612
0
  }
613
614
0
  if (priority->no_status_request)
615
0
    session->internals.flags |= GNUTLS_NO_STATUS_REQUEST;
616
617
0
  ADD_PROFILE_VFLAGS(session, priority->additional_verify_flags);
618
619
  /* mirror variables */
620
0
#undef COPY_TO_INTERNALS
621
0
#define COPY_TO_INTERNALS(xx) session->internals.xx = priority->_##xx
622
0
  COPY_TO_INTERNALS(allow_large_records);
623
0
  COPY_TO_INTERNALS(allow_small_records);
624
0
  COPY_TO_INTERNALS(no_etm);
625
0
  COPY_TO_INTERNALS(no_ext_master_secret);
626
0
  COPY_TO_INTERNALS(allow_key_usage_violation);
627
0
  COPY_TO_INTERNALS(dumbfw);
628
0
  COPY_TO_INTERNALS(dh_prime_bits);
629
630
0
  return 0;
631
0
}
632
633
0
#define LEVEL_NONE "NONE"
634
#define LEVEL_NORMAL "NORMAL"
635
#define LEVEL_PFS "PFS"
636
#define LEVEL_PERFORMANCE "PERFORMANCE"
637
#define LEVEL_SECURE128 "SECURE128"
638
#define LEVEL_SECURE192 "SECURE192"
639
#define LEVEL_SECURE256 "SECURE256"
640
#define LEVEL_SUITEB128 "SUITEB128"
641
#define LEVEL_SUITEB192 "SUITEB192"
642
#define LEVEL_LEGACY "LEGACY"
643
0
#define LEVEL_SYSTEM "SYSTEM"
644
645
struct priority_groups_st {
646
  const char *name;
647
  const char *alias;
648
  const int **proto_list;
649
  const int **cipher_list;
650
  const int **mac_list;
651
  const int **kx_list;
652
  const int **sign_list;
653
  const int **group_list;
654
  unsigned profile;
655
  int sec_param;
656
  bool no_tickets;
657
  bool no_tickets_tls12;
658
};
659
660
static const struct priority_groups_st pgroups[] = {
661
  { .name = LEVEL_NORMAL,
662
    .cipher_list = &cipher_priority_normal,
663
    .mac_list = &mac_priority_normal,
664
    .kx_list = &kx_priority_secure,
665
    .sign_list = &sign_priority_default,
666
    .group_list = &supported_groups_normal,
667
    .profile = GNUTLS_PROFILE_LOW,
668
    .sec_param = GNUTLS_SEC_PARAM_WEAK },
669
  { .name = LEVEL_PFS,
670
    .cipher_list = &cipher_priority_normal,
671
    .mac_list = &mac_priority_secure128,
672
    .kx_list = &kx_priority_pfs,
673
    .sign_list = &sign_priority_default,
674
    .group_list = &supported_groups_normal,
675
    .profile = GNUTLS_PROFILE_LOW,
676
    .sec_param = GNUTLS_SEC_PARAM_WEAK,
677
    .no_tickets_tls12 = 1 },
678
  { .name = LEVEL_SECURE128,
679
    .alias = "SECURE",
680
    .cipher_list = &cipher_priority_secure128,
681
    .mac_list = &mac_priority_secure128,
682
    .kx_list = &kx_priority_secure,
683
    .sign_list = &sign_priority_secure128,
684
    .group_list = &supported_groups_secure128,
685
    /* The profile should have been HIGH but if we don't allow
686
    * SHA-1 (80-bits) as signature algorithm we are not able
687
    * to connect anywhere with this level */
688
    .profile = GNUTLS_PROFILE_LOW,
689
    .sec_param = GNUTLS_SEC_PARAM_LOW },
690
  { .name = LEVEL_SECURE192,
691
    .alias = LEVEL_SECURE256,
692
    .cipher_list = &cipher_priority_secure192,
693
    .mac_list = &mac_priority_secure192,
694
    .kx_list = &kx_priority_secure,
695
    .sign_list = &sign_priority_secure192,
696
    .group_list = &supported_groups_secure192,
697
    .profile = GNUTLS_PROFILE_HIGH,
698
    .sec_param = GNUTLS_SEC_PARAM_HIGH },
699
  { .name = LEVEL_SUITEB128,
700
    .proto_list = &protocol_priority_suiteb,
701
    .cipher_list = &cipher_priority_suiteb128,
702
    .mac_list = &mac_priority_suiteb,
703
    .kx_list = &kx_priority_suiteb,
704
    .sign_list = &sign_priority_suiteb128,
705
    .group_list = &supported_groups_suiteb128,
706
    .profile = GNUTLS_PROFILE_SUITEB128,
707
    .sec_param = GNUTLS_SEC_PARAM_HIGH },
708
  { .name = LEVEL_SUITEB192,
709
    .proto_list = &protocol_priority_suiteb,
710
    .cipher_list = &cipher_priority_suiteb192,
711
    .mac_list = &mac_priority_suiteb,
712
    .kx_list = &kx_priority_suiteb,
713
    .sign_list = &sign_priority_suiteb192,
714
    .group_list = &supported_groups_suiteb192,
715
    .profile = GNUTLS_PROFILE_SUITEB192,
716
    .sec_param = GNUTLS_SEC_PARAM_ULTRA },
717
  { .name = LEVEL_LEGACY,
718
    .cipher_list = &cipher_priority_normal,
719
    .mac_list = &mac_priority_normal,
720
    .kx_list = &kx_priority_secure,
721
    .sign_list = &sign_priority_default,
722
    .group_list = &supported_groups_normal,
723
    .sec_param = GNUTLS_SEC_PARAM_VERY_WEAK },
724
  { .name = LEVEL_PERFORMANCE,
725
    .cipher_list = &cipher_priority_performance,
726
    .mac_list = &mac_priority_normal,
727
    .kx_list = &kx_priority_performance,
728
    .sign_list = &sign_priority_default,
729
    .group_list = &supported_groups_normal,
730
    .profile = GNUTLS_PROFILE_LOW,
731
    .sec_param = GNUTLS_SEC_PARAM_WEAK },
732
  {
733
    .name = NULL,
734
  }
735
};
736
737
#define SET_PROFILE(to_set)                                \
738
0
  profile = GNUTLS_VFLAGS_TO_PROFILE(                \
739
0
    priority_cache->additional_verify_flags);  \
740
0
  if (profile == 0 || profile > to_set) {            \
741
0
    priority_cache->additional_verify_flags &= \
742
0
      ~GNUTLS_VFLAGS_PROFILE_MASK;       \
743
0
    priority_cache->additional_verify_flags |= \
744
0
      GNUTLS_PROFILE_TO_VFLAGS(to_set);  \
745
0
  }
746
747
#define SET_LEVEL(to_set)                                       \
748
0
  if (priority_cache->level == 0 ||                       \
749
0
      (unsigned)priority_cache->level > (unsigned)to_set) \
750
0
  priority_cache->level = to_set
751
752
static int check_level(const char *level, gnutls_priority_t priority_cache,
753
           int add)
754
0
{
755
0
  bulk_rmadd_func *func;
756
0
  unsigned profile = 0;
757
0
  unsigned i;
758
0
  int j;
759
0
  const cipher_entry_st *centry;
760
761
0
  if (add)
762
0
    func = _add_priority;
763
0
  else
764
0
    func = _set_priority;
765
766
0
  for (i = 0;; i++) {
767
0
    if (pgroups[i].name == NULL)
768
0
      return 0;
769
770
0
    if (c_strcasecmp(level, pgroups[i].name) == 0 ||
771
0
        (pgroups[i].alias != NULL &&
772
0
         c_strcasecmp(level, pgroups[i].alias) == 0)) {
773
0
      if (pgroups[i].proto_list != NULL)
774
0
        func(&priority_cache->protocol,
775
0
             *pgroups[i].proto_list);
776
0
      func(&priority_cache->_cipher, *pgroups[i].cipher_list);
777
0
      func(&priority_cache->_kx, *pgroups[i].kx_list);
778
0
      func(&priority_cache->_mac, *pgroups[i].mac_list);
779
0
      func(&priority_cache->_sign_algo,
780
0
           *pgroups[i].sign_list);
781
0
      func(&priority_cache->_supported_ecc,
782
0
           *pgroups[i].group_list);
783
784
0
      if (pgroups[i].profile != 0) {
785
0
        SET_PROFILE(
786
0
          pgroups[i].profile); /* set certificate level */
787
0
      }
788
0
      SET_LEVEL(
789
0
        pgroups[i].sec_param); /* set DH params level */
790
0
      priority_cache->no_tickets = pgroups[i].no_tickets;
791
0
      priority_cache->no_tickets_tls12 =
792
0
        pgroups[i].no_tickets_tls12;
793
0
      if (priority_cache->have_cbc == 0) {
794
0
        for (j = 0; (*pgroups[i].cipher_list)[j] != 0;
795
0
             j++) {
796
0
          centry = cipher_to_entry(
797
0
            (*pgroups[i].cipher_list)[j]);
798
0
          if (centry != NULL &&
799
0
              centry->type == CIPHER_BLOCK) {
800
0
            priority_cache->have_cbc = 1;
801
0
            break;
802
0
          }
803
0
        }
804
0
      }
805
0
      return 1;
806
0
    }
807
0
  }
808
0
}
809
810
static void enable_compat(gnutls_priority_t c)
811
0
{
812
0
  ENABLE_PRIO_COMPAT(c);
813
0
}
814
815
static void enable_server_key_usage_violations(gnutls_priority_t c)
816
0
{
817
0
  c->allow_server_key_usage_violation = 1;
818
0
}
819
820
static void enable_allow_small_records(gnutls_priority_t c)
821
0
{
822
0
  c->_allow_small_records = 1;
823
0
}
824
825
static void enable_dumbfw(gnutls_priority_t c)
826
0
{
827
0
  c->_dumbfw = 1;
828
0
}
829
830
static void enable_no_extensions(gnutls_priority_t c)
831
0
{
832
0
  c->no_extensions = 1;
833
0
}
834
835
static void enable_no_status_request(gnutls_priority_t c)
836
0
{
837
0
  c->no_status_request = 1;
838
0
}
839
840
static void enable_no_ext_master_secret(gnutls_priority_t c)
841
0
{
842
0
  c->_no_ext_master_secret = 1;
843
0
}
844
845
static void enable_force_ext_master_secret(gnutls_priority_t c)
846
0
{
847
0
  c->force_ext_master_secret = EMS_REQUIRE;
848
0
}
849
850
static void enable_no_etm(gnutls_priority_t c)
851
0
{
852
0
  c->_no_etm = 1;
853
0
}
854
855
static void enable_force_etm(gnutls_priority_t c)
856
0
{
857
0
  c->force_etm = 1;
858
0
}
859
860
static void enable_no_tickets(gnutls_priority_t c)
861
0
{
862
0
  c->no_tickets = 1;
863
0
}
864
865
static void enable_no_tickets_tls12(gnutls_priority_t c)
866
0
{
867
0
  c->no_tickets_tls12 = 1;
868
0
}
869
870
static void disable_wildcards(gnutls_priority_t c)
871
0
{
872
0
  c->additional_verify_flags |= GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS;
873
0
}
874
875
static void enable_profile_very_weak(gnutls_priority_t c)
876
0
{
877
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_VERY_WEAK);
878
0
}
879
880
static void enable_profile_low(gnutls_priority_t c)
881
0
{
882
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_LOW);
883
0
}
884
885
static void enable_profile_legacy(gnutls_priority_t c)
886
0
{
887
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_LEGACY);
888
0
}
889
890
static void enable_profile_medium(gnutls_priority_t c)
891
0
{
892
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_MEDIUM);
893
0
}
894
895
static void enable_profile_high(gnutls_priority_t c)
896
0
{
897
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_HIGH);
898
0
}
899
900
static void enable_profile_ultra(gnutls_priority_t c)
901
0
{
902
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_ULTRA);
903
0
}
904
905
static void enable_profile_future(gnutls_priority_t c)
906
0
{
907
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_FUTURE);
908
0
}
909
910
static void enable_profile_suiteb128(gnutls_priority_t c)
911
0
{
912
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_SUITEB128);
913
0
}
914
915
static void enable_profile_suiteb192(gnutls_priority_t c)
916
0
{
917
0
  ENABLE_PROFILE(c, GNUTLS_PROFILE_SUITEB128);
918
0
}
919
920
static void enable_safe_renegotiation(gnutls_priority_t c)
921
0
{
922
0
  c->sr = SR_SAFE;
923
0
}
924
925
static void enable_unsafe_renegotiation(gnutls_priority_t c)
926
0
{
927
0
  c->sr = SR_UNSAFE;
928
0
}
929
930
static void enable_partial_safe_renegotiation(gnutls_priority_t c)
931
0
{
932
0
  c->sr = SR_PARTIAL;
933
0
}
934
935
static void disable_safe_renegotiation(gnutls_priority_t c)
936
0
{
937
0
  c->sr = SR_DISABLED;
938
0
}
939
940
static void enable_fallback_scsv(gnutls_priority_t c)
941
0
{
942
0
  c->fallback = 1;
943
0
}
944
945
static void enable_latest_record_version(gnutls_priority_t c)
946
0
{
947
0
  c->min_record_version = 0;
948
0
}
949
950
static void enable_ssl3_record_version(gnutls_priority_t c)
951
0
{
952
0
  c->min_record_version = 1;
953
0
}
954
955
static void enable_verify_allow_rsa_md5(gnutls_priority_t c)
956
0
{
957
0
  c->additional_verify_flags |= GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5;
958
0
}
959
960
static void enable_verify_allow_sha1(gnutls_priority_t c)
961
0
{
962
0
  c->additional_verify_flags |= GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1;
963
0
}
964
965
static void enable_verify_allow_broken(gnutls_priority_t c)
966
0
{
967
0
  c->additional_verify_flags |= GNUTLS_VERIFY_ALLOW_BROKEN;
968
0
}
969
970
static void disable_crl_checks(gnutls_priority_t c)
971
0
{
972
0
  c->additional_verify_flags |= GNUTLS_VERIFY_DISABLE_CRL_CHECKS;
973
0
}
974
975
static void enable_server_precedence(gnutls_priority_t c)
976
0
{
977
0
  c->server_precedence = 1;
978
0
}
979
980
static void disable_tls13_compat_mode(gnutls_priority_t c)
981
0
{
982
0
  c->tls13_compat_mode = false;
983
0
}
984
985
static void enable_no_shuffle_extensions(gnutls_priority_t c)
986
0
{
987
0
  c->no_shuffle_extensions = 1;
988
0
}
989
990
static void dummy_func(gnutls_priority_t c)
991
0
{
992
0
}
993
994
#include <priority_options.h>
995
996
struct cfg {
997
  bool allowlisting;
998
  bool ktls_enabled;
999
  bool allow_rsa_pkcs1_encrypt;
1000
1001
  name_val_array_t priority_strings;
1002
  char *priority_string;
1003
  char *default_priority_string;
1004
  gnutls_certificate_verification_profiles_t verification_profile;
1005
1006
  gnutls_cipher_algorithm_t ciphers[MAX_ALGOS + 1];
1007
  gnutls_mac_algorithm_t macs[MAX_ALGOS + 1];
1008
  gnutls_group_t groups[MAX_ALGOS + 1];
1009
  gnutls_kx_algorithm_t kxs[MAX_ALGOS + 1];
1010
  gnutls_sign_algorithm_t sigs[MAX_ALGOS + 1];
1011
  gnutls_protocol_t versions[MAX_ALGOS + 1];
1012
1013
  gnutls_digest_algorithm_t hashes[MAX_ALGOS + 1];
1014
  gnutls_ecc_curve_t ecc_curves[MAX_ALGOS + 1];
1015
  gnutls_sign_algorithm_t sigs_for_cert[MAX_ALGOS + 1];
1016
1017
  ext_master_secret_t force_ext_master_secret;
1018
  bool force_ext_master_secret_set;
1019
};
1020
1021
static inline void cfg_init(struct cfg *cfg)
1022
2
{
1023
2
  memset(cfg, 0, sizeof(*cfg));
1024
2
  cfg->allow_rsa_pkcs1_encrypt = true;
1025
2
}
1026
1027
static inline void cfg_deinit(struct cfg *cfg)
1028
0
{
1029
0
  if (cfg->priority_strings) {
1030
0
    _name_val_array_clear(&cfg->priority_strings);
1031
0
  }
1032
0
  gnutls_free(cfg->priority_string);
1033
0
  gnutls_free(cfg->default_priority_string);
1034
0
}
1035
1036
/* Lock for reading and writing system_wide_config */
1037
GNUTLS_RWLOCK(system_wide_config_rwlock);
1038
static struct cfg system_wide_config;
1039
1040
static unsigned fail_on_invalid_config = 0;
1041
static const char *system_priority_file = SYSTEM_PRIORITY_FILE;
1042
static time_t system_priority_last_mod = 0;
1043
static unsigned system_priority_file_loaded = 0;
1044
1045
0
#define GLOBAL_SECTION "global"
1046
0
#define CUSTOM_PRIORITY_SECTION "priorities"
1047
0
#define OVERRIDES_SECTION "overrides"
1048
0
#define MAX_ALGO_NAME 2048
1049
1050
bool _gnutls_allowlisting_mode(void)
1051
0
{
1052
0
  return system_wide_config.allowlisting;
1053
0
}
1054
1055
static void _clear_default_system_priority(void)
1056
0
{
1057
0
  gnutls_free(system_wide_config.default_priority_string);
1058
0
  system_wide_config.default_priority_string = NULL;
1059
1060
0
  _gnutls_default_priority_string = DEFAULT_PRIORITY_STRING;
1061
0
}
1062
1063
gnutls_certificate_verification_profiles_t
1064
_gnutls_get_system_wide_verification_profile(void)
1065
0
{
1066
0
  return system_wide_config.verification_profile;
1067
0
}
1068
1069
/* removes spaces */
1070
static char *clear_spaces(const char *str, char out[MAX_ALGO_NAME])
1071
0
{
1072
0
  const char *p = str;
1073
0
  unsigned i = 0;
1074
1075
0
  while (c_isspace(*p))
1076
0
    p++;
1077
1078
0
  while (!c_isspace(*p) && *p != 0) {
1079
0
    out[i++] = *p;
1080
0
    p++;
1081
1082
0
    if (i >= MAX_ALGO_NAME - 1)
1083
0
      break;
1084
0
  }
1085
0
  out[i] = 0;
1086
0
  return out;
1087
0
}
1088
1089
struct ini_ctx {
1090
  struct cfg cfg;
1091
1092
  gnutls_digest_algorithm_t *hashes;
1093
  size_t hashes_size;
1094
  gnutls_sign_algorithm_t *sigs;
1095
  size_t sigs_size;
1096
  gnutls_sign_algorithm_t *sigs_for_cert;
1097
  size_t sigs_for_cert_size;
1098
  gnutls_protocol_t *versions;
1099
  size_t versions_size;
1100
  gnutls_ecc_curve_t *curves;
1101
  size_t curves_size;
1102
};
1103
1104
static inline void ini_ctx_init(struct ini_ctx *ctx)
1105
0
{
1106
0
  memset(ctx, 0, sizeof(*ctx));
1107
0
  cfg_init(&ctx->cfg);
1108
0
}
1109
1110
static inline void ini_ctx_deinit(struct ini_ctx *ctx)
1111
0
{
1112
0
  cfg_deinit(&ctx->cfg);
1113
0
  gnutls_free(ctx->hashes);
1114
0
  gnutls_free(ctx->sigs);
1115
0
  gnutls_free(ctx->sigs_for_cert);
1116
0
  gnutls_free(ctx->versions);
1117
0
  gnutls_free(ctx->curves);
1118
0
}
1119
1120
static inline void cfg_steal(struct cfg *dst, struct cfg *src)
1121
0
{
1122
0
  dst->verification_profile = src->verification_profile;
1123
1124
0
  dst->priority_strings = src->priority_strings;
1125
0
  src->priority_strings = NULL;
1126
1127
0
  dst->priority_string = src->priority_string;
1128
0
  src->priority_string = NULL;
1129
1130
0
  dst->default_priority_string = src->default_priority_string;
1131
0
  src->default_priority_string = NULL;
1132
1133
0
  dst->allowlisting = src->allowlisting;
1134
0
  dst->ktls_enabled = src->ktls_enabled;
1135
0
  dst->allow_rsa_pkcs1_encrypt = src->allow_rsa_pkcs1_encrypt;
1136
0
  dst->force_ext_master_secret = src->force_ext_master_secret;
1137
0
  dst->force_ext_master_secret_set = src->force_ext_master_secret_set;
1138
0
  memcpy(dst->ciphers, src->ciphers, sizeof(src->ciphers));
1139
0
  memcpy(dst->macs, src->macs, sizeof(src->macs));
1140
0
  memcpy(dst->groups, src->groups, sizeof(src->groups));
1141
0
  memcpy(dst->kxs, src->kxs, sizeof(src->kxs));
1142
0
  memcpy(dst->hashes, src->hashes, sizeof(src->hashes));
1143
0
  memcpy(dst->ecc_curves, src->ecc_curves, sizeof(src->ecc_curves));
1144
0
  memcpy(dst->sigs, src->sigs, sizeof(src->sigs));
1145
0
  memcpy(dst->sigs_for_cert, src->sigs_for_cert,
1146
0
         sizeof(src->sigs_for_cert));
1147
0
}
1148
1149
/*
1150
 * synchronizing changes from struct cfg to global `lib/algorithms` arrays
1151
 */
1152
1153
/* global side-effect! modifies `flags` in `hash_algorithms[]` */
1154
static inline int /* allowlisting-only */ _cfg_hashes_remark(struct cfg *cfg)
1155
0
{
1156
0
  size_t i;
1157
0
  _gnutls_digest_mark_insecure_all();
1158
0
  for (i = 0; cfg->hashes[i] != 0; i++) {
1159
0
    int ret = _gnutls_digest_set_secure(cfg->hashes[i], 1);
1160
0
    if (unlikely(ret < 0)) {
1161
0
      return gnutls_assert_val(ret);
1162
0
    }
1163
0
  }
1164
0
  return 0;
1165
0
}
1166
1167
/* global side-effect! modifies `flags` in `sign_algorithms[]` */
1168
static inline int /* allowlisting-only */ _cfg_sigs_remark(struct cfg *cfg)
1169
0
{
1170
0
  size_t i;
1171
0
  _gnutls_sign_mark_insecure_all(_INSECURE);
1172
0
  for (i = 0; cfg->sigs[i] != 0; i++) {
1173
0
    int ret = _gnutls_sign_set_secure(cfg->sigs[i],
1174
0
              _INSECURE_FOR_CERTS);
1175
0
    if (unlikely(ret < 0)) {
1176
0
      return gnutls_assert_val(ret);
1177
0
    }
1178
0
  }
1179
0
  for (i = 0; cfg->sigs_for_cert[i] != 0; i++) {
1180
0
    int ret =
1181
0
      _gnutls_sign_set_secure(cfg->sigs_for_cert[i], _SECURE);
1182
0
    if (unlikely(ret < 0)) {
1183
0
      return gnutls_assert_val(ret);
1184
0
    }
1185
0
  }
1186
0
  return 0;
1187
0
}
1188
1189
/* global side-effect! modifies `supported` in `sup_versions[]` */
1190
static inline int /* allowlisting-only */ _cfg_versions_remark(struct cfg *cfg)
1191
0
{
1192
0
  size_t i;
1193
0
  _gnutls_version_mark_disabled_all();
1194
0
  for (i = 0; cfg->versions[i] != 0; i++) {
1195
0
    int ret = _gnutls_protocol_set_enabled(cfg->versions[i], 1);
1196
0
    if (unlikely(ret < 0)) {
1197
0
      return gnutls_assert_val(ret);
1198
0
    }
1199
0
  }
1200
0
  return 0;
1201
0
}
1202
1203
/* global side-effect! modifies `supported` in `ecc_curves[]` */
1204
static inline int /* allowlisting-only */
1205
_cfg_ecc_curves_remark(struct cfg *cfg)
1206
0
{
1207
0
  size_t i;
1208
0
  _gnutls_ecc_curve_mark_disabled_all();
1209
0
  for (i = 0; cfg->ecc_curves[i] != 0; i++) {
1210
0
    int ret = _gnutls_ecc_curve_set_enabled(cfg->ecc_curves[i], 1);
1211
0
    if (unlikely(ret < 0)) {
1212
0
      return gnutls_assert_val(ret);
1213
0
    }
1214
0
  }
1215
0
  return 0;
1216
0
}
1217
1218
/*
1219
 * setting arrays of struct cfg: from other arrays
1220
 */
1221
1222
static inline int /* allowlisting-only */
1223
cfg_hashes_set_array(struct cfg *cfg, gnutls_digest_algorithm_t *src,
1224
         size_t len)
1225
0
{
1226
0
  if (unlikely(len >= MAX_ALGOS)) {
1227
0
    return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
1228
0
  }
1229
0
  if (len) {
1230
0
    memcpy(cfg->hashes, src,
1231
0
           sizeof(gnutls_digest_algorithm_t) * len);
1232
0
  }
1233
0
  cfg->hashes[len] = 0;
1234
0
  return _cfg_hashes_remark(cfg);
1235
0
}
1236
1237
static inline int /* allowlisting-only */
1238
cfg_sigs_set_arrays(struct cfg *cfg, gnutls_sign_algorithm_t *src, size_t len,
1239
        gnutls_sign_algorithm_t *src_for_cert, size_t len_for_cert)
1240
0
{
1241
0
  if (unlikely(len >= MAX_ALGOS)) {
1242
0
    return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
1243
0
  }
1244
0
  if (unlikely(len_for_cert >= MAX_ALGOS)) {
1245
0
    return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
1246
0
  }
1247
0
  if (len) {
1248
0
    memcpy(cfg->sigs, src, sizeof(gnutls_sign_algorithm_t) * len);
1249
0
  }
1250
0
  if (len_for_cert) {
1251
0
    memcpy(cfg->sigs_for_cert, src_for_cert,
1252
0
           sizeof(gnutls_sign_algorithm_t) * len_for_cert);
1253
0
  }
1254
0
  cfg->sigs[len] = 0;
1255
0
  cfg->sigs_for_cert[len_for_cert] = 0;
1256
0
  return _cfg_sigs_remark(cfg);
1257
0
}
1258
1259
static inline int /* allowlisting-only */
1260
cfg_versions_set_array(struct cfg *cfg, gnutls_protocol_t *src, size_t len)
1261
0
{
1262
0
  if (unlikely(len >= MAX_ALGOS)) {
1263
0
    return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
1264
0
  }
1265
0
  if (len) {
1266
0
    memcpy(cfg->versions, src, sizeof(gnutls_protocol_t) * len);
1267
0
  }
1268
0
  cfg->versions[len] = 0;
1269
0
  return _cfg_versions_remark(cfg);
1270
0
}
1271
1272
static inline int /* allowlisting-only */
1273
cfg_ecc_curves_set_array(struct cfg *cfg, gnutls_ecc_curve_t *src, size_t len)
1274
0
{
1275
0
  if (unlikely(len >= MAX_ALGOS)) {
1276
0
    return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR);
1277
0
  }
1278
0
  if (len) {
1279
0
    memcpy(cfg->ecc_curves, src, sizeof(gnutls_ecc_curve_t) * len);
1280
0
  }
1281
0
  cfg->ecc_curves[len] = 0;
1282
0
  return _cfg_ecc_curves_remark(cfg);
1283
0
}
1284
1285
/*
1286
 * appending to arrays of struct cfg
1287
 */
1288
1289
/* polymorphic way to DRY this operation. other possible approaches:
1290
 * 1. just unmacro (long)
1291
 * 2. cast to ints and write a function operating on ints
1292
 *    (hacky, every call is +4 lines, needs a portable static assert)
1293
 * 3. macro whole functions, not just this operation (harder to find/read)
1294
 */
1295
#define APPEND_TO_NULL_TERMINATED_ARRAY(dst, element)                      \
1296
0
  do {                                                               \
1297
0
    size_t i;                                                  \
1298
0
    for (i = 0; dst[i] != 0; i++) {                            \
1299
0
      if (dst[i] == element) {                           \
1300
0
        return 0;                                  \
1301
0
      }                                                  \
1302
0
    }                                                          \
1303
0
    if (unlikely(i >= MAX_ALGOS)) {                            \
1304
0
      return gnutls_assert_val(GNUTLS_A_INTERNAL_ERROR); \
1305
0
    }                                                          \
1306
0
    dst[i] = element;                                          \
1307
0
    dst[i + 1] = 0;                                            \
1308
0
  } while (0)
1309
1310
static inline int /* allowlisting-only */
1311
cfg_hashes_add(struct cfg *cfg, gnutls_digest_algorithm_t dig)
1312
0
{
1313
0
  _gnutls_debug_log("cfg: enabling digest algorithm %s\n",
1314
0
        gnutls_digest_get_name(dig));
1315
0
  APPEND_TO_NULL_TERMINATED_ARRAY(cfg->hashes, dig);
1316
0
  return _cfg_hashes_remark(cfg);
1317
0
}
1318
1319
static inline int /* allowlisting-only */
1320
cfg_sigs_add(struct cfg *cfg, gnutls_sign_algorithm_t sig)
1321
0
{
1322
0
  _gnutls_debug_log("cfg: enabling signature algorithm "
1323
0
        "(for non-certificate usage) "
1324
0
        "%s\n",
1325
0
        gnutls_sign_get_name(sig));
1326
0
  APPEND_TO_NULL_TERMINATED_ARRAY(cfg->sigs, sig);
1327
0
  return _cfg_sigs_remark(cfg);
1328
0
}
1329
1330
static inline int /* allowlisting-only */
1331
cfg_sigs_for_cert_add(struct cfg *cfg, gnutls_sign_algorithm_t sig)
1332
0
{
1333
0
  _gnutls_debug_log("cfg: enabling signature algorithm"
1334
0
        "(for certificate usage) "
1335
0
        "%s\n",
1336
0
        gnutls_sign_get_name(sig));
1337
0
  APPEND_TO_NULL_TERMINATED_ARRAY(cfg->sigs_for_cert, sig);
1338
0
  return _cfg_sigs_remark(cfg);
1339
0
}
1340
1341
static inline int /* allowlisting-only */
1342
cfg_versions_add(struct cfg *cfg, gnutls_protocol_t prot)
1343
0
{
1344
0
  _gnutls_debug_log("cfg: enabling version %s\n",
1345
0
        gnutls_protocol_get_name(prot));
1346
0
  APPEND_TO_NULL_TERMINATED_ARRAY(cfg->versions, prot);
1347
0
  return _cfg_versions_remark(cfg);
1348
0
}
1349
1350
static inline int /* allowlisting-only */
1351
cfg_ecc_curves_add(struct cfg *cfg, gnutls_ecc_curve_t curve)
1352
0
{
1353
0
  _gnutls_debug_log("cfg: enabling curve %s\n",
1354
0
        gnutls_ecc_curve_get_name(curve));
1355
0
  APPEND_TO_NULL_TERMINATED_ARRAY(cfg->ecc_curves, curve);
1356
0
  return _cfg_ecc_curves_remark(cfg);
1357
0
}
1358
1359
#undef APPEND_TO_NULL_TERMINATED_ARRAY
1360
1361
/*
1362
 * removing from arrays of struct cfg
1363
 */
1364
1365
/* polymorphic way to DRY this removal, see APPEND_TO_NULL_TERMINATED_ARRAY */
1366
#define REMOVE_FROM_NULL_TERMINATED_ARRAY(dst, element)         \
1367
0
  do {                                                    \
1368
0
    size_t i, j;                                    \
1369
0
    for (i = 0; dst[i] != 0; i++) {                 \
1370
0
      if (dst[i] == element) {                \
1371
0
        for (j = i; dst[j] != 0; j++) { \
1372
0
          dst[j] = dst[j + 1];    \
1373
0
        }                               \
1374
0
      }                                       \
1375
0
    }                                               \
1376
0
  } while (0)
1377
1378
static inline int /* allowlisting-only */
1379
cfg_hashes_remove(struct cfg *cfg, gnutls_digest_algorithm_t dig)
1380
0
{
1381
0
  _gnutls_debug_log("cfg: disabling digest algorithm %s\n",
1382
0
        gnutls_digest_get_name(dig));
1383
0
  REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->hashes, dig);
1384
0
  return _cfg_hashes_remark(cfg);
1385
0
}
1386
1387
static inline int /* allowlisting-only */
1388
cfg_sigs_remove(struct cfg *cfg, gnutls_sign_algorithm_t sig)
1389
0
{
1390
0
  _gnutls_debug_log("cfg: disabling signature algorithm "
1391
0
        "(for non-certificate usage) "
1392
0
        "%s\n",
1393
0
        gnutls_sign_get_name(sig));
1394
0
  REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->sigs, sig);
1395
0
  return _cfg_sigs_remark(cfg);
1396
0
}
1397
1398
static inline int /* allowlisting-only */
1399
cfg_sigs_for_cert_remove(struct cfg *cfg, gnutls_sign_algorithm_t sig)
1400
0
{
1401
0
  _gnutls_debug_log("cfg: disabling signature algorithm"
1402
0
        "(for certificate usage) "
1403
0
        "%s\n",
1404
0
        gnutls_sign_get_name(sig));
1405
0
  REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->sigs_for_cert, sig);
1406
0
  return _cfg_sigs_remark(cfg);
1407
0
}
1408
1409
static inline int /* allowlisting-only */
1410
cfg_versions_remove(struct cfg *cfg, gnutls_protocol_t prot)
1411
0
{
1412
0
  _gnutls_debug_log("cfg: disabling version %s\n",
1413
0
        gnutls_protocol_get_name(prot));
1414
0
  REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->versions, prot);
1415
0
  return _cfg_versions_remark(cfg);
1416
0
}
1417
1418
static inline int /* allowlisting-only */
1419
cfg_ecc_curves_remove(struct cfg *cfg, gnutls_ecc_curve_t curve)
1420
0
{
1421
0
  _gnutls_debug_log("cfg: disabling curve %s\n",
1422
0
        gnutls_ecc_curve_get_name(curve));
1423
0
  REMOVE_FROM_NULL_TERMINATED_ARRAY(cfg->ecc_curves, curve);
1424
0
  return _cfg_ecc_curves_remark(cfg);
1425
0
}
1426
1427
static inline int cfg_apply(struct cfg *cfg, struct ini_ctx *ctx)
1428
0
{
1429
0
  size_t i;
1430
0
  int ret;
1431
1432
0
  cfg_steal(cfg, &ctx->cfg);
1433
1434
0
  if (cfg->default_priority_string) {
1435
0
    _gnutls_default_priority_string = cfg->default_priority_string;
1436
0
  }
1437
1438
0
  if (cfg->allowlisting) {
1439
    /* also updates `flags` of global `hash_algorithms[]` */
1440
0
    ret = cfg_hashes_set_array(cfg, ctx->hashes, ctx->hashes_size);
1441
0
    if (unlikely(ret < 0)) {
1442
0
      return gnutls_assert_val(ret);
1443
0
    }
1444
    /* also updates `flags` of global `sign_algorithms[]` */
1445
0
    ret = cfg_sigs_set_arrays(cfg, ctx->sigs, ctx->sigs_size,
1446
0
            ctx->sigs_for_cert,
1447
0
            ctx->sigs_for_cert_size);
1448
0
    if (unlikely(ret < 0)) {
1449
0
      return gnutls_assert_val(ret);
1450
0
    }
1451
    /* also updates `supported` field of global `sup_versions[]` */
1452
0
    ret = cfg_versions_set_array(cfg, ctx->versions,
1453
0
               ctx->versions_size);
1454
0
    if (unlikely(ret < 0)) {
1455
0
      return gnutls_assert_val(ret);
1456
0
    }
1457
    /* also updates `supported` field of global `ecc_curves[]` */
1458
0
    ret = cfg_ecc_curves_set_array(cfg, ctx->curves,
1459
0
                 ctx->curves_size);
1460
0
    if (unlikely(ret < 0)) {
1461
0
      return gnutls_assert_val(ret);
1462
0
    }
1463
0
  } else {
1464
    /* updates same global arrays as above, but doesn't store
1465
     * the algorithms into the `struct cfg` as allowlisting does.
1466
     * blocklisting doesn't allow relaxing the restrictions */
1467
0
    for (i = 0; i < ctx->hashes_size; i++) {
1468
0
      ret = _gnutls_digest_mark_insecure(ctx->hashes[i]);
1469
0
      if (unlikely(ret < 0)) {
1470
0
        return ret;
1471
0
      }
1472
0
    }
1473
0
    for (i = 0; i < ctx->sigs_size; i++) {
1474
0
      ret = _gnutls_sign_mark_insecure(ctx->sigs[i],
1475
0
               _INSECURE);
1476
0
      if (unlikely(ret < 0)) {
1477
0
        return ret;
1478
0
      }
1479
0
    }
1480
0
    for (i = 0; i < ctx->sigs_for_cert_size; i++) {
1481
0
      ret = _gnutls_sign_mark_insecure(ctx->sigs_for_cert[i],
1482
0
               _INSECURE_FOR_CERTS);
1483
0
      if (unlikely(ret < 0)) {
1484
0
        return ret;
1485
0
      }
1486
0
    }
1487
0
    for (i = 0; i < ctx->versions_size; i++) {
1488
0
      ret = _gnutls_version_mark_disabled(ctx->versions[i]);
1489
0
      if (unlikely(ret < 0)) {
1490
0
        return ret;
1491
0
      }
1492
0
    }
1493
0
    for (i = 0; i < ctx->curves_size; i++) {
1494
0
      ret = _gnutls_ecc_curve_mark_disabled(ctx->curves[i]);
1495
0
      if (unlikely(ret < 0)) {
1496
0
        return ret;
1497
0
      }
1498
0
    }
1499
0
  }
1500
1501
0
  return 0;
1502
0
}
1503
1504
/* This function parses the global section of the configuration file.
1505
 */
1506
static int global_ini_handler(void *ctx, const char *section, const char *name,
1507
            const char *value)
1508
0
{
1509
0
  char *p;
1510
0
  char str[MAX_ALGO_NAME];
1511
0
  struct cfg *cfg = ctx;
1512
1513
0
  if (section != NULL && c_strcasecmp(section, GLOBAL_SECTION) == 0) {
1514
0
    if (c_strcasecmp(name, "override-mode") == 0) {
1515
0
      p = clear_spaces(value, str);
1516
0
      if (c_strcasecmp(p, "allowlist") == 0) {
1517
0
        cfg->allowlisting = true;
1518
0
      } else if (c_strcasecmp(p, "blocklist") == 0) {
1519
0
        cfg->allowlisting = false;
1520
0
      } else {
1521
0
        _gnutls_debug_log(
1522
0
          "cfg: unknown override mode %s\n", p);
1523
0
        if (fail_on_invalid_config)
1524
0
          return 0;
1525
0
      }
1526
0
    } else if (c_strcasecmp(name, "ktls") == 0) {
1527
0
      p = clear_spaces(value, str);
1528
0
      if (c_strcasecmp(p, "true") == 0) {
1529
0
        cfg->ktls_enabled = true;
1530
0
      } else if (c_strcasecmp(p, "false") == 0) {
1531
0
        cfg->ktls_enabled = false;
1532
0
      } else {
1533
0
        _gnutls_debug_log("cfg: unknown ktls mode %s\n",
1534
0
              p);
1535
0
        if (fail_on_invalid_config)
1536
0
          return 0;
1537
0
      }
1538
0
    } else {
1539
0
      _gnutls_debug_log("unknown parameter %s\n", name);
1540
0
      if (fail_on_invalid_config)
1541
0
        return 0;
1542
0
    }
1543
0
  }
1544
1545
0
  return 1;
1546
0
}
1547
1548
static bool override_allowed(bool allowlisting, const char *name)
1549
0
{
1550
0
  static const struct {
1551
0
    const char *allowlist_name;
1552
0
    const char *blocklist_name;
1553
0
  } names[] = { { "secure-hash", "insecure-hash" },
1554
0
          { "secure-sig", "insecure-sig" },
1555
0
          { "secure-sig-for-cert", "insecure-sig-for-cert" },
1556
0
          { "enabled-version", "disabled-version" },
1557
0
          { "enabled-curve", "disabled-curve" },
1558
0
          { "tls-enabled-cipher", "tls-disabled-cipher" },
1559
0
          { "tls-enabled-group", "tls-disabled-group" },
1560
0
          { "tls-enabled-kx", "tls-disabled-kx" },
1561
0
          { "tls-enabled-mac", "tls-disabled-mac" } };
1562
0
  size_t i;
1563
1564
0
  for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
1565
0
    if (c_strcasecmp(name, allowlisting ?
1566
0
                 names[i].blocklist_name :
1567
0
                 names[i].allowlist_name) == 0)
1568
0
      return false;
1569
0
  }
1570
1571
0
  return true;
1572
0
}
1573
1574
/* This function parses a gnutls configuration file.  Updating internal settings
1575
 * according to the parsed configuration is done by cfg_apply.
1576
 */
1577
static int cfg_ini_handler(void *_ctx, const char *section, const char *name,
1578
         const char *value)
1579
0
{
1580
0
  char *p;
1581
0
  int ret;
1582
0
  unsigned i;
1583
0
  char str[MAX_ALGO_NAME];
1584
0
  struct ini_ctx *ctx = _ctx;
1585
0
  struct cfg *cfg = &ctx->cfg;
1586
1587
  /* Note that we intentionally overwrite the value above; inih does
1588
   * not use that value after we handle it. */
1589
1590
  /* Parse sections */
1591
0
  if (section == NULL || section[0] == 0 ||
1592
0
      c_strcasecmp(section, CUSTOM_PRIORITY_SECTION) == 0) {
1593
0
    _gnutls_debug_log("cfg: adding priority: %s -> %s\n", name,
1594
0
          value);
1595
1596
0
    ret = _name_val_array_append(&cfg->priority_strings, name,
1597
0
               value);
1598
0
    if (ret < 0)
1599
0
      return 0;
1600
0
  } else if (c_strcasecmp(section, OVERRIDES_SECTION) == 0) {
1601
0
    if (!override_allowed(cfg->allowlisting, name)) {
1602
0
      _gnutls_debug_log(
1603
0
        "cfg: %s is not allowed in this mode\n", name);
1604
0
      if (fail_on_invalid_config)
1605
0
        return 0;
1606
0
    } else if (c_strcasecmp(name, "default-priority-string") == 0) {
1607
0
      if (cfg->default_priority_string) {
1608
0
        gnutls_free(cfg->default_priority_string);
1609
0
        cfg->default_priority_string = NULL;
1610
0
      }
1611
0
      p = clear_spaces(value, str);
1612
0
      _gnutls_debug_log(
1613
0
        "cfg: setting default-priority-string to %s\n",
1614
0
        p);
1615
0
      if (strlen(p) > 0) {
1616
0
        cfg->default_priority_string = gnutls_strdup(p);
1617
0
        if (!cfg->default_priority_string) {
1618
0
          _gnutls_debug_log(
1619
0
            "cfg: failed setting default-priority-string\n");
1620
0
          return 0;
1621
0
        }
1622
0
      } else {
1623
0
        _gnutls_debug_log(
1624
0
          "cfg: empty default-priority-string, using default\n");
1625
0
        if (fail_on_invalid_config)
1626
0
          return 0;
1627
0
      }
1628
0
    } else if (c_strcasecmp(name, "insecure-hash") == 0 ||
1629
0
         c_strcasecmp(name, "secure-hash") == 0) {
1630
0
      gnutls_digest_algorithm_t dig, *tmp;
1631
1632
0
      p = clear_spaces(value, str);
1633
1634
0
      if (cfg->allowlisting) {
1635
0
        _gnutls_debug_log(
1636
0
          "cfg: marking hash %s as secure\n", p);
1637
0
      } else {
1638
0
        _gnutls_debug_log(
1639
0
          "cfg: marking hash %s as insecure\n",
1640
0
          p);
1641
0
      }
1642
1643
0
      dig = gnutls_digest_get_id(p);
1644
0
      if (dig == GNUTLS_DIG_UNKNOWN) {
1645
0
        _gnutls_debug_log(
1646
0
          "cfg: found unknown hash %s in %s\n", p,
1647
0
          name);
1648
0
        if (fail_on_invalid_config)
1649
0
          return 0;
1650
0
        goto exit;
1651
0
      }
1652
0
      tmp = _gnutls_reallocarray(
1653
0
        ctx->hashes, ctx->hashes_size + 1,
1654
0
        sizeof(gnutls_digest_algorithm_t));
1655
0
      if (!tmp) {
1656
0
        if (cfg->allowlisting) {
1657
0
          _gnutls_debug_log(
1658
0
            "cfg: failed marking hash %s as secure\n",
1659
0
            p);
1660
0
        } else {
1661
0
          _gnutls_debug_log(
1662
0
            "cfg: failed marking hash %s as insecure\n",
1663
0
            p);
1664
0
        }
1665
0
        if (fail_on_invalid_config)
1666
0
          return 0;
1667
0
        goto exit;
1668
0
      }
1669
1670
0
      ctx->hashes = tmp;
1671
0
      ctx->hashes[ctx->hashes_size] = dig;
1672
0
      ctx->hashes_size++;
1673
0
    } else if (c_strcasecmp(name, "insecure-sig") == 0 ||
1674
0
         c_strcasecmp(name, "secure-sig") == 0) {
1675
0
      gnutls_sign_algorithm_t sig, *tmp;
1676
1677
0
      p = clear_spaces(value, str);
1678
1679
0
      if (cfg->allowlisting) {
1680
0
        _gnutls_debug_log(
1681
0
          "cfg: marking signature %s as secure\n",
1682
0
          p);
1683
0
      } else {
1684
0
        _gnutls_debug_log(
1685
0
          "cfg: marking signature %s as insecure\n",
1686
0
          p);
1687
0
      }
1688
1689
0
      sig = gnutls_sign_get_id(p);
1690
0
      if (sig == GNUTLS_SIGN_UNKNOWN) {
1691
0
        _gnutls_debug_log(
1692
0
          "cfg: found unknown signature algorithm %s in %s\n",
1693
0
          p, name);
1694
0
        if (fail_on_invalid_config)
1695
0
          return 0;
1696
0
        goto exit;
1697
0
      }
1698
0
      tmp = _gnutls_reallocarray(
1699
0
        ctx->sigs, ctx->sigs_size + 1,
1700
0
        sizeof(gnutls_sign_algorithm_t));
1701
0
      if (!tmp) {
1702
0
        if (cfg->allowlisting) {
1703
0
          _gnutls_debug_log(
1704
0
            "cfg: failed marking signature %s as secure\n",
1705
0
            p);
1706
0
        } else {
1707
0
          _gnutls_debug_log(
1708
0
            "cfg: failed marking signature %s as insecure\n",
1709
0
            p);
1710
0
        }
1711
0
        if (fail_on_invalid_config)
1712
0
          return 0;
1713
0
        goto exit;
1714
0
      }
1715
1716
0
      ctx->sigs = tmp;
1717
0
      ctx->sigs[ctx->sigs_size] = sig;
1718
0
      ctx->sigs_size++;
1719
0
    } else if (c_strcasecmp(name, "insecure-sig-for-cert") == 0 ||
1720
0
         c_strcasecmp(name, "secure-sig-for-cert") == 0) {
1721
0
      gnutls_sign_algorithm_t sig, *tmp;
1722
1723
0
      p = clear_spaces(value, str);
1724
1725
0
      if (cfg->allowlisting) {
1726
0
        _gnutls_debug_log(
1727
0
          "cfg: marking signature %s as secure for certs\n",
1728
0
          p);
1729
0
      } else {
1730
0
        _gnutls_debug_log(
1731
0
          "cfg: marking signature %s as insecure for certs\n",
1732
0
          p);
1733
0
      }
1734
1735
0
      sig = gnutls_sign_get_id(p);
1736
0
      if (sig == GNUTLS_SIGN_UNKNOWN) {
1737
0
        _gnutls_debug_log(
1738
0
          "cfg: found unknown signature algorithm %s in %s\n",
1739
0
          p, name);
1740
0
        if (fail_on_invalid_config)
1741
0
          return 0;
1742
0
        goto exit;
1743
0
      }
1744
0
      tmp = _gnutls_reallocarray(
1745
0
        ctx->sigs_for_cert, ctx->sigs_for_cert_size + 1,
1746
0
        sizeof(gnutls_sign_algorithm_t));
1747
0
      if (!tmp) {
1748
0
        if (cfg->allowlisting) {
1749
0
          _gnutls_debug_log(
1750
0
            "cfg: failed marking signature %s as secure for certs\n",
1751
0
            p);
1752
0
        } else {
1753
0
          _gnutls_debug_log(
1754
0
            "cfg: failed marking signature %s as insecure for certs\n",
1755
0
            p);
1756
0
        }
1757
0
        if (fail_on_invalid_config)
1758
0
          return 0;
1759
0
        goto exit;
1760
0
      }
1761
1762
0
      ctx->sigs_for_cert = tmp;
1763
0
      ctx->sigs_for_cert[ctx->sigs_for_cert_size] = sig;
1764
0
      ctx->sigs_for_cert_size++;
1765
0
    } else if (c_strcasecmp(name, "disabled-version") == 0 ||
1766
0
         c_strcasecmp(name, "enabled-version") == 0) {
1767
0
      gnutls_protocol_t prot, *tmp;
1768
1769
0
      p = clear_spaces(value, str);
1770
1771
0
      if (cfg->allowlisting) {
1772
0
        _gnutls_debug_log("cfg: enabling version %s\n",
1773
0
              p);
1774
0
      } else {
1775
0
        _gnutls_debug_log("cfg: disabling version %s\n",
1776
0
              p);
1777
0
      }
1778
1779
0
      prot = gnutls_protocol_get_id(p);
1780
0
      if (prot == GNUTLS_VERSION_UNKNOWN) {
1781
0
        _gnutls_debug_log(
1782
0
          "cfg: found unknown version %s in %s\n",
1783
0
          p, name);
1784
0
        if (fail_on_invalid_config)
1785
0
          return 0;
1786
0
        goto exit;
1787
0
      }
1788
0
      tmp = _gnutls_reallocarray(ctx->versions,
1789
0
               ctx->versions_size + 1,
1790
0
               sizeof(gnutls_protocol_t));
1791
0
      if (!tmp) {
1792
0
        if (cfg->allowlisting) {
1793
0
          _gnutls_debug_log(
1794
0
            "cfg: failed enabling version %s\n",
1795
0
            p);
1796
0
        } else {
1797
0
          _gnutls_debug_log(
1798
0
            "cfg: failed disabling version %s\n",
1799
0
            p);
1800
0
        }
1801
0
        if (fail_on_invalid_config)
1802
0
          return 0;
1803
0
        goto exit;
1804
0
      }
1805
1806
0
      ctx->versions = tmp;
1807
0
      ctx->versions[ctx->versions_size] = prot;
1808
0
      ctx->versions_size++;
1809
0
    } else if (c_strcasecmp(name, "disabled-curve") == 0 ||
1810
0
         c_strcasecmp(name, "enabled-curve") == 0) {
1811
0
      gnutls_ecc_curve_t curve, *tmp;
1812
1813
0
      p = clear_spaces(value, str);
1814
1815
0
      if (cfg->allowlisting) {
1816
0
        _gnutls_debug_log("cfg: enabling curve %s\n",
1817
0
              p);
1818
0
      } else {
1819
0
        _gnutls_debug_log("cfg: disabling curve %s\n",
1820
0
              p);
1821
0
      }
1822
1823
0
      curve = gnutls_ecc_curve_get_id(p);
1824
0
      if (curve == GNUTLS_ECC_CURVE_INVALID) {
1825
0
        _gnutls_debug_log(
1826
0
          "cfg: found unknown curve %s in %s\n",
1827
0
          p, name);
1828
0
        if (fail_on_invalid_config)
1829
0
          return 0;
1830
0
        goto exit;
1831
0
      }
1832
0
      tmp = _gnutls_reallocarray(ctx->curves,
1833
0
               ctx->curves_size + 1,
1834
0
               sizeof(gnutls_ecc_curve_t));
1835
0
      if (!tmp) {
1836
0
        if (cfg->allowlisting) {
1837
0
          _gnutls_debug_log(
1838
0
            "cfg: failed enabling curve %s\n",
1839
0
            p);
1840
0
        } else {
1841
0
          _gnutls_debug_log(
1842
0
            "cfg: failed disabling curve %s\n",
1843
0
            p);
1844
0
        }
1845
0
        if (fail_on_invalid_config)
1846
0
          return 0;
1847
0
        goto exit;
1848
0
      }
1849
1850
0
      ctx->curves = tmp;
1851
0
      ctx->curves[ctx->curves_size] = curve;
1852
0
      ctx->curves_size++;
1853
0
    } else if (c_strcasecmp(name, "min-verification-profile") ==
1854
0
         0) {
1855
0
      gnutls_certificate_verification_profiles_t profile;
1856
0
      profile =
1857
0
        gnutls_certificate_verification_profile_get_id(
1858
0
          value);
1859
1860
0
      if (profile == GNUTLS_PROFILE_UNKNOWN) {
1861
0
        _gnutls_debug_log(
1862
0
          "cfg: found unknown profile %s in %s\n",
1863
0
          value, name);
1864
0
        if (fail_on_invalid_config)
1865
0
          return 0;
1866
0
        goto exit;
1867
0
      }
1868
1869
0
      cfg->verification_profile = profile;
1870
0
    } else if (c_strcasecmp(name, "tls-disabled-cipher") == 0 ||
1871
0
         c_strcasecmp(name, "tls-enabled-cipher") == 0) {
1872
0
      gnutls_cipher_algorithm_t algo;
1873
1874
0
      p = clear_spaces(value, str);
1875
1876
0
      if (cfg->allowlisting) {
1877
0
        _gnutls_debug_log(
1878
0
          "cfg: enabling cipher %s for TLS\n", p);
1879
0
      } else {
1880
0
        _gnutls_debug_log(
1881
0
          "cfg: disabling cipher %s for TLS\n",
1882
0
          p);
1883
0
      }
1884
1885
0
      algo = gnutls_cipher_get_id(p);
1886
0
      if (algo == GNUTLS_CIPHER_UNKNOWN) {
1887
0
        _gnutls_debug_log(
1888
0
          "cfg: unknown algorithm %s listed at %s\n",
1889
0
          p, name);
1890
0
        if (fail_on_invalid_config)
1891
0
          return 0;
1892
0
        goto exit;
1893
0
      }
1894
1895
0
      i = 0;
1896
0
      while (cfg->ciphers[i] != 0)
1897
0
        i++;
1898
1899
0
      if (i > MAX_ALGOS - 1) {
1900
0
        if (cfg->allowlisting) {
1901
0
          _gnutls_debug_log(
1902
0
            "cfg: too many (%d) enabled ciphers from %s\n",
1903
0
            i, name);
1904
0
        } else {
1905
0
          _gnutls_debug_log(
1906
0
            "cfg: too many (%d) disabled ciphers from %s\n",
1907
0
            i, name);
1908
0
        }
1909
0
        if (fail_on_invalid_config)
1910
0
          return 0;
1911
0
        goto exit;
1912
0
      }
1913
0
      cfg->ciphers[i] = algo;
1914
0
      cfg->ciphers[i + 1] = 0;
1915
1916
0
    } else if (c_strcasecmp(name, "tls-disabled-mac") == 0 ||
1917
0
         c_strcasecmp(name, "tls-enabled-mac") == 0) {
1918
0
      gnutls_mac_algorithm_t algo;
1919
1920
0
      p = clear_spaces(value, str);
1921
1922
0
      if (cfg->allowlisting) {
1923
0
        _gnutls_debug_log(
1924
0
          "cfg: enabling MAC %s for TLS\n", p);
1925
0
      } else {
1926
0
        _gnutls_debug_log(
1927
0
          "cfg: disabling MAC %s for TLS\n", p);
1928
0
      }
1929
1930
0
      algo = gnutls_mac_get_id(p);
1931
0
      if (algo == 0) {
1932
0
        _gnutls_debug_log(
1933
0
          "cfg: unknown algorithm %s listed at %s\n",
1934
0
          p, name);
1935
0
        if (fail_on_invalid_config)
1936
0
          return 0;
1937
0
        goto exit;
1938
0
      }
1939
1940
0
      i = 0;
1941
0
      while (cfg->macs[i] != 0)
1942
0
        i++;
1943
1944
0
      if (i > MAX_ALGOS - 1) {
1945
0
        if (cfg->allowlisting) {
1946
0
          _gnutls_debug_log(
1947
0
            "cfg: too many (%d) enabled MACs from %s\n",
1948
0
            i, name);
1949
0
        } else {
1950
0
          _gnutls_debug_log(
1951
0
            "cfg: too many (%d) disabled MACs from %s\n",
1952
0
            i, name);
1953
0
        }
1954
0
        if (fail_on_invalid_config)
1955
0
          return 0;
1956
0
        goto exit;
1957
0
      }
1958
0
      cfg->macs[i] = algo;
1959
0
      cfg->macs[i + 1] = 0;
1960
0
    } else if (c_strcasecmp(name, "tls-disabled-group") == 0 ||
1961
0
         c_strcasecmp(name, "tls-enabled-group") == 0) {
1962
0
      gnutls_group_t algo;
1963
1964
0
      p = clear_spaces(value, str);
1965
1966
0
      if (c_strncasecmp(p, "GROUP-", 6) == 0)
1967
0
        p += 6;
1968
1969
0
      if (cfg->allowlisting) {
1970
0
        _gnutls_debug_log(
1971
0
          "cfg: enabling group %s for TLS\n", p);
1972
0
      } else {
1973
0
        _gnutls_debug_log(
1974
0
          "cfg: disabling group %s for TLS\n", p);
1975
0
      }
1976
1977
0
      algo = _gnutls_group_get_id(p);
1978
0
      if (algo == 0) {
1979
0
        _gnutls_debug_log(
1980
0
          "cfg: unknown group %s listed at %s\n",
1981
0
          p, name);
1982
0
        if (fail_on_invalid_config)
1983
0
          return 0;
1984
0
        goto exit;
1985
0
      }
1986
1987
0
      i = 0;
1988
0
      while (cfg->groups[i] != 0)
1989
0
        i++;
1990
1991
0
      if (i > MAX_ALGOS - 1) {
1992
0
        if (cfg->allowlisting) {
1993
0
          _gnutls_debug_log(
1994
0
            "cfg: too many (%d) enabled groups from %s\n",
1995
0
            i, name);
1996
0
        } else {
1997
0
          _gnutls_debug_log(
1998
0
            "cfg: too many (%d) disabled groups from %s\n",
1999
0
            i, name);
2000
0
        }
2001
0
        if (fail_on_invalid_config)
2002
0
          return 0;
2003
0
        goto exit;
2004
0
      }
2005
0
      cfg->groups[i] = algo;
2006
0
      cfg->groups[i + 1] = 0;
2007
0
    } else if (c_strcasecmp(name, "tls-disabled-kx") == 0 ||
2008
0
         c_strcasecmp(name, "tls-enabled-kx") == 0) {
2009
0
      unsigned algo;
2010
2011
0
      p = clear_spaces(value, str);
2012
2013
0
      if (cfg->allowlisting) {
2014
0
        _gnutls_debug_log(
2015
0
          "cfg: enabling key exchange %s for TLS\n",
2016
0
          p);
2017
0
      } else {
2018
0
        _gnutls_debug_log(
2019
0
          "cfg: disabling key exchange %s for TLS\n",
2020
0
          p);
2021
0
      }
2022
2023
0
      algo = gnutls_kx_get_id(p);
2024
0
      if (algo == 0) {
2025
0
        _gnutls_debug_log(
2026
0
          "cfg: unknown key exchange %s listed at %s\n",
2027
0
          p, name);
2028
0
        if (fail_on_invalid_config)
2029
0
          return 0;
2030
0
        goto exit;
2031
0
      }
2032
2033
0
      i = 0;
2034
0
      while (cfg->kxs[i] != 0)
2035
0
        i++;
2036
2037
0
      if (i > MAX_ALGOS - 1) {
2038
0
        if (cfg->allowlisting) {
2039
0
          _gnutls_debug_log(
2040
0
            "cfg: too many (%d) enabled key exchanges from %s\n",
2041
0
            i, name);
2042
0
        } else {
2043
0
          _gnutls_debug_log(
2044
0
            "cfg: too many (%d) disabled key exchanges from %s\n",
2045
0
            i, name);
2046
0
        }
2047
0
        if (fail_on_invalid_config)
2048
0
          return 0;
2049
0
        goto exit;
2050
0
      }
2051
0
      cfg->kxs[i] = algo;
2052
0
      cfg->kxs[i + 1] = 0;
2053
0
    } else if (c_strcasecmp(name, "tls-session-hash") == 0) {
2054
0
      if (c_strcasecmp(value, "request") == 0) {
2055
0
        cfg->force_ext_master_secret = EMS_REQUEST;
2056
0
        cfg->force_ext_master_secret_set = true;
2057
0
      } else if (c_strcasecmp(value, "require") == 0) {
2058
0
        cfg->force_ext_master_secret = EMS_REQUIRE;
2059
0
        cfg->force_ext_master_secret_set = true;
2060
0
      } else {
2061
0
        _gnutls_debug_log(
2062
0
          "cfg: unknown value for %s: %s\n", name,
2063
0
          value);
2064
0
        if (fail_on_invalid_config)
2065
0
          return 0;
2066
0
        goto exit;
2067
0
      }
2068
0
    } else if (c_strcasecmp(name, "allow-rsa-pkcs1-encrypt") == 0) {
2069
0
      p = clear_spaces(value, str);
2070
0
      if (c_strcasecmp(p, "true") == 0) {
2071
0
        cfg->allow_rsa_pkcs1_encrypt = true;
2072
0
      } else if (c_strcasecmp(p, "false") == 0) {
2073
0
        cfg->allow_rsa_pkcs1_encrypt = false;
2074
0
      } else {
2075
0
        _gnutls_debug_log(
2076
0
          "cfg: unknown RSA PKCS1 encryption mode %s\n",
2077
0
          p);
2078
0
        if (fail_on_invalid_config)
2079
0
          return 0;
2080
0
        goto exit;
2081
0
      }
2082
0
    } else {
2083
0
      _gnutls_debug_log("unknown parameter %s\n", name);
2084
0
      if (fail_on_invalid_config)
2085
0
        return 0;
2086
0
    }
2087
0
  } else if (c_strcasecmp(section, GLOBAL_SECTION) != 0) {
2088
0
    _gnutls_debug_log("cfg: unknown section %s\n", section);
2089
0
    if (fail_on_invalid_config)
2090
0
      return 0;
2091
0
  }
2092
2093
0
exit:
2094
0
  return 1;
2095
0
}
2096
2097
static int /* not locking system_wide_config */
2098
construct_system_wide_priority_string(gnutls_buffer_st *buf)
2099
0
{
2100
0
  int ret;
2101
0
  size_t i;
2102
2103
0
  _gnutls_buffer_init(buf);
2104
2105
0
  ret = _gnutls_buffer_append_str(buf, "NONE");
2106
0
  if (ret < 0) {
2107
0
    _gnutls_buffer_clear(buf);
2108
0
    return ret;
2109
0
  }
2110
2111
0
  for (i = 0; system_wide_config.kxs[i] != 0; i++) {
2112
0
    ret = _gnutls_buffer_append_str(buf, ":+");
2113
0
    if (ret < 0) {
2114
0
      _gnutls_buffer_clear(buf);
2115
0
      return ret;
2116
0
    }
2117
2118
0
    ret = _gnutls_buffer_append_str(
2119
0
      buf, gnutls_kx_get_name(system_wide_config.kxs[i]));
2120
0
    if (ret < 0) {
2121
0
      _gnutls_buffer_clear(buf);
2122
0
      return ret;
2123
0
    }
2124
0
  }
2125
2126
0
  for (i = 0; system_wide_config.groups[i] != 0; i++) {
2127
0
    ret = _gnutls_buffer_append_str(buf, ":+GROUP-");
2128
0
    if (ret < 0) {
2129
0
      _gnutls_buffer_clear(buf);
2130
0
      return ret;
2131
0
    }
2132
2133
0
    ret = _gnutls_buffer_append_str(
2134
0
      buf,
2135
0
      gnutls_group_get_name(system_wide_config.groups[i]));
2136
0
    if (ret < 0) {
2137
0
      _gnutls_buffer_clear(buf);
2138
0
      return ret;
2139
0
    }
2140
0
  }
2141
2142
0
  for (i = 0; system_wide_config.ciphers[i] != 0; i++) {
2143
0
    ret = _gnutls_buffer_append_str(buf, ":+");
2144
0
    if (ret < 0) {
2145
0
      _gnutls_buffer_clear(buf);
2146
0
      return ret;
2147
0
    }
2148
2149
0
    ret = _gnutls_buffer_append_str(
2150
0
      buf,
2151
0
      gnutls_cipher_get_name(system_wide_config.ciphers[i]));
2152
0
    if (ret < 0) {
2153
0
      _gnutls_buffer_clear(buf);
2154
0
      return ret;
2155
0
    }
2156
0
  }
2157
2158
0
  for (i = 0; system_wide_config.macs[i] != 0; i++) {
2159
0
    ret = _gnutls_buffer_append_str(buf, ":+");
2160
0
    if (ret < 0) {
2161
0
      _gnutls_buffer_clear(buf);
2162
0
      return ret;
2163
0
    }
2164
2165
0
    ret = _gnutls_buffer_append_str(
2166
0
      buf, gnutls_mac_get_name(system_wide_config.macs[i]));
2167
0
    if (ret < 0) {
2168
0
      _gnutls_buffer_clear(buf);
2169
0
      return ret;
2170
0
    }
2171
0
  }
2172
2173
0
  for (i = 0; system_wide_config.sigs[i] != 0; i++) {
2174
0
    ret = _gnutls_buffer_append_str(buf, ":+SIGN-");
2175
0
    if (ret < 0) {
2176
0
      _gnutls_buffer_clear(buf);
2177
0
      return ret;
2178
0
    }
2179
2180
0
    ret = _gnutls_buffer_append_str(
2181
0
      buf, gnutls_sign_get_name(system_wide_config.sigs[i]));
2182
0
    if (ret < 0) {
2183
0
      _gnutls_buffer_clear(buf);
2184
0
      return ret;
2185
0
    }
2186
0
  }
2187
2188
0
  for (i = 0; system_wide_config.versions[i] != 0; i++) {
2189
0
    ret = _gnutls_buffer_append_str(buf, ":+VERS-");
2190
0
    if (ret < 0) {
2191
0
      _gnutls_buffer_clear(buf);
2192
0
      return ret;
2193
0
    }
2194
2195
0
    ret = _gnutls_buffer_append_str(
2196
0
      buf, gnutls_protocol_get_name(
2197
0
             system_wide_config.versions[i]));
2198
0
    if (ret < 0) {
2199
0
      _gnutls_buffer_clear(buf);
2200
0
      return ret;
2201
0
    }
2202
0
  }
2203
0
  return 0;
2204
0
}
2205
2206
static int /* not locking system_wide_config */
2207
update_system_wide_priority_string(void)
2208
0
{
2209
  /* doesn't do locking, _gnutls_update_system_priorities does */
2210
0
  gnutls_buffer_st buf;
2211
0
  int ret;
2212
2213
0
  ret = construct_system_wide_priority_string(&buf);
2214
0
  if (ret < 0) {
2215
0
    _gnutls_debug_log("cfg: unable to construct "
2216
0
          "system-wide priority string: %s",
2217
0
          gnutls_strerror(ret));
2218
0
    _gnutls_buffer_clear(&buf);
2219
0
    return ret;
2220
0
  }
2221
2222
0
  gnutls_free(system_wide_config.priority_string);
2223
0
  system_wide_config.priority_string = gnutls_strdup((char *)buf.data);
2224
0
  _gnutls_buffer_clear(&buf);
2225
2226
0
  return 0;
2227
0
}
2228
2229
/* Returns false on parse error, otherwise true.
2230
 * The system_wide_config must be locked for writing.
2231
 */
2232
static inline bool load_system_priority_file(void)
2233
0
{
2234
0
  int err;
2235
0
  FILE *fp;
2236
0
  struct ini_ctx ctx;
2237
2238
0
  cfg_init(&system_wide_config);
2239
2240
0
  fp = fopen(system_priority_file, "re");
2241
0
  if (fp == NULL) {
2242
0
    _gnutls_debug_log("cfg: unable to open: %s: %d\n",
2243
0
          system_priority_file, errno);
2244
0
    return true;
2245
0
  }
2246
2247
  /* Parsing the configuration file needs to be done in 2 phases:
2248
   * first parsing the [global] section
2249
   * and then the other sections,
2250
   * because the [global] section modifies the parsing behavior.
2251
   */
2252
0
  ini_ctx_init(&ctx);
2253
0
  err = ini_parse_file(fp, global_ini_handler, &ctx);
2254
0
  if (!err) {
2255
0
    if (fseek(fp, 0L, SEEK_SET) < 0) {
2256
0
      _gnutls_debug_log("cfg: unable to rewind: %s\n",
2257
0
            system_priority_file);
2258
0
      if (fail_on_invalid_config)
2259
0
        exit(1);
2260
0
    }
2261
0
    err = ini_parse_file(fp, cfg_ini_handler, &ctx);
2262
0
  }
2263
0
  fclose(fp);
2264
0
  if (err) {
2265
0
    ini_ctx_deinit(&ctx);
2266
0
    _gnutls_debug_log("cfg: unable to parse: %s: %d\n",
2267
0
          system_priority_file, err);
2268
0
    return false;
2269
0
  }
2270
0
  cfg_apply(&system_wide_config, &ctx);
2271
0
  ini_ctx_deinit(&ctx);
2272
0
  return true;
2273
0
}
2274
2275
static int _gnutls_update_system_priorities(bool defer_system_wide)
2276
2
{
2277
2
  int ret;
2278
2
  bool config_parse_error = false;
2279
2
  struct stat sb;
2280
2
  gnutls_buffer_st buf;
2281
2282
2
  ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock);
2283
2
  if (ret < 0)
2284
0
    return gnutls_assert_val(ret);
2285
2286
2
  if (stat(system_priority_file, &sb) < 0) {
2287
2
    _gnutls_debug_log("cfg: unable to access: %s: %d\n",
2288
2
          system_priority_file, errno);
2289
2290
2
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
2291
2
    ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
2292
2
    if (ret < 0)
2293
0
      goto out;
2294
    /* If system-wide config is unavailable, apply the defaults */
2295
2
    cfg_init(&system_wide_config);
2296
2
    goto out;
2297
2
  }
2298
2299
0
  if (system_priority_file_loaded &&
2300
0
      system_priority_last_mod == sb.st_mtime) {
2301
0
    _gnutls_debug_log("cfg: system priority %s has not changed\n",
2302
0
          system_priority_file);
2303
0
    if (system_wide_config.priority_string)
2304
0
      goto out; /* nothing to do */
2305
0
  }
2306
2307
0
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
2308
2309
0
  ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
2310
0
  if (ret < 0)
2311
0
    return gnutls_assert_val(ret);
2312
2313
  /* Another thread could have successfully re-read system-wide config,
2314
   * skip re-reading if the mtime it has used is exactly the same.
2315
   */
2316
0
  if (system_priority_file_loaded)
2317
0
    system_priority_file_loaded =
2318
0
      (system_priority_last_mod == sb.st_mtime);
2319
2320
0
  if (!system_priority_file_loaded) {
2321
0
    config_parse_error = !load_system_priority_file();
2322
0
    if (config_parse_error)
2323
0
      goto out;
2324
0
    _gnutls_debug_log("cfg: loaded system config %s mtime %lld\n",
2325
0
          system_priority_file,
2326
0
          (unsigned long long)sb.st_mtime);
2327
0
  }
2328
2329
0
  if (system_wide_config.allowlisting) {
2330
0
    if (defer_system_wide) {
2331
      /* try constructing a priority string,
2332
       * but don't apply it yet, at this point
2333
       * we're only interested in whether we can */
2334
0
      ret = construct_system_wide_priority_string(&buf);
2335
0
      _gnutls_buffer_clear(&buf);
2336
0
      _gnutls_debug_log("cfg: deferred setting "
2337
0
            "system-wide priority string\n");
2338
0
    } else {
2339
0
      ret = update_system_wide_priority_string();
2340
0
      _gnutls_debug_log("cfg: finalized "
2341
0
            "system-wide priority string\n");
2342
0
    }
2343
0
    if (ret < 0) {
2344
0
      _gnutls_debug_log(
2345
0
        "cfg: unable to build priority string: %s\n",
2346
0
        gnutls_strerror(ret));
2347
0
      if (fail_on_invalid_config)
2348
0
        exit(1);
2349
0
      goto out;
2350
0
    }
2351
0
  }
2352
2353
0
  system_priority_file_loaded = 1;
2354
0
  system_priority_last_mod = sb.st_mtime;
2355
2356
2
out:
2357
2
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
2358
2359
2
  if (config_parse_error && fail_on_invalid_config)
2360
0
    exit(1);
2361
2362
2
  return ret;
2363
2
}
2364
2365
void _gnutls_prepare_to_load_system_priorities(void)
2366
2
{
2367
2
  const char *p;
2368
2
  int ret;
2369
2370
2
  p = secure_getenv("GNUTLS_SYSTEM_PRIORITY_FILE");
2371
2
  if (p != NULL)
2372
0
    system_priority_file = p;
2373
2374
2
  p = secure_getenv("GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID");
2375
2
  if (p != NULL && p[0] == '1' && p[1] == 0)
2376
0
    fail_on_invalid_config = 1;
2377
2378
2
  ret = _gnutls_update_system_priorities(true /* defer_system_wide */);
2379
2
  if (ret < 0) {
2380
0
    _gnutls_debug_log("failed to update system priorities: %s\n",
2381
0
          gnutls_strerror(ret));
2382
0
  }
2383
2
}
2384
2385
void _gnutls_unload_system_priorities(void)
2386
0
{
2387
0
  _name_val_array_clear(&system_wide_config.priority_strings);
2388
0
  gnutls_free(system_wide_config.priority_string);
2389
0
  _clear_default_system_priority();
2390
0
  system_priority_last_mod = 0;
2391
0
}
2392
2393
/**
2394
 * gnutls_get_system_config_file:
2395
 *
2396
 * Returns the filename of the system wide configuration
2397
 * file to be loaded by the library.
2398
 *
2399
 * Returns: a constant pointer to the config file path
2400
 *
2401
 * Since: 3.6.9
2402
 **/
2403
const char *gnutls_get_system_config_file(void)
2404
0
{
2405
0
  return system_priority_file;
2406
0
}
2407
2408
#define S(str) ((str != NULL) ? str : "")
2409
2410
/* Returns the new priorities if a priority string prefixed
2411
 * with '@' is provided, or just a copy of the provided
2412
 * priorities, appended with any additional present in
2413
 * the priorities string.
2414
 *
2415
 * The returned string must be released using gnutls_free().
2416
 */
2417
char *_gnutls_resolve_priorities(const char *priorities)
2418
0
{
2419
0
  const char *p = priorities;
2420
0
  char *additional = NULL;
2421
0
  char *resolved = NULL;
2422
0
  const char *ss, *ss_next;
2423
0
  unsigned ss_len, ss_next_len;
2424
0
  size_t n, n2 = 0;
2425
0
  int ret;
2426
2427
0
  while (c_isspace(*p)) {
2428
0
    p++;
2429
0
  }
2430
2431
  /* Cannot reduce further. */
2432
0
  if (*p != '@') {
2433
0
    return gnutls_strdup(p);
2434
0
  }
2435
2436
0
  ss = p + 1;
2437
0
  additional = strchr(ss, ':');
2438
0
  if (additional) {
2439
0
    additional++;
2440
0
  }
2441
2442
  /* Always try to refresh the cached data, to allow it to be
2443
   * updated without restarting all applications.
2444
   */
2445
0
  ret = _gnutls_update_system_priorities(false /* defer_system_wide */);
2446
0
  if (ret < 0) {
2447
0
    _gnutls_debug_log("failed to update system priorities: %s\n",
2448
0
          gnutls_strerror(ret));
2449
0
  }
2450
2451
0
  do {
2452
0
    ss_next = strchr(ss, ',');
2453
0
    if (ss_next) {
2454
0
      if (additional && ss_next > additional) {
2455
0
        ss_next = NULL;
2456
0
      } else {
2457
0
        ss_next++;
2458
0
      }
2459
0
    }
2460
2461
0
    if (ss_next) {
2462
0
      ss_len = ss_next - ss - 1;
2463
0
      ss_next_len = additional - ss_next - 1;
2464
0
    } else if (additional) {
2465
0
      ss_len = additional - ss - 1;
2466
0
      ss_next_len = 0;
2467
0
    } else {
2468
0
      ss_len = strlen(ss);
2469
0
      ss_next_len = 0;
2470
0
    }
2471
2472
0
    ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock);
2473
0
    if (ret < 0) {
2474
0
      _gnutls_debug_log(
2475
0
        "cannot read system priority strings: %s\n",
2476
0
        gnutls_strerror(ret));
2477
0
      break;
2478
0
    }
2479
0
    if (system_wide_config.allowlisting &&
2480
0
        ss_len == sizeof(LEVEL_SYSTEM) - 1 &&
2481
0
        strncmp(LEVEL_SYSTEM, ss, ss_len) == 0) {
2482
0
      p = system_wide_config.priority_string;
2483
0
    } else {
2484
0
      p = _name_val_array_value(
2485
0
        system_wide_config.priority_strings, ss,
2486
0
        ss_len);
2487
0
    }
2488
2489
0
    _gnutls_debug_log("resolved '%.*s' to '%s', next '%.*s'\n",
2490
0
          ss_len, ss, S(p), ss_next_len, S(ss_next));
2491
2492
0
    if (p) {
2493
0
      n = strlen(p);
2494
0
      if (additional) {
2495
0
        n2 = strlen(additional);
2496
0
      }
2497
2498
0
      resolved = gnutls_malloc(n + n2 + 1 + 1);
2499
0
      if (resolved) {
2500
0
        memcpy(resolved, p, n);
2501
0
        if (additional) {
2502
0
          resolved[n] = ':';
2503
0
          memcpy(&resolved[n + 1], additional,
2504
0
                 n2);
2505
0
          resolved[n + n2 + 1] = 0;
2506
0
        } else {
2507
0
          resolved[n] = 0;
2508
0
        }
2509
0
      }
2510
0
    }
2511
2512
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
2513
2514
0
    ss = ss_next;
2515
0
  } while (ss && !resolved);
2516
2517
0
  if (resolved) {
2518
0
    _gnutls_debug_log("selected priority string: %s\n", resolved);
2519
0
  } else {
2520
0
    _gnutls_debug_log("unable to resolve %s\n", priorities);
2521
0
  }
2522
2523
0
  return resolved;
2524
0
}
2525
2526
static void add_ec(gnutls_priority_t priority_cache)
2527
0
{
2528
0
  const gnutls_group_entry_st *ge;
2529
0
  unsigned i;
2530
2531
0
  for (i = 0; i < priority_cache->_supported_ecc.num_priorities; i++) {
2532
0
    ge = _gnutls_id_to_group(
2533
0
      priority_cache->_supported_ecc.priorities[i]);
2534
0
    if (ge != NULL &&
2535
0
        priority_cache->groups.size <
2536
0
          sizeof(priority_cache->groups.entry) /
2537
0
            sizeof(priority_cache->groups.entry[0])) {
2538
      /* do not add groups which do not correspond to enabled ciphersuites */
2539
0
      if (!ge->curve)
2540
0
        continue;
2541
0
      priority_cache->groups
2542
0
        .entry[priority_cache->groups.size++] = ge;
2543
0
    }
2544
0
  }
2545
0
}
2546
2547
static void add_dh(gnutls_priority_t priority_cache)
2548
0
{
2549
0
  const gnutls_group_entry_st *ge;
2550
0
  unsigned i;
2551
2552
0
  for (i = 0; i < priority_cache->_supported_ecc.num_priorities; i++) {
2553
0
    ge = _gnutls_id_to_group(
2554
0
      priority_cache->_supported_ecc.priorities[i]);
2555
0
    if (ge != NULL &&
2556
0
        priority_cache->groups.size <
2557
0
          sizeof(priority_cache->groups.entry) /
2558
0
            sizeof(priority_cache->groups.entry[0])) {
2559
      /* do not add groups which do not correspond to enabled ciphersuites */
2560
0
      if (!ge->prime)
2561
0
        continue;
2562
0
      priority_cache->groups
2563
0
        .entry[priority_cache->groups.size++] = ge;
2564
0
      priority_cache->groups.have_ffdhe = 1;
2565
0
    }
2566
0
  }
2567
0
}
2568
2569
static void add_hybrid(gnutls_priority_t priority_cache)
2570
0
{
2571
0
  const gnutls_group_entry_st *ge;
2572
0
  unsigned i;
2573
2574
0
  for (i = 0; i < priority_cache->_supported_ecc.num_priorities; i++) {
2575
0
    ge = _gnutls_id_to_group(
2576
0
      priority_cache->_supported_ecc.priorities[i]);
2577
0
    if (ge != NULL &&
2578
0
        priority_cache->groups.size <
2579
0
          sizeof(priority_cache->groups.entry) /
2580
0
            sizeof(priority_cache->groups.entry[0])) {
2581
      /* do not add groups which do not correspond to enabled ciphersuites */
2582
0
      if (!IS_GROUP_HYBRID(ge))
2583
0
        continue;
2584
0
      priority_cache->groups
2585
0
        .entry[priority_cache->groups.size++] = ge;
2586
0
    }
2587
0
  }
2588
0
}
2589
2590
/* This function was originally precalculating ciphersuite-specific items, however
2591
 * it has now extended to much more than that. It provides a consistency check to
2592
 * set parameters, and in cases it applies policy specific items.
2593
 */
2594
static int set_ciphersuite_list(gnutls_priority_t priority_cache)
2595
0
{
2596
0
  unsigned i, j, z;
2597
0
  const gnutls_cipher_suite_entry_st *ce;
2598
0
  const gnutls_sign_entry_st *se;
2599
0
  unsigned have_ec = 0;
2600
0
  unsigned have_dh = 0;
2601
0
  unsigned have_hybrid = 0;
2602
0
  unsigned tls_sig_sem = 0;
2603
0
  const version_entry_st *tlsmax = NULL, *vers;
2604
0
  const version_entry_st *dtlsmax = NULL;
2605
0
  const version_entry_st *tlsmin = NULL;
2606
0
  const version_entry_st *dtlsmin = NULL;
2607
0
  unsigned have_tls13 = 0, have_srp = 0;
2608
0
  unsigned have_pre_tls12 = 0, have_tls12 = 0;
2609
0
  unsigned have_psk = 0, have_null = 0, have_rsa_psk = 0;
2610
0
  gnutls_digest_algorithm_t prf_digest;
2611
0
  int ret = 0;
2612
2613
  /* have_psk indicates that a PSK key exchange compatible
2614
   * with TLS1.3 is enabled. */
2615
2616
0
  priority_cache->cs.size = 0;
2617
0
  priority_cache->sigalg.size = 0;
2618
0
  priority_cache->groups.size = 0;
2619
0
  priority_cache->groups.have_ffdhe = 0;
2620
2621
  /* The following requires a lock so there are no inconsistencies in the
2622
   * members of system_wide_config loaded from the config file. */
2623
0
  ret = gnutls_rwlock_rdlock(&system_wide_config_rwlock);
2624
0
  if (ret < 0) {
2625
0
    return gnutls_assert_val(ret);
2626
0
  }
2627
2628
  /* in blocklisting mode, apply system wide disablement of key exchanges,
2629
   * groups, MACs, and ciphers. */
2630
0
  if (!system_wide_config.allowlisting) {
2631
    /* disable key exchanges which are globally disabled */
2632
0
    z = 0;
2633
0
    while (system_wide_config.kxs[z] != 0) {
2634
0
      for (i = j = 0; i < priority_cache->_kx.num_priorities;
2635
0
           i++) {
2636
0
        if (priority_cache->_kx.priorities[i] !=
2637
0
            system_wide_config.kxs[z])
2638
0
          priority_cache->_kx.priorities[j++] =
2639
0
            priority_cache->_kx
2640
0
              .priorities[i];
2641
0
      }
2642
0
      priority_cache->_kx.num_priorities = j;
2643
0
      z++;
2644
0
    }
2645
2646
    /* disable groups which are globally disabled */
2647
0
    z = 0;
2648
0
    while (system_wide_config.groups[z] != 0) {
2649
0
      for (i = j = 0;
2650
0
           i < priority_cache->_supported_ecc.num_priorities;
2651
0
           i++) {
2652
0
        if (priority_cache->_supported_ecc
2653
0
              .priorities[i] !=
2654
0
            system_wide_config.groups[z])
2655
0
          priority_cache->_supported_ecc
2656
0
            .priorities[j++] =
2657
0
            priority_cache->_supported_ecc
2658
0
              .priorities[i];
2659
0
      }
2660
0
      priority_cache->_supported_ecc.num_priorities = j;
2661
0
      z++;
2662
0
    }
2663
2664
    /* disable ciphers which are globally disabled */
2665
0
    z = 0;
2666
0
    while (system_wide_config.ciphers[z] != 0) {
2667
0
      for (i = j = 0;
2668
0
           i < priority_cache->_cipher.num_priorities; i++) {
2669
0
        if (priority_cache->_cipher.priorities[i] !=
2670
0
            system_wide_config.ciphers[z])
2671
0
          priority_cache->_cipher.priorities[j++] =
2672
0
            priority_cache->_cipher
2673
0
              .priorities[i];
2674
0
      }
2675
0
      priority_cache->_cipher.num_priorities = j;
2676
0
      z++;
2677
0
    }
2678
2679
    /* disable MACs which are globally disabled */
2680
0
    z = 0;
2681
0
    while (system_wide_config.macs[z] != 0) {
2682
0
      for (i = j = 0; i < priority_cache->_mac.num_priorities;
2683
0
           i++) {
2684
0
        if (priority_cache->_mac.priorities[i] !=
2685
0
            system_wide_config.macs[z])
2686
0
          priority_cache->_mac.priorities[j++] =
2687
0
            priority_cache->_mac
2688
0
              .priorities[i];
2689
0
      }
2690
0
      priority_cache->_mac.num_priorities = j;
2691
0
      z++;
2692
0
    }
2693
0
  }
2694
2695
0
  for (j = 0; j < priority_cache->_cipher.num_priorities; j++) {
2696
0
    if (priority_cache->_cipher.priorities[j] ==
2697
0
        GNUTLS_CIPHER_NULL) {
2698
0
      have_null = 1;
2699
0
      break;
2700
0
    }
2701
0
  }
2702
2703
0
  for (i = 0; i < priority_cache->_kx.num_priorities; i++) {
2704
0
    if (IS_SRP_KX(priority_cache->_kx.priorities[i])) {
2705
0
      have_srp = 1;
2706
0
    } else if (_gnutls_kx_is_psk(
2707
0
           priority_cache->_kx.priorities[i])) {
2708
0
      if (priority_cache->_kx.priorities[i] ==
2709
0
          GNUTLS_KX_RSA_PSK)
2710
0
        have_rsa_psk = 1;
2711
0
      else
2712
0
        have_psk = 1;
2713
0
    }
2714
0
  }
2715
2716
  /* disable TLS versions which are added but are unsupported */
2717
0
  for (i = j = 0; i < priority_cache->protocol.num_priorities; i++) {
2718
0
    vers = version_to_entry(priority_cache->protocol.priorities[i]);
2719
0
    if (!vers || vers->supported ||
2720
0
        (system_wide_config.allowlisting &&
2721
0
         vers->supported_revertible))
2722
0
      priority_cache->protocol.priorities[j++] =
2723
0
        priority_cache->protocol.priorities[i];
2724
0
  }
2725
0
  priority_cache->protocol.num_priorities = j;
2726
2727
  /* if we have NULL ciphersuites, SRP, or RSA-PSK enabled remove TLS1.3+
2728
   * protocol versions; they cannot be negotiated under TLS1.3. */
2729
0
  if (have_null || have_srp || have_rsa_psk ||
2730
0
      priority_cache->no_extensions) {
2731
0
    for (i = j = 0; i < priority_cache->protocol.num_priorities;
2732
0
         i++) {
2733
0
      vers = version_to_entry(
2734
0
        priority_cache->protocol.priorities[i]);
2735
0
      if (!vers || !vers->tls13_sem)
2736
0
        priority_cache->protocol.priorities[j++] =
2737
0
          priority_cache->protocol.priorities[i];
2738
0
    }
2739
0
    priority_cache->protocol.num_priorities = j;
2740
0
  }
2741
2742
0
  for (i = 0; i < priority_cache->protocol.num_priorities; i++) {
2743
0
    vers = version_to_entry(priority_cache->protocol.priorities[i]);
2744
0
    if (!vers)
2745
0
      continue;
2746
2747
0
    if (vers->transport == GNUTLS_STREAM) { /* TLS */
2748
0
      tls_sig_sem |= vers->tls_sig_sem;
2749
0
      if (vers->tls13_sem)
2750
0
        have_tls13 = 1;
2751
2752
0
      if (vers->id == GNUTLS_TLS1_2)
2753
0
        have_tls12 = 1;
2754
0
      else if (vers->id < GNUTLS_TLS1_2)
2755
0
        have_pre_tls12 = 1;
2756
2757
0
      if (tlsmax == NULL || vers->age > tlsmax->age)
2758
0
        tlsmax = vers;
2759
0
      if (tlsmin == NULL || vers->age < tlsmin->age)
2760
0
        tlsmin = vers;
2761
0
    } else { /* dtls */
2762
0
      tls_sig_sem |= vers->tls_sig_sem;
2763
2764
      /* we need to introduce similar handling to above
2765
       * when DTLS1.3 is supported */
2766
2767
0
      if (dtlsmax == NULL || vers->age > dtlsmax->age)
2768
0
        dtlsmax = vers;
2769
0
      if (dtlsmin == NULL || vers->age < dtlsmin->age)
2770
0
        dtlsmin = vers;
2771
0
    }
2772
0
  }
2773
2774
  /* DTLS or TLS protocols must be present */
2775
0
  if ((!tlsmax || !tlsmin) && (!dtlsmax || !dtlsmin)) {
2776
0
    ret = gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
2777
0
    goto out;
2778
0
  }
2779
2780
0
  priority_cache->have_psk = have_psk;
2781
2782
  /* if we are have TLS1.3+ do not enable any key exchange algorithms,
2783
   * the protocol doesn't require any. */
2784
0
  if (tlsmin && tlsmin->tls13_sem && !have_psk) {
2785
0
    if (!dtlsmin || (dtlsmin && dtlsmin->tls13_sem))
2786
0
      priority_cache->_kx.num_priorities = 0;
2787
0
  }
2788
2789
  /* Add TLS 1.3 ciphersuites (no KX) */
2790
0
  for (j = 0; j < priority_cache->_cipher.num_priorities; j++) {
2791
0
    for (z = 0; z < priority_cache->_mac.num_priorities; z++) {
2792
0
      ce = cipher_suite_get(
2793
0
        0, priority_cache->_cipher.priorities[j],
2794
0
        priority_cache->_mac.priorities[z]);
2795
0
      if (ce == NULL)
2796
0
        continue;
2797
2798
0
      prf_digest = MAC_TO_DIG(ce->prf);
2799
0
      if (prf_digest == GNUTLS_DIG_UNKNOWN)
2800
0
        continue;
2801
0
      if (_gnutls_digest_is_insecure(prf_digest))
2802
0
        continue;
2803
2804
0
      if (priority_cache->cs.size == MAX_CIPHERSUITE_SIZE)
2805
0
        continue;
2806
2807
0
      priority_cache->cs.entry[priority_cache->cs.size++] =
2808
0
        ce;
2809
2810
0
      if (!have_hybrid) {
2811
0
        have_hybrid = 1;
2812
0
        add_hybrid(priority_cache);
2813
0
      }
2814
0
    }
2815
0
  }
2816
2817
0
  for (i = 0; i < priority_cache->_kx.num_priorities; i++) {
2818
0
    for (j = 0; j < priority_cache->_cipher.num_priorities; j++) {
2819
0
      for (z = 0; z < priority_cache->_mac.num_priorities;
2820
0
           z++) {
2821
0
        ce = cipher_suite_get(
2822
0
          priority_cache->_kx.priorities[i],
2823
0
          priority_cache->_cipher.priorities[j],
2824
0
          priority_cache->_mac.priorities[z]);
2825
0
        if (ce == NULL)
2826
0
          continue;
2827
2828
0
        prf_digest = MAC_TO_DIG(ce->prf);
2829
0
        if (prf_digest == GNUTLS_DIG_UNKNOWN)
2830
0
          continue;
2831
0
        if (_gnutls_digest_is_insecure(prf_digest))
2832
0
          continue;
2833
2834
0
        if (priority_cache->cs.size ==
2835
0
            MAX_CIPHERSUITE_SIZE)
2836
0
          continue;
2837
0
        priority_cache->cs
2838
0
          .entry[priority_cache->cs.size++] = ce;
2839
0
        if (!have_ec &&
2840
0
            (_gnutls_kx_is_ecc(ce->kx_algorithm) ||
2841
0
             _gnutls_kx_is_vko_gost(ce->kx_algorithm))) {
2842
0
          have_ec = 1;
2843
0
          add_ec(priority_cache);
2844
0
        }
2845
0
        if (!have_dh &&
2846
0
            _gnutls_kx_is_dhe(ce->kx_algorithm)) {
2847
0
          have_dh = 1;
2848
0
          add_dh(priority_cache);
2849
0
        }
2850
0
      }
2851
0
    }
2852
0
  }
2853
2854
0
  if (have_tls13 && (!have_ec || !have_dh || !have_hybrid)) {
2855
    /* scan groups to determine have_{ec,dh,hybrid} */
2856
0
    for (i = 0; i < priority_cache->_supported_ecc.num_priorities;
2857
0
         i++) {
2858
0
      const gnutls_group_entry_st *ge;
2859
0
      ge = _gnutls_id_to_group(
2860
0
        priority_cache->_supported_ecc.priorities[i]);
2861
0
      if (ge) {
2862
0
        if (ge->curve && !have_ec) {
2863
0
          add_ec(priority_cache);
2864
0
          have_ec = 1;
2865
0
        } else if (ge->prime && !have_dh) {
2866
0
          add_dh(priority_cache);
2867
0
          have_dh = 1;
2868
0
        } else if (IS_GROUP_HYBRID(ge) &&
2869
0
             !have_hybrid) {
2870
0
          add_hybrid(priority_cache);
2871
0
          have_hybrid = 1;
2872
0
        }
2873
2874
0
        if (have_dh && have_ec && have_hybrid)
2875
0
          break;
2876
0
      }
2877
0
    }
2878
0
  }
2879
2880
0
  for (i = 0; i < priority_cache->_sign_algo.num_priorities; i++) {
2881
0
    se = _gnutls_sign_to_entry(
2882
0
      priority_cache->_sign_algo.priorities[i]);
2883
0
    if (se != NULL &&
2884
0
        priority_cache->sigalg.size <
2885
0
          sizeof(priority_cache->sigalg.entry) /
2886
0
            sizeof(priority_cache->sigalg.entry[0])) {
2887
      /* if the signature algorithm semantics is not
2888
       * compatible with the protocol's, or the algorithm is
2889
       * marked as insecure, then skip. */
2890
0
      if ((se->aid.tls_sem & tls_sig_sem) == 0 ||
2891
0
          !_gnutls_sign_is_secure2(
2892
0
            se,
2893
0
            system_wide_config.allowlisting ?
2894
0
              GNUTLS_SIGN_FLAG_ALLOW_INSECURE_REVERTIBLE :
2895
0
              0)) {
2896
0
        continue;
2897
0
      }
2898
0
      priority_cache->sigalg
2899
0
        .entry[priority_cache->sigalg.size++] = se;
2900
0
    }
2901
0
  }
2902
2903
0
  _gnutls_debug_log(
2904
0
    "added %d protocols, %d ciphersuites, %d sig algos and %d groups into priority list\n",
2905
0
    priority_cache->protocol.num_priorities,
2906
0
    priority_cache->cs.size, priority_cache->sigalg.size,
2907
0
    priority_cache->groups.size);
2908
2909
0
  if (priority_cache->sigalg.size == 0) {
2910
    /* no signature algorithms; eliminate TLS 1.2 or DTLS 1.2 and later */
2911
0
    priority_st newp;
2912
0
    newp.num_priorities = 0;
2913
2914
    /* we need to eliminate TLS 1.2 or DTLS 1.2 and later protocols */
2915
0
    for (i = 0; i < priority_cache->protocol.num_priorities; i++) {
2916
0
      if (priority_cache->protocol.priorities[i] <
2917
0
          GNUTLS_TLS1_2) {
2918
0
        newp.priorities[newp.num_priorities++] =
2919
0
          priority_cache->protocol.priorities[i];
2920
0
      } else if (priority_cache->protocol.priorities[i] >=
2921
0
             GNUTLS_DTLS_VERSION_MIN &&
2922
0
           priority_cache->protocol.priorities[i] <
2923
0
             GNUTLS_DTLS1_2) {
2924
0
        newp.priorities[newp.num_priorities++] =
2925
0
          priority_cache->protocol.priorities[i];
2926
0
      }
2927
0
    }
2928
0
    memcpy(&priority_cache->protocol, &newp, sizeof(newp));
2929
0
  }
2930
2931
0
  if (unlikely(priority_cache->protocol.num_priorities == 0)) {
2932
0
    ret = gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
2933
0
    goto out;
2934
0
  }
2935
0
#ifndef ENABLE_SSL3
2936
0
  else if (unlikely(priority_cache->protocol.num_priorities == 1 &&
2937
0
        priority_cache->protocol.priorities[0] ==
2938
0
          GNUTLS_SSL3)) {
2939
0
    ret = gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
2940
0
    goto out;
2941
0
  }
2942
0
#endif
2943
2944
0
  if (unlikely(priority_cache->cs.size == 0)) {
2945
0
    ret = gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
2946
0
    goto out;
2947
0
  }
2948
2949
  /* when TLS 1.3 is available we must have groups set; additionally
2950
   * we require TLS1.2 to be enabled if TLS1.3 is asked for, and
2951
   * a pre-TLS1.2 protocol is there; that is because servers which
2952
   * do not support TLS1.3 will negotiate TLS1.2 if seen a TLS1.3 handshake */
2953
0
  if (unlikely((!have_psk && tlsmax && tlsmax->id >= GNUTLS_TLS1_3 &&
2954
0
          priority_cache->groups.size == 0)) ||
2955
0
      (!have_tls12 && have_pre_tls12 && have_tls13)) {
2956
0
    for (i = j = 0; i < priority_cache->protocol.num_priorities;
2957
0
         i++) {
2958
0
      vers = version_to_entry(
2959
0
        priority_cache->protocol.priorities[i]);
2960
0
      if (!vers || vers->transport != GNUTLS_STREAM ||
2961
0
          !vers->tls13_sem)
2962
0
        priority_cache->protocol.priorities[j++] =
2963
0
          priority_cache->protocol.priorities[i];
2964
0
    }
2965
0
    priority_cache->protocol.num_priorities = j;
2966
0
  }
2967
2968
  /* ensure that the verification profile is not lower from the configured */
2969
0
  if (system_wide_config.verification_profile) {
2970
0
    gnutls_sec_param_t level = priority_cache->level;
2971
0
    gnutls_sec_param_t system_wide_level =
2972
0
      _gnutls_profile_to_sec_level(
2973
0
        system_wide_config.verification_profile);
2974
2975
0
    if (level < system_wide_level) {
2976
0
      ENABLE_PROFILE(priority_cache,
2977
0
               system_wide_config.verification_profile);
2978
0
    }
2979
0
  }
2980
2981
0
out:
2982
0
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
2983
0
  return ret;
2984
0
}
2985
2986
/**
2987
 * gnutls_priority_init2:
2988
 * @priority_cache: is a #gnutls_priority_t type.
2989
 * @priorities: is a string describing priorities (may be %NULL)
2990
 * @err_pos: In case of an error this will have the position in the string the error occurred
2991
 * @flags: zero or %GNUTLS_PRIORITY_INIT_DEF_APPEND
2992
 *
2993
 * Sets priorities for the ciphers, key exchange methods, and macs.
2994
 * The @priority_cache should be deinitialized
2995
 * using gnutls_priority_deinit().
2996
 *
2997
 * The #priorities option allows you to specify a colon
2998
 * separated list of the cipher priorities to enable.
2999
 * Some keywords are defined to provide quick access
3000
 * to common preferences.
3001
 *
3002
 * When @flags is set to %GNUTLS_PRIORITY_INIT_DEF_APPEND then the @priorities
3003
 * specified will be appended to the default options.
3004
 *
3005
 * Unless there is a special need, use the "NORMAL" keyword to
3006
 * apply a reasonable security level, or "NORMAL:%%COMPAT" for compatibility.
3007
 *
3008
 * "PERFORMANCE" means all the "secure" ciphersuites are enabled,
3009
 * limited to 128 bit ciphers and sorted by terms of speed
3010
 * performance.
3011
 *
3012
 * "LEGACY" the NORMAL settings for GnuTLS 3.2.x or earlier. There is
3013
 * no verification profile set, and the allowed DH primes are considered
3014
 * weak today.
3015
 *
3016
 * "NORMAL" means all "secure" ciphersuites. The 256-bit ciphers are
3017
 * included as a fallback only.  The ciphers are sorted by security
3018
 * margin.
3019
 *
3020
 * "PFS" means all "secure" ciphersuites that support perfect forward secrecy.
3021
 * The 256-bit ciphers are included as a fallback only.
3022
 * The ciphers are sorted by security margin.
3023
 *
3024
 * "SECURE128" means all "secure" ciphersuites of security level 128-bit
3025
 * or more.
3026
 *
3027
 * "SECURE192" means all "secure" ciphersuites of security level 192-bit
3028
 * or more.
3029
 *
3030
 * "SUITEB128" means all the NSA SuiteB ciphersuites with security level
3031
 * of 128.
3032
 *
3033
 * "SUITEB192" means all the NSA SuiteB ciphersuites with security level
3034
 * of 192.
3035
 *
3036
 * "NONE" means nothing is enabled.  This disables everything, including protocols.
3037
 *
3038
 * "@@KEYWORD1,KEYWORD2,..." The system administrator imposed settings.
3039
 * The provided keyword(s) will be expanded from a configuration-time
3040
 * provided file - default is: /etc/gnutls/config.
3041
 * Any attributes that follow it, will be appended to the expanded
3042
 * string. If multiple keywords are provided, separated by commas,
3043
 * then the first keyword that exists in the configuration file
3044
 * will be used. At least one of the keywords must exist, or this
3045
 * function will return an error. Typical usage would be to specify
3046
 * an application specified keyword first, followed by "SYSTEM" as
3047
 * a default fallback. e.g., "@LIBVIRT,SYSTEM:!-VERS-SSL3.0" will
3048
 * first try to find a config file entry matching "LIBVIRT", but if
3049
 * that does not exist will use the entry for "SYSTEM". If "SYSTEM"
3050
 * does not exist either, an error will be returned. In all cases,
3051
 * the SSL3.0 protocol will be disabled. The system priority file
3052
 * entries should be formatted as "KEYWORD=VALUE", e.g.,
3053
 * "SYSTEM=NORMAL:+ARCFOUR-128".
3054
 *
3055
 * Special keywords are "!", "-" and "+".
3056
 * "!" or "-" appended with an algorithm will remove this algorithm.
3057
 * "+" appended with an algorithm will add this algorithm.
3058
 *
3059
 * Check the GnuTLS manual section "Priority strings" for detailed
3060
 * information.
3061
 *
3062
 * Examples:
3063
 *
3064
 * "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"
3065
 *
3066
 * "NORMAL:+ARCFOUR-128" means normal ciphers plus ARCFOUR-128.
3067
 *
3068
 * "SECURE128:-VERS-SSL3.0" means that only secure ciphers are
3069
 * and enabled, SSL3.0 is disabled.
3070
 *
3071
 * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1",
3072
 *
3073
 * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+ECDHE-RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1:+CURVE-SECP256R1",
3074
 *
3075
 * "SECURE256:+SECURE128",
3076
 *
3077
 * Note that "NORMAL:%%COMPAT" is the most compatible mode.
3078
 *
3079
 * A %NULL @priorities string indicates the default priorities to be
3080
 * used (this is available since GnuTLS 3.3.0).
3081
 *
3082
 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
3083
 * %GNUTLS_E_SUCCESS on success, or an error code.
3084
 *
3085
 * Since: 3.6.3
3086
 **/
3087
int gnutls_priority_init2(gnutls_priority_t *priority_cache,
3088
        const char *priorities, const char **err_pos,
3089
        unsigned flags)
3090
0
{
3091
0
  gnutls_buffer_st buf;
3092
0
  const char *ep;
3093
0
  int ret;
3094
3095
0
  *priority_cache = NULL;
3096
0
  if (flags & GNUTLS_PRIORITY_INIT_DEF_APPEND) {
3097
0
    if (priorities == NULL)
3098
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
3099
3100
0
    if (err_pos)
3101
0
      *err_pos = priorities;
3102
3103
0
    _gnutls_buffer_init(&buf);
3104
3105
0
    ret = _gnutls_buffer_append_str(
3106
0
      &buf, _gnutls_default_priority_string);
3107
0
    if (ret < 0) {
3108
0
      _gnutls_buffer_clear(&buf);
3109
0
      return gnutls_assert_val(ret);
3110
0
    }
3111
3112
0
    ret = _gnutls_buffer_append_str(&buf, ":");
3113
0
    if (ret < 0) {
3114
0
      _gnutls_buffer_clear(&buf);
3115
0
      return gnutls_assert_val(ret);
3116
0
    }
3117
3118
0
    ret = _gnutls_buffer_append_str(&buf, priorities);
3119
0
    if (ret < 0) {
3120
0
      _gnutls_buffer_clear(&buf);
3121
0
      return gnutls_assert_val(ret);
3122
0
    }
3123
3124
0
    ret = gnutls_priority_init(priority_cache,
3125
0
             (const char *)buf.data, &ep);
3126
0
    if (ret < 0 && ep != (const char *)buf.data && ep != NULL) {
3127
0
      ptrdiff_t diff = (ptrdiff_t)ep - (ptrdiff_t)buf.data;
3128
0
      unsigned hlen =
3129
0
        strlen(_gnutls_default_priority_string) + 1;
3130
3131
0
      if (err_pos && diff > hlen) {
3132
0
        *err_pos = priorities + diff - hlen;
3133
0
      }
3134
0
    }
3135
0
    _gnutls_buffer_clear(&buf);
3136
0
    return ret;
3137
0
  } else {
3138
0
    return gnutls_priority_init(priority_cache, priorities,
3139
0
              err_pos);
3140
0
  }
3141
0
}
3142
3143
#define PRIO_MATCH(name) \
3144
0
  c_strncasecmp(&broken_list[i][1], name, sizeof(name) - 1)
3145
3146
/**
3147
 * gnutls_priority_init:
3148
 * @priority_cache: is a #gnutls_priority_t type.
3149
 * @priorities: is a string describing priorities (may be %NULL)
3150
 * @err_pos: In case of an error this will have the position in the string the error occurred
3151
 *
3152
 * For applications that do not modify their crypto settings per release, consider
3153
 * using gnutls_priority_init2() with %GNUTLS_PRIORITY_INIT_DEF_APPEND flag
3154
 * instead. We suggest to use centralized crypto settings handled by the GnuTLS
3155
 * library, and applications modifying the default settings to their needs.
3156
 *
3157
 * This function is identical to gnutls_priority_init2() with zero
3158
 * flags.
3159
 *
3160
 * A %NULL @priorities string indicates the default priorities to be
3161
 * used (this is available since GnuTLS 3.3.0).
3162
 *
3163
 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
3164
 * %GNUTLS_E_SUCCESS on success, or an error code.
3165
 **/
3166
int gnutls_priority_init(gnutls_priority_t *priority_cache,
3167
       const char *priorities, const char **err_pos)
3168
0
{
3169
0
  char *broken_list[MAX_ELEMENTS];
3170
0
  int broken_list_size = 0, i = 0, j;
3171
0
  char *darg = NULL;
3172
0
  unsigned ikeyword_set = 0;
3173
0
  int algo;
3174
0
  int ret;
3175
0
  rmadd_func *fn;
3176
0
  bulk_rmadd_func *bulk_fn;
3177
0
  bulk_rmadd_func *bulk_given_fn;
3178
0
  const cipher_entry_st *centry;
3179
0
  unsigned resolved_match = 1;
3180
3181
0
  if (err_pos)
3182
0
    *err_pos = priorities;
3183
3184
0
  *priority_cache = gnutls_calloc(1, sizeof(struct gnutls_priority_st));
3185
0
  if (*priority_cache == NULL) {
3186
0
    gnutls_assert();
3187
0
    return GNUTLS_E_MEMORY_ERROR;
3188
0
  }
3189
3190
  /* for now unsafe renegotiation is default on everyone. To be removed
3191
   * when we make it the default.
3192
   */
3193
0
  (*priority_cache)->sr = SR_PARTIAL;
3194
  /* For now TLS 1.3 middlebox compatibility mode is enabled by default.
3195
   * This will eventually be disabled by default and moved to the %COMPAT
3196
   * setting.
3197
   */
3198
0
  (*priority_cache)->tls13_compat_mode = true;
3199
0
  (*priority_cache)->min_record_version = 1;
3200
0
  gnutls_atomic_init(&(*priority_cache)->usage_cnt);
3201
3202
0
  if (_gnutls_fips_mode_enabled()) {
3203
0
    (*priority_cache)->force_ext_master_secret = EMS_REQUIRE;
3204
0
  } else {
3205
0
    (*priority_cache)->force_ext_master_secret = EMS_REQUEST;
3206
0
  }
3207
3208
0
  if (system_wide_config.allowlisting && !priorities) {
3209
0
    priorities = "@" LEVEL_SYSTEM;
3210
0
  }
3211
0
  if (priorities == NULL) {
3212
0
    priorities = _gnutls_default_priority_string;
3213
0
    resolved_match = 0;
3214
0
  }
3215
3216
0
  darg = _gnutls_resolve_priorities(priorities);
3217
0
  if (darg == NULL) {
3218
0
    gnutls_assert();
3219
0
    goto error;
3220
0
  }
3221
3222
0
  if (strcmp(darg, priorities) != 0)
3223
0
    resolved_match = 0;
3224
3225
0
  break_list(darg, broken_list, &broken_list_size);
3226
  /* This is our default set of protocol version, certificate types.
3227
   */
3228
0
  if (c_strcasecmp(broken_list[0], LEVEL_NONE) != 0) {
3229
0
    _set_priority(&(*priority_cache)->protocol, protocol_priority);
3230
0
    _set_priority(&(*priority_cache)->client_ctype,
3231
0
            cert_type_priority_default);
3232
0
    _set_priority(&(*priority_cache)->server_ctype,
3233
0
            cert_type_priority_default);
3234
0
    _set_priority(&(*priority_cache)->_sign_algo,
3235
0
            sign_priority_default);
3236
0
    _set_priority(&(*priority_cache)->_supported_ecc,
3237
0
            supported_groups_normal);
3238
0
    i = 0;
3239
0
  } else {
3240
0
    ikeyword_set = 1;
3241
0
    i = 1;
3242
0
  }
3243
3244
0
  for (; i < broken_list_size; i++) {
3245
0
    if (check_level(broken_list[i], *priority_cache,
3246
0
        ikeyword_set) != 0) {
3247
0
      ikeyword_set = 1;
3248
0
      continue;
3249
0
    } else if (broken_list[i][0] == '!' ||
3250
0
         broken_list[i][0] == '+' ||
3251
0
         broken_list[i][0] == '-') {
3252
0
      if (broken_list[i][0] == '+') {
3253
0
        fn = prio_add;
3254
0
        bulk_fn = _add_priority;
3255
0
        bulk_given_fn = _add_priority;
3256
0
      } else {
3257
0
        fn = prio_remove;
3258
0
        bulk_fn = _clear_priorities;
3259
0
        bulk_given_fn = _clear_given_priorities;
3260
0
      }
3261
3262
0
      if (broken_list[i][0] == '+' &&
3263
0
          check_level(&broken_list[i][1], *priority_cache,
3264
0
          1) != 0) {
3265
0
        continue;
3266
0
      } else if ((algo = gnutls_mac_get_id(
3267
0
              &broken_list[i][1])) !=
3268
0
           GNUTLS_MAC_UNKNOWN) {
3269
0
        fn(&(*priority_cache)->_mac, algo);
3270
0
      } else if ((centry = cipher_name_to_entry(
3271
0
              &broken_list[i][1])) != NULL) {
3272
0
        if (_gnutls_cipher_exists(centry->id)) {
3273
0
          fn(&(*priority_cache)->_cipher,
3274
0
             centry->id);
3275
0
          if (centry->type == CIPHER_BLOCK)
3276
0
            (*priority_cache)->have_cbc = 1;
3277
0
        }
3278
0
      } else if ((algo = _gnutls_kx_get_id(
3279
0
              &broken_list[i][1])) !=
3280
0
           GNUTLS_KX_UNKNOWN) {
3281
0
        if (algo != GNUTLS_KX_INVALID)
3282
0
          fn(&(*priority_cache)->_kx, algo);
3283
0
      } else if (PRIO_MATCH("VERS-") == 0) {
3284
0
        if (PRIO_MATCH("VERS-TLS-ALL") == 0) {
3285
0
          bulk_given_fn(
3286
0
            &(*priority_cache)->protocol,
3287
0
            stream_protocol_priority);
3288
0
        } else if (PRIO_MATCH("VERS-DTLS-ALL") == 0) {
3289
0
          bulk_given_fn(
3290
0
            &(*priority_cache)->protocol,
3291
0
            (bulk_given_fn ==
3292
0
             _add_priority) ?
3293
0
              dtls_protocol_priority :
3294
0
              dgram_protocol_priority);
3295
0
        } else if (PRIO_MATCH("VERS-ALL") == 0) {
3296
0
          bulk_fn(&(*priority_cache)->protocol,
3297
0
            protocol_priority);
3298
0
        } else {
3299
0
          if ((algo = gnutls_protocol_get_id(
3300
0
                 &broken_list[i][6])) !=
3301
0
              GNUTLS_VERSION_UNKNOWN) {
3302
0
            fn(&(*priority_cache)->protocol,
3303
0
               algo);
3304
0
          } else
3305
0
            goto error;
3306
0
        }
3307
0
      } /* now check if the element is something like -ALGO */
3308
0
      else if (PRIO_MATCH("COMP-") == 0) {
3309
        /* ignore all compression methods */
3310
0
        continue;
3311
0
      } /* now check if the element is something like -ALGO */
3312
0
      else if (PRIO_MATCH("CURVE-") == 0) {
3313
0
        if (PRIO_MATCH("CURVE-ALL") == 0) {
3314
0
          bulk_fn(&(*priority_cache)
3315
0
               ->_supported_ecc,
3316
0
            supported_groups_normal);
3317
0
        } else {
3318
0
          if ((algo = gnutls_ecc_curve_get_id(
3319
0
                 &broken_list[i][7])) !=
3320
0
              GNUTLS_ECC_CURVE_INVALID)
3321
0
            fn(&(*priority_cache)
3322
0
                  ->_supported_ecc,
3323
0
               algo);
3324
0
          else
3325
0
            goto error;
3326
0
        }
3327
0
      } else if (PRIO_MATCH("GROUP-") == 0) {
3328
0
        if (PRIO_MATCH("GROUP-ALL") == 0) {
3329
0
          bulk_fn(&(*priority_cache)
3330
0
               ->_supported_ecc,
3331
0
            supported_groups_normal);
3332
0
        } else if (PRIO_MATCH("GROUP-DH-ALL") == 0) {
3333
0
          bulk_given_fn(&(*priority_cache)
3334
0
                     ->_supported_ecc,
3335
0
                  _supported_groups_dh);
3336
0
        } else if (PRIO_MATCH("GROUP-EC-ALL") == 0) {
3337
0
          bulk_given_fn(&(*priority_cache)
3338
0
                     ->_supported_ecc,
3339
0
                  _supported_groups_ecdh);
3340
0
        } else if (PRIO_MATCH("GROUP-GOST-ALL") == 0) {
3341
0
          bulk_given_fn(&(*priority_cache)
3342
0
                     ->_supported_ecc,
3343
0
                  _supported_groups_gost);
3344
0
        } else {
3345
0
          if ((algo = _gnutls_group_get_id(
3346
0
                 &broken_list[i][7])) !=
3347
0
              GNUTLS_GROUP_INVALID)
3348
0
            fn(&(*priority_cache)
3349
0
                  ->_supported_ecc,
3350
0
               algo);
3351
0
          else
3352
0
            goto error;
3353
0
        }
3354
0
      } else if (PRIO_MATCH("CTYPE-") == 0) {
3355
        // Certificate types
3356
0
        if (PRIO_MATCH("CTYPE-ALL") == 0) {
3357
          // Symmetric cert types, all types allowed
3358
0
          bulk_fn(&(*priority_cache)->client_ctype,
3359
0
            cert_type_priority_all);
3360
0
          bulk_fn(&(*priority_cache)->server_ctype,
3361
0
            cert_type_priority_all);
3362
0
        } else if (PRIO_MATCH("CTYPE-CLI-") == 0) {
3363
          // Client certificate types
3364
0
          if (PRIO_MATCH("CTYPE-CLI-ALL") == 0) {
3365
            // All client cert types allowed
3366
0
            bulk_fn(&(*priority_cache)
3367
0
                 ->client_ctype,
3368
0
              cert_type_priority_all);
3369
0
          } else if ((algo = gnutls_certificate_type_get_id(
3370
0
                  &broken_list[i]
3371
0
                  [11])) !=
3372
0
               GNUTLS_CRT_UNKNOWN) {
3373
            // Specific client cert type allowed
3374
0
            fn(&(*priority_cache)
3375
0
                  ->client_ctype,
3376
0
               algo);
3377
0
          } else
3378
0
            goto error;
3379
0
        } else if (PRIO_MATCH("CTYPE-SRV-") == 0) {
3380
          // Server certificate types
3381
0
          if (PRIO_MATCH("CTYPE-SRV-ALL") == 0) {
3382
            // All server cert types allowed
3383
0
            bulk_fn(&(*priority_cache)
3384
0
                 ->server_ctype,
3385
0
              cert_type_priority_all);
3386
0
          } else if ((algo = gnutls_certificate_type_get_id(
3387
0
                  &broken_list[i]
3388
0
                  [11])) !=
3389
0
               GNUTLS_CRT_UNKNOWN) {
3390
            // Specific server cert type allowed
3391
0
            fn(&(*priority_cache)
3392
0
                  ->server_ctype,
3393
0
               algo);
3394
0
          } else
3395
0
            goto error;
3396
0
        } else { // Symmetric certificate type
3397
0
          if ((algo = gnutls_certificate_type_get_id(
3398
0
                 &broken_list[i][7])) !=
3399
0
              GNUTLS_CRT_UNKNOWN) {
3400
0
            fn(&(*priority_cache)
3401
0
                  ->client_ctype,
3402
0
               algo);
3403
0
            fn(&(*priority_cache)
3404
0
                  ->server_ctype,
3405
0
               algo);
3406
0
          } else if (PRIO_MATCH(
3407
0
                 "CTYPE-OPENPGP") ==
3408
0
               0) {
3409
            /* legacy openpgp option - ignore */
3410
0
            continue;
3411
0
          } else
3412
0
            goto error;
3413
0
        }
3414
0
      } else if (PRIO_MATCH("SIGN-") == 0) {
3415
0
        if (PRIO_MATCH("SIGN-ALL") == 0) {
3416
0
          bulk_fn(&(*priority_cache)->_sign_algo,
3417
0
            sign_priority_default);
3418
0
        } else if (PRIO_MATCH("SIGN-GOST-ALL") == 0) {
3419
0
          bulk_fn(&(*priority_cache)->_sign_algo,
3420
0
            sign_priority_gost);
3421
0
        } else {
3422
0
          if ((algo = gnutls_sign_get_id(
3423
0
                 &broken_list[i][6])) !=
3424
0
              GNUTLS_SIGN_UNKNOWN)
3425
0
            fn(&(*priority_cache)
3426
0
                  ->_sign_algo,
3427
0
               algo);
3428
0
          else
3429
0
            goto error;
3430
0
        }
3431
0
      } else if (PRIO_MATCH("MAC-") == 0) {
3432
0
        if (PRIO_MATCH("MAC-ALL") == 0) {
3433
0
          bulk_fn(&(*priority_cache)->_mac,
3434
0
            mac_priority_normal);
3435
0
        } else if (PRIO_MATCH("MAC-GOST-ALL") == 0) {
3436
0
          bulk_fn(&(*priority_cache)->_mac,
3437
0
            mac_priority_gost);
3438
0
        }
3439
0
      } else if (PRIO_MATCH("CIPHER-") == 0) {
3440
0
        if (PRIO_MATCH("CIPHER-ALL") == 0) {
3441
0
          bulk_fn(&(*priority_cache)->_cipher,
3442
0
            cipher_priority_normal);
3443
0
        } else if (PRIO_MATCH("CIPHER-GOST-ALL") == 0) {
3444
0
          bulk_fn(&(*priority_cache)->_cipher,
3445
0
            cipher_priority_gost);
3446
0
        }
3447
0
      } else if (PRIO_MATCH("KX-") == 0) {
3448
0
        if (PRIO_MATCH("KX-ALL") == 0) {
3449
0
          bulk_fn(&(*priority_cache)->_kx,
3450
0
            kx_priority_secure);
3451
0
        } else if (PRIO_MATCH("KX-GOST-ALL") == 0) {
3452
0
          bulk_fn(&(*priority_cache)->_kx,
3453
0
            kx_priority_gost);
3454
0
        }
3455
0
      } else if (PRIO_MATCH("GOST") == 0) {
3456
0
        bulk_given_fn(
3457
0
          &(*priority_cache)->_supported_ecc,
3458
0
          _supported_groups_gost);
3459
0
        bulk_fn(&(*priority_cache)->_sign_algo,
3460
0
          sign_priority_gost);
3461
0
        bulk_fn(&(*priority_cache)->_mac,
3462
0
          mac_priority_gost);
3463
0
        bulk_fn(&(*priority_cache)->_cipher,
3464
0
          cipher_priority_gost);
3465
0
        bulk_fn(&(*priority_cache)->_kx,
3466
0
          kx_priority_gost);
3467
0
      } else
3468
0
        goto error;
3469
0
    } else if (broken_list[i][0] == '%') {
3470
0
      const struct priority_options_st *o;
3471
      /* to add a new option modify
3472
       * priority_options.gperf */
3473
0
      o = in_word_set(&broken_list[i][1],
3474
0
          strlen(&broken_list[i][1]));
3475
0
      if (o == NULL) {
3476
0
        goto error;
3477
0
      }
3478
0
      o->func(*priority_cache);
3479
0
    } else
3480
0
      goto error;
3481
0
  }
3482
3483
  /* This needs to be done after parsing modifiers, as
3484
   * tls-session-hash has precedence over modifiers.
3485
   */
3486
0
  if (system_wide_config.force_ext_master_secret_set) {
3487
0
    (*priority_cache)->force_ext_master_secret =
3488
0
      system_wide_config.force_ext_master_secret;
3489
0
    (*priority_cache)->_no_ext_master_secret = false;
3490
0
  }
3491
3492
0
  ret = set_ciphersuite_list(*priority_cache);
3493
0
  if (ret < 0) {
3494
0
    if (err_pos)
3495
0
      *err_pos = priorities;
3496
0
    goto error_cleanup;
3497
0
  }
3498
3499
0
  gnutls_free(darg);
3500
3501
0
  return 0;
3502
3503
0
error:
3504
0
  if (err_pos != NULL && i < broken_list_size && resolved_match) {
3505
0
    *err_pos = priorities;
3506
0
    for (j = 0; j < i; j++) {
3507
0
      (*err_pos) += strlen(broken_list[j]) + 1;
3508
0
    }
3509
0
  }
3510
0
  ret = GNUTLS_E_INVALID_REQUEST;
3511
3512
0
error_cleanup:
3513
0
  gnutls_free(darg);
3514
0
  gnutls_priority_deinit(*priority_cache);
3515
0
  *priority_cache = NULL;
3516
3517
0
  return ret;
3518
0
}
3519
3520
/**
3521
 * gnutls_priority_deinit:
3522
 * @priority_cache: is a #gnutls_priority_t type.
3523
 *
3524
 * Deinitializes the priority cache.
3525
 **/
3526
void gnutls_priority_deinit(gnutls_priority_t priority_cache)
3527
0
{
3528
0
  if (priority_cache == NULL)
3529
0
    return;
3530
3531
  /* Note that here we care about the following two cases:
3532
   * 1. Multiple sessions or different threads holding a reference + a global reference
3533
   * 2. One session holding a reference with a possible global reference
3534
   *
3535
   * As such, it will never be that two threads reach the
3536
   * zero state at the same time, unless the global reference
3537
   * is cleared too, which is invalid state.
3538
   */
3539
0
  if (gnutls_atomic_val(&priority_cache->usage_cnt) == 0) {
3540
0
    gnutls_atomic_deinit(&priority_cache->usage_cnt);
3541
0
    gnutls_free(priority_cache);
3542
0
    return;
3543
0
  } else {
3544
0
    gnutls_atomic_decrement(&priority_cache->usage_cnt);
3545
0
  }
3546
0
}
3547
3548
/**
3549
 * gnutls_priority_set_direct:
3550
 * @session: is a #gnutls_session_t type.
3551
 * @priorities: is a string describing priorities
3552
 * @err_pos: In case of an error this will have the position in the string the error occurred
3553
 *
3554
 * Sets the priorities to use on the ciphers, key exchange methods,
3555
 * and macs.  This function avoids keeping a
3556
 * priority cache and is used to directly set string priorities to a
3557
 * TLS session.  For documentation check the gnutls_priority_init().
3558
 *
3559
 * To use a reasonable default, consider using gnutls_set_default_priority(),
3560
 * or gnutls_set_default_priority_append() instead of this function.
3561
 *
3562
 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
3563
 * %GNUTLS_E_SUCCESS on success, or an error code.
3564
 **/
3565
int gnutls_priority_set_direct(gnutls_session_t session, const char *priorities,
3566
             const char **err_pos)
3567
0
{
3568
0
  gnutls_priority_t prio;
3569
0
  int ret;
3570
3571
0
  ret = gnutls_priority_init(&prio, priorities, err_pos);
3572
0
  if (ret < 0) {
3573
0
    gnutls_assert();
3574
0
    return ret;
3575
0
  }
3576
3577
0
  ret = gnutls_priority_set(session, prio);
3578
0
  if (ret < 0) {
3579
0
    gnutls_assert();
3580
0
    return ret;
3581
0
  }
3582
3583
  /* ensure that the session holds the only reference for the struct */
3584
0
  gnutls_priority_deinit(prio);
3585
3586
0
  return 0;
3587
0
}
3588
3589
/* Breaks a list of "xxx", "yyy", to a character array, of
3590
 * MAX_COMMA_SEP_ELEMENTS size; Note that the given string is modified.
3591
  */
3592
static void break_list(char *list, char *broken_list[MAX_ELEMENTS], int *size)
3593
0
{
3594
0
  char *p = list;
3595
3596
0
  *size = 0;
3597
3598
0
  do {
3599
0
    broken_list[*size] = p;
3600
3601
0
    (*size)++;
3602
3603
0
    p = strchr(p, ':');
3604
0
    if (p) {
3605
0
      *p = 0;
3606
0
      p++; /* move to next entry and skip white
3607
         * space.
3608
         */
3609
0
      while (*p == ' ')
3610
0
        p++;
3611
0
    }
3612
0
  } while (p != NULL && *size < MAX_ELEMENTS);
3613
0
}
3614
3615
/**
3616
 * gnutls_set_default_priority:
3617
 * @session: is a #gnutls_session_t type.
3618
 *
3619
 * Sets the default priority on the ciphers, key exchange methods,
3620
 * and macs. This is the recommended method of
3621
 * setting the defaults, in order to promote consistency between applications
3622
 * using GnuTLS, and to allow GnuTLS using applications to update settings
3623
 * in par with the library. For client applications which require
3624
 * maximum compatibility consider calling gnutls_session_enable_compatibility_mode()
3625
 * after this function.
3626
 *
3627
 * For an application to specify additional options to priority string
3628
 * consider using gnutls_set_default_priority_append().
3629
 *
3630
 * To allow a user to override the defaults (e.g., when a user interface
3631
 * or configuration file is available), the functions
3632
 * gnutls_priority_set_direct() or gnutls_priority_set() can
3633
 * be used.
3634
 *
3635
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
3636
 *
3637
 * Since: 2.1.4
3638
 **/
3639
int gnutls_set_default_priority(gnutls_session_t session)
3640
0
{
3641
0
  return gnutls_priority_set_direct(session, NULL, NULL);
3642
0
}
3643
3644
/**
3645
 * gnutls_set_default_priority_append:
3646
 * @session: is a #gnutls_session_t type.
3647
 * @add_prio: is a string describing priorities to be appended to default
3648
 * @err_pos: In case of an error this will have the position in the string the error occurred
3649
 * @flags: must be zero
3650
 *
3651
 * Sets the default priority on the ciphers, key exchange methods,
3652
 * and macs with the additional options in @add_prio. This is the recommended method of
3653
 * setting the defaults when only few additional options are to be added. This promotes
3654
 * consistency between applications using GnuTLS, and allows GnuTLS using applications
3655
 * to update settings in par with the library.
3656
 *
3657
 * The @add_prio string should start as a normal priority string, e.g.,
3658
 * '-VERS-TLS-ALL:+VERS-TLS1.3:%%COMPAT' or '%%FORCE_ETM'. That is, it must not start
3659
 * with ':'.
3660
 *
3661
 * To allow a user to override the defaults (e.g., when a user interface
3662
 * or configuration file is available), the functions
3663
 * gnutls_priority_set_direct() or gnutls_priority_set() can
3664
 * be used.
3665
 *
3666
 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
3667
 *
3668
 * Since: 3.6.3
3669
 **/
3670
int gnutls_set_default_priority_append(gnutls_session_t session,
3671
               const char *add_prio,
3672
               const char **err_pos, unsigned flags)
3673
0
{
3674
0
  gnutls_priority_t prio;
3675
0
  int ret;
3676
3677
0
  ret = gnutls_priority_init2(&prio, add_prio, err_pos,
3678
0
            GNUTLS_PRIORITY_INIT_DEF_APPEND);
3679
0
  if (ret < 0) {
3680
0
    gnutls_assert();
3681
0
    return ret;
3682
0
  }
3683
3684
0
  ret = gnutls_priority_set(session, prio);
3685
0
  if (ret < 0) {
3686
0
    gnutls_assert();
3687
0
    return ret;
3688
0
  }
3689
3690
  /* ensure that the session holds the only reference for the struct */
3691
0
  gnutls_priority_deinit(prio);
3692
3693
0
  return 0;
3694
0
}
3695
3696
/**
3697
 * gnutls_priority_ecc_curve_list:
3698
 * @pcache: is a #gnutls_priority_t type.
3699
 * @list: will point to an integer list
3700
 *
3701
 * Get a list of available elliptic curves in the priority
3702
 * structure.
3703
 *
3704
 * Deprecated: This function has been replaced by
3705
 * gnutls_priority_group_list() since 3.6.0.
3706
 *
3707
 * Returns: the number of items, or an error code.
3708
 *
3709
 * Since: 3.0
3710
 **/
3711
int gnutls_priority_ecc_curve_list(gnutls_priority_t pcache,
3712
           const unsigned int **list)
3713
0
{
3714
0
  unsigned i;
3715
3716
0
  if (pcache->_supported_ecc.num_priorities == 0)
3717
0
    return 0;
3718
3719
0
  *list = pcache->_supported_ecc.priorities;
3720
3721
  /* to ensure we don't confuse the caller, we do not include
3722
   * any FFDHE groups. This may return an incomplete list. */
3723
0
  for (i = 0; i < pcache->_supported_ecc.num_priorities; i++)
3724
0
    if (pcache->_supported_ecc.priorities[i] > GNUTLS_ECC_CURVE_MAX)
3725
0
      return i;
3726
3727
0
  return pcache->_supported_ecc.num_priorities;
3728
0
}
3729
3730
/**
3731
 * gnutls_priority_group_list:
3732
 * @pcache: is a #gnutls_priority_t type.
3733
 * @list: will point to an integer list
3734
 *
3735
 * Get a list of available groups in the priority
3736
 * structure.
3737
 *
3738
 * Returns: the number of items, or an error code.
3739
 *
3740
 * Since: 3.6.0
3741
 **/
3742
int gnutls_priority_group_list(gnutls_priority_t pcache,
3743
             const unsigned int **list)
3744
0
{
3745
0
  if (pcache->_supported_ecc.num_priorities == 0)
3746
0
    return 0;
3747
3748
0
  *list = pcache->_supported_ecc.priorities;
3749
0
  return pcache->_supported_ecc.num_priorities;
3750
0
}
3751
3752
/**
3753
 * gnutls_priority_kx_list:
3754
 * @pcache: is a #gnutls_priority_t type.
3755
 * @list: will point to an integer list
3756
 *
3757
 * Get a list of available key exchange methods in the priority
3758
 * structure.
3759
 *
3760
 * Returns: the number of items, or an error code.
3761
 * Since: 3.2.3
3762
 **/
3763
int gnutls_priority_kx_list(gnutls_priority_t pcache, const unsigned int **list)
3764
0
{
3765
0
  if (pcache->_kx.num_priorities == 0)
3766
0
    return 0;
3767
3768
0
  *list = pcache->_kx.priorities;
3769
0
  return pcache->_kx.num_priorities;
3770
0
}
3771
3772
/**
3773
 * gnutls_priority_cipher_list:
3774
 * @pcache: is a #gnutls_priority_t type.
3775
 * @list: will point to an integer list
3776
 *
3777
 * Get a list of available ciphers in the priority
3778
 * structure.
3779
 *
3780
 * Returns: the number of items, or an error code.
3781
 * Since: 3.2.3
3782
 **/
3783
int gnutls_priority_cipher_list(gnutls_priority_t pcache,
3784
        const unsigned int **list)
3785
0
{
3786
0
  if (pcache->_cipher.num_priorities == 0)
3787
0
    return 0;
3788
3789
0
  *list = pcache->_cipher.priorities;
3790
0
  return pcache->_cipher.num_priorities;
3791
0
}
3792
3793
/**
3794
 * gnutls_priority_mac_list:
3795
 * @pcache: is a #gnutls_priority_t type.
3796
 * @list: will point to an integer list
3797
 *
3798
 * Get a list of available MAC algorithms in the priority
3799
 * structure.
3800
 *
3801
 * Returns: the number of items, or an error code.
3802
 * Since: 3.2.3
3803
 **/
3804
int gnutls_priority_mac_list(gnutls_priority_t pcache,
3805
           const unsigned int **list)
3806
0
{
3807
0
  if (pcache->_mac.num_priorities == 0)
3808
0
    return 0;
3809
3810
0
  *list = pcache->_mac.priorities;
3811
0
  return pcache->_mac.num_priorities;
3812
0
}
3813
3814
/**
3815
 * gnutls_priority_compression_list:
3816
 * @pcache: is a #gnutls_priority_t type.
3817
 * @list: will point to an integer list
3818
 *
3819
 * Get a list of available compression method in the priority
3820
 * structure.
3821
 *
3822
 * Returns: the number of methods, or an error code.
3823
 * Since: 3.0
3824
 **/
3825
int gnutls_priority_compression_list(gnutls_priority_t pcache,
3826
             const unsigned int **list)
3827
0
{
3828
0
  static const unsigned int priority[1] = { GNUTLS_COMP_NULL };
3829
3830
0
  *list = priority;
3831
0
  return 1;
3832
0
}
3833
3834
/**
3835
 * gnutls_priority_protocol_list:
3836
 * @pcache: is a #gnutls_priority_t type.
3837
 * @list: will point to an integer list
3838
 *
3839
 * Get a list of available TLS version numbers in the priority
3840
 * structure.
3841
 *
3842
 * Returns: the number of protocols, or an error code.
3843
 * Since: 3.0
3844
 **/
3845
int gnutls_priority_protocol_list(gnutls_priority_t pcache,
3846
          const unsigned int **list)
3847
0
{
3848
0
  if (pcache->protocol.num_priorities == 0)
3849
0
    return 0;
3850
3851
0
  *list = pcache->protocol.priorities;
3852
0
  return pcache->protocol.num_priorities;
3853
0
}
3854
3855
/**
3856
 * gnutls_priority_sign_list:
3857
 * @pcache: is a #gnutls_priority_t type.
3858
 * @list: will point to an integer list
3859
 *
3860
 * Get a list of available signature algorithms in the priority
3861
 * structure.
3862
 *
3863
 * Returns: the number of algorithms, or an error code.
3864
 * Since: 3.0
3865
 **/
3866
int gnutls_priority_sign_list(gnutls_priority_t pcache,
3867
            const unsigned int **list)
3868
0
{
3869
0
  if (pcache->_sign_algo.num_priorities == 0)
3870
0
    return 0;
3871
3872
0
  *list = pcache->_sign_algo.priorities;
3873
0
  return pcache->_sign_algo.num_priorities;
3874
0
}
3875
3876
/**
3877
 * gnutls_priority_certificate_type_list:
3878
 * @pcache: is a #gnutls_priority_t type.
3879
 * @list: will point to an integer list
3880
 *
3881
 * Get a list of available certificate types in the priority
3882
 * structure.
3883
 *
3884
 * As of version 3.6.4 this function is an alias for
3885
 * gnutls_priority_certificate_type_list2 with the target parameter
3886
 * set to:
3887
 * - GNUTLS_CTYPE_SERVER, if the %SERVER_PRECEDENCE option is set
3888
 * - GNUTLS_CTYPE_CLIENT, otherwise.
3889
 *
3890
 * Returns: the number of certificate types, or an error code.
3891
 * Since: 3.0
3892
 **/
3893
int gnutls_priority_certificate_type_list(gnutls_priority_t pcache,
3894
            const unsigned int **list)
3895
0
{
3896
0
  gnutls_ctype_target_t target = pcache->server_precedence ?
3897
0
                 GNUTLS_CTYPE_SERVER :
3898
0
                 GNUTLS_CTYPE_CLIENT;
3899
3900
0
  return gnutls_priority_certificate_type_list2(pcache, list, target);
3901
0
}
3902
3903
/**
3904
 * gnutls_priority_certificate_type_list2:
3905
 * @pcache: is a #gnutls_priority_t type.
3906
 * @list: will point to an integer list.
3907
 * @target: is a #gnutls_ctype_target_t type. Valid arguments are
3908
 *   GNUTLS_CTYPE_CLIENT and GNUTLS_CTYPE_SERVER
3909
 *
3910
 * Get a list of available certificate types for the given target
3911
 * in the priority structure.
3912
 *
3913
 * Returns: the number of certificate types, or an error code.
3914
 *
3915
 * Since: 3.6.4
3916
 **/
3917
int gnutls_priority_certificate_type_list2(gnutls_priority_t pcache,
3918
             const unsigned int **list,
3919
             gnutls_ctype_target_t target)
3920
0
{
3921
0
  switch (target) {
3922
0
  case GNUTLS_CTYPE_CLIENT:
3923
0
    if (pcache->client_ctype.num_priorities > 0) {
3924
0
      *list = pcache->client_ctype.priorities;
3925
0
      return pcache->client_ctype.num_priorities;
3926
0
    }
3927
0
    break;
3928
0
  case GNUTLS_CTYPE_SERVER:
3929
0
    if (pcache->server_ctype.num_priorities > 0) {
3930
0
      *list = pcache->server_ctype.priorities;
3931
0
      return pcache->server_ctype.num_priorities;
3932
0
    }
3933
0
    break;
3934
0
  default:
3935
    // Invalid target given
3936
0
    gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
3937
0
  }
3938
3939
  // Found a matching target but non of them had any ctypes set
3940
0
  return 0;
3941
0
}
3942
3943
/**
3944
 * gnutls_priority_string_list:
3945
 * @iter: an integer counter starting from zero
3946
 * @flags: one of %GNUTLS_PRIORITY_LIST_INIT_KEYWORDS, %GNUTLS_PRIORITY_LIST_SPECIAL
3947
 *
3948
 * Can be used to iterate all available priority strings.
3949
 * Due to internal implementation details, there are cases where this
3950
 * function can return the empty string. In that case that string should be ignored.
3951
 * When no strings are available it returns %NULL.
3952
 *
3953
 * Returns: a priority string
3954
 * Since: 3.4.0
3955
 **/
3956
const char *gnutls_priority_string_list(unsigned iter, unsigned int flags)
3957
0
{
3958
0
  if (flags & GNUTLS_PRIORITY_LIST_INIT_KEYWORDS) {
3959
0
    if (iter >= (sizeof(pgroups) / sizeof(pgroups[0])) - 1)
3960
0
      return NULL;
3961
0
    return pgroups[iter].name;
3962
0
  } else if (flags & GNUTLS_PRIORITY_LIST_SPECIAL) {
3963
0
    if (iter >= (sizeof(wordlist) / sizeof(wordlist[0])) - 1)
3964
0
      return NULL;
3965
0
    return wordlist[iter].name;
3966
0
  }
3967
0
  return NULL;
3968
0
}
3969
3970
bool _gnutls_config_is_ktls_enabled(void)
3971
0
{
3972
0
  return system_wide_config.ktls_enabled;
3973
0
}
3974
3975
bool _gnutls_config_is_rsa_pkcs1_encrypt_allowed(void)
3976
0
{
3977
0
  return system_wide_config.allow_rsa_pkcs1_encrypt;
3978
0
}
3979
3980
/*
3981
 * high-level interface for overriding configuration files
3982
 */
3983
3984
static inline bool /* not locking system_wide_config */
3985
system_wide_config_is_malleable(void)
3986
0
{
3987
0
  if (!system_wide_config.allowlisting) {
3988
0
    _gnutls_audit_log(NULL, "allowlisting is not enabled!\n");
3989
0
    return false;
3990
0
  }
3991
0
  if (system_wide_config.priority_string) {
3992
0
    _gnutls_audit_log(NULL, "priority strings have already been "
3993
0
          "initialized!\n");
3994
0
    return false;
3995
0
  }
3996
0
  return true;
3997
0
}
3998
3999
/**
4000
 * gnutls_digest_set_secure:
4001
 * @dig: is a digest algorithm
4002
 * @secure: whether to mark the digest algorithm secure
4003
 *
4004
 * Modify the previous system wide setting that marked @dig as secure
4005
 * or insecure. This only has effect when the algorithm is enabled
4006
 * through the allowlisting mode in the configuration file, or when
4007
 * the setting is modified with a prior call to this function.
4008
 *
4009
 * Since: 3.7.3
4010
 */
4011
int gnutls_digest_set_secure(gnutls_digest_algorithm_t dig, unsigned int secure)
4012
0
{
4013
0
#ifndef DISABLE_SYSTEM_CONFIG
4014
0
  int ret;
4015
0
  ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
4016
0
  if (ret < 0) {
4017
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4018
0
    return gnutls_assert_val(ret);
4019
0
  }
4020
0
  if (!system_wide_config_is_malleable()) {
4021
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4022
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4023
0
  }
4024
4025
0
  if (secure) {
4026
0
    ret = cfg_hashes_add(&system_wide_config, dig);
4027
0
  } else {
4028
0
    ret = cfg_hashes_remove(&system_wide_config, dig);
4029
0
  }
4030
4031
0
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4032
0
  return ret;
4033
#else
4034
  return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4035
#endif
4036
0
}
4037
4038
/**
4039
 * gnutls_sign_set_secure:
4040
 * @sign: the sign algorithm
4041
 * @secure: whether to mark the sign algorithm secure
4042
 *
4043
 * Modify the previous system wide setting that marked @sign as secure
4044
 * or insecure.  Calling this function is allowed
4045
 * only if allowlisting mode is set in the configuration file,
4046
 * and only if the system-wide TLS priority string
4047
 * has not been initialized yet.
4048
 * The intended usage is to provide applications with a way
4049
 * to expressly deviate from the distribution or site defaults
4050
 * inherited from the configuration file.
4051
 * The modification is composable with further modifications
4052
 * performed through the priority string mechanism.
4053
 *
4054
 * This function is not thread-safe and is intended to be called
4055
 * in the main thread at the beginning of the process execution.
4056
 *
4057
 * Even when @secure is true, @sign is not marked as secure for the
4058
 * use in certificates.  Use gnutls_sign_set_secure_for_certs() to
4059
 * mark it secure as well for certificates.
4060
 *
4061
 * Returns: 0 on success or negative error code otherwise.
4062
 *
4063
 * Since: 3.7.3
4064
 */
4065
int gnutls_sign_set_secure(gnutls_sign_algorithm_t sign, unsigned int secure)
4066
0
{
4067
0
#ifndef DISABLE_SYSTEM_CONFIG
4068
0
  int ret;
4069
0
  ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
4070
0
  if (ret < 0) {
4071
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4072
0
    return gnutls_assert_val(ret);
4073
0
  }
4074
0
  if (!system_wide_config_is_malleable()) {
4075
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4076
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4077
0
  }
4078
4079
0
  if (secure) {
4080
0
    ret = cfg_sigs_add(&system_wide_config, sign);
4081
0
  } else {
4082
0
    ret = cfg_sigs_remove(&system_wide_config, sign);
4083
0
    if (ret < 0) {
4084
0
      (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4085
0
      return ret;
4086
0
    }
4087
    /* irregularity, distrusting also means distrusting for certs */
4088
0
    ret = cfg_sigs_for_cert_remove(&system_wide_config, sign);
4089
0
  }
4090
4091
0
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4092
0
  return ret;
4093
#else
4094
  return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4095
#endif
4096
0
}
4097
4098
/**
4099
 * gnutls_sign_set_secure_for_certs:
4100
 * @sign: the sign algorithm
4101
 * @secure: whether to mark the sign algorithm secure for certificates
4102
 *
4103
 * Modify the previous system wide setting that marked @sign as secure
4104
 * or insecure for the use in certificates.  Calling this function is allowed
4105
 * only if allowlisting mode is set in the configuration file,
4106
 * and only if the system-wide TLS priority string
4107
 * has not been initialized yet.
4108
 * The intended usage is to provide applications with a way
4109
 * to expressly deviate from the distribution or site defaults
4110
 * inherited from the configuration file.
4111
 * The modification is composable with further modifications
4112
 * performed through the priority string mechanism.
4113
 *
4114
 * This function is not thread-safe and is intended to be called
4115
 * in the main thread at the beginning of the process execution.
4116
4117
 * When @secure is true, @sign is marked as secure for any use unlike
4118
 * gnutls_sign_set_secure().  Otherwise, it is marked as insecure only
4119
 * for the use in certificates.  Use gnutls_sign_set_secure() to mark
4120
 * it insecure for any uses.
4121
 *
4122
 * Returns: 0 on success or negative error code otherwise.
4123
 *
4124
 * Since: 3.7.3
4125
 */
4126
int gnutls_sign_set_secure_for_certs(gnutls_sign_algorithm_t sign,
4127
             unsigned int secure)
4128
0
{
4129
0
#ifndef DISABLE_SYSTEM_CONFIG
4130
0
  int ret;
4131
0
  ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
4132
0
  if (ret < 0) {
4133
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4134
0
    return gnutls_assert_val(ret);
4135
0
  }
4136
0
  if (!system_wide_config_is_malleable()) {
4137
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4138
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4139
0
  }
4140
4141
0
  if (secure) {
4142
    /* irregularity, trusting for certs means trusting in general */
4143
0
    ret = cfg_sigs_add(&system_wide_config, sign);
4144
0
    if (ret < 0) {
4145
0
      (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4146
0
      return ret;
4147
0
    }
4148
0
    ret = cfg_sigs_for_cert_add(&system_wide_config, sign);
4149
0
  } else {
4150
0
    ret = cfg_sigs_for_cert_remove(&system_wide_config, sign);
4151
0
  }
4152
4153
0
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4154
0
  return ret;
4155
#else
4156
  return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4157
#endif
4158
0
}
4159
4160
/**
4161
 * gnutls_protocol_set_enabled:
4162
 * @version: is a (gnutls) version number
4163
 * @enabled: whether to enable the protocol
4164
 *
4165
 * Control the previous system-wide setting that marked @version as
4166
 * enabled or disabled.  Calling this function is allowed
4167
 * only if allowlisting mode is set in the configuration file,
4168
 * and only if the system-wide TLS priority string
4169
 * has not been initialized yet.
4170
 * The intended usage is to provide applications with a way
4171
 * to expressly deviate from the distribution or site defaults
4172
 * inherited from the configuration file.
4173
 * The modification is composable with further modifications
4174
 * performed through the priority string mechanism.
4175
 *
4176
 * This function is not thread-safe and is intended to be called
4177
 * in the main thread at the beginning of the process execution.
4178
 *
4179
 * Returns: 0 on success or negative error code otherwise.
4180
 *
4181
 * Since: 3.7.3
4182
 */
4183
int /* allowlisting-only */
4184
/* not thread-safe */
4185
gnutls_protocol_set_enabled(gnutls_protocol_t version, unsigned int enabled)
4186
0
{
4187
0
#ifndef DISABLE_SYSTEM_CONFIG
4188
0
  int ret;
4189
0
  ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
4190
0
  if (ret < 0) {
4191
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4192
0
    return gnutls_assert_val(ret);
4193
0
  }
4194
0
  if (!system_wide_config_is_malleable()) {
4195
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4196
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4197
0
  }
4198
4199
0
  if (enabled) {
4200
0
    ret = cfg_versions_add(&system_wide_config, version);
4201
0
  } else {
4202
0
    ret = cfg_versions_remove(&system_wide_config, version);
4203
0
  }
4204
4205
0
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4206
0
  return ret;
4207
#else
4208
  return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4209
#endif
4210
0
}
4211
4212
/**
4213
 * gnutls_ecc_curve_set_enabled:
4214
 * @curve: is an ECC curve
4215
 * @enabled: whether to enable the curve
4216
 *
4217
 * Modify the previous system wide setting that marked @curve as
4218
 * enabled or disabled.  Calling this function is allowed
4219
 * only if allowlisting mode is set in the configuration file,
4220
 * and only if the system-wide TLS priority string
4221
 * has not been initialized yet.
4222
 * The intended usage is to provide applications with a way
4223
 * to expressly deviate from the distribution or site defaults
4224
 * inherited from the configuration file.
4225
 * The modification is composable with further modifications
4226
 * performed through the priority string mechanism.
4227
 *
4228
 * This function is not thread-safe and is intended to be called
4229
 * in the main thread at the beginning of the process execution.
4230
 *
4231
 * Returns: 0 on success or negative error code otherwise.
4232
 *
4233
 * Since: 3.7.3
4234
 */
4235
int gnutls_ecc_curve_set_enabled(gnutls_ecc_curve_t curve, unsigned int enabled)
4236
0
{
4237
0
#ifndef DISABLE_SYSTEM_CONFIG
4238
0
  int ret;
4239
0
  ret = gnutls_rwlock_wrlock(&system_wide_config_rwlock);
4240
0
  if (ret < 0) {
4241
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4242
0
    return gnutls_assert_val(ret);
4243
0
  }
4244
0
  if (!system_wide_config_is_malleable()) {
4245
0
    (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4246
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4247
0
  }
4248
4249
0
  if (enabled) {
4250
0
    ret = cfg_ecc_curves_add(&system_wide_config, curve);
4251
0
  } else {
4252
0
    ret = cfg_ecc_curves_remove(&system_wide_config, curve);
4253
0
  }
4254
4255
0
  (void)gnutls_rwlock_unlock(&system_wide_config_rwlock);
4256
0
  return ret;
4257
#else
4258
  return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
4259
#endif
4260
0
}