Coverage Report

Created: 2026-11-12 07:51

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