Coverage Report

Created: 2023-03-26 07:33

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