LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - priority.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 823 966 85.2 %
Date: 2020-10-30 04:50:48 Functions: 59 72 81.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2004-2015 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2015-2019 Red Hat, Inc.
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : /* Here lies the code of the gnutls_*_set_priority() functions.
      25             :  */
      26             : 
      27             : #include "gnutls_int.h"
      28             : #include "algorithms.h"
      29             : #include "errors.h"
      30             : #include <num.h>
      31             : #include <gnutls/x509.h>
      32             : #include <c-ctype.h>
      33             : #include <hello_ext.h>
      34             : #include <c-strcase.h>
      35             : #include "fips.h"
      36             : #include "errno.h"
      37             : #include "ext/srp.h"
      38             : #include <gnutls/gnutls.h>
      39             : #include "profiles.h"
      40             : #include "c-strcase.h"
      41             : #include "inih/ini.h"
      42             : #include "profiles.h"
      43             : #include "name_val_array.h"
      44             : 
      45             : #define MAX_ELEMENTS 64
      46             : 
      47             : #define ENABLE_PROFILE(c, profile) do { \
      48             :         c->additional_verify_flags &= 0x00ffffff; \
      49             :         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(profile); \
      50             :         c->level = _gnutls_profile_to_sec_level(profile); \
      51             :         } while(0)
      52             : 
      53             : /* This function is used by the test suite */
      54             : char *_gnutls_resolve_priorities(const char* priorities);
      55             : const char *_gnutls_default_priority_string = DEFAULT_PRIORITY_STRING;
      56             : 
      57             : static void prio_remove(priority_st * priority_list, unsigned int algo);
      58             : static void prio_add(priority_st * priority_list, unsigned int algo);
      59             : static void
      60             : break_list(char *etag,
      61             :                  char *broken_etag[MAX_ELEMENTS], int *size);
      62             : 
      63             : typedef void (bulk_rmadd_func) (priority_st * priority_list, const int *);
      64             : 
      65      199372 : inline static void _set_priority(priority_st * st, const int *list)
      66             : {
      67      119624 :         int num = 0, i;
      68             : 
      69     1774280 :         while (list[num] != 0)
      70     1574910 :                 num++;
      71      199372 :         if (num > MAX_ALGOS)
      72           0 :                 num = MAX_ALGOS;
      73      199372 :         st->num_priorities = num;
      74             : 
      75     1774280 :         for (i = 0; i < num; i++) {
      76     1574910 :                 st->priorities[i] = list[i];
      77             :         }
      78             : 
      79      179435 :         return;
      80             : }
      81             : 
      82       13602 : inline static void _add_priority(priority_st * st, const int *list)
      83             : {
      84       13602 :         int num, i, j, init;
      85             : 
      86       13602 :         init = i = st->num_priorities;
      87             : 
      88      140649 :         for (num = 0; list[num] != 0; ++num) {
      89      127047 :                 if (i + 1 > MAX_ALGOS) {
      90             :                         return;
      91             :                 }
      92             : 
      93      158761 :                 for (j = 0; j < init; j++) {
      94       32392 :                         if (st->priorities[j] == (unsigned) list[num]) {
      95             :                                 break;
      96             :                         }
      97             :                 }
      98             : 
      99      127047 :                 if (j == init) {
     100      126369 :                         st->priorities[i++] = list[num];
     101      126369 :                         st->num_priorities++;
     102             :                 }
     103             :         }
     104             : 
     105             :         return;
     106             : }
     107             : 
     108       21402 : static void _clear_priorities(priority_st * st, const int *list)
     109             : {
     110       21402 :         memset(st, 0, sizeof(*st));
     111       21402 : }
     112             : 
     113         911 : static void _clear_given_priorities(priority_st * st, const int *list)
     114             : {
     115         911 :         unsigned i;
     116             : 
     117        5202 :         for (i=0;list[i]!=0;i++) {
     118        4291 :                 prio_remove(st, list[i]);
     119             :         }
     120         911 : }
     121             : 
     122             : static const int _supported_groups_dh[] = {
     123             :         GNUTLS_GROUP_FFDHE2048,
     124             :         GNUTLS_GROUP_FFDHE3072,
     125             :         GNUTLS_GROUP_FFDHE4096,
     126             :         GNUTLS_GROUP_FFDHE6144,
     127             :         GNUTLS_GROUP_FFDHE8192,
     128             :         0
     129             : };
     130             : 
     131             : static const int _supported_groups_ecdh[] = {
     132             :         GNUTLS_GROUP_SECP256R1,
     133             :         GNUTLS_GROUP_SECP384R1,
     134             :         GNUTLS_GROUP_SECP521R1,
     135             :         GNUTLS_GROUP_X25519, /* RFC 8422 */
     136             :         GNUTLS_GROUP_X448, /* RFC 8422 */
     137             :         0
     138             : };
     139             : 
     140             : static const int _supported_groups_gost[] = {
     141             : #ifdef ENABLE_GOST
     142             :         GNUTLS_GROUP_GC256A,
     143             :         GNUTLS_GROUP_GC256B,
     144             :         GNUTLS_GROUP_GC256C,
     145             :         GNUTLS_GROUP_GC256D,
     146             :         GNUTLS_GROUP_GC512A,
     147             :         GNUTLS_GROUP_GC512B,
     148             :         GNUTLS_GROUP_GC512C,
     149             : #endif
     150             :         0
     151             : };
     152             : 
     153             : static const int _supported_groups_normal[] = {
     154             :         GNUTLS_GROUP_SECP256R1,
     155             :         GNUTLS_GROUP_SECP384R1,
     156             :         GNUTLS_GROUP_SECP521R1,
     157             :         GNUTLS_GROUP_X25519, /* RFC 8422 */
     158             :         GNUTLS_GROUP_X448, /* RFC 8422 */
     159             : 
     160             :         /* These should stay last as our default behavior
     161             :          * is to send key shares for two top types (GNUTLS_KEY_SHARE_TOP2)
     162             :          * and we wouldn't want to have these sent by all clients
     163             :          * by default as they are quite expensive CPU-wise. */
     164             :         GNUTLS_GROUP_FFDHE2048,
     165             :         GNUTLS_GROUP_FFDHE3072,
     166             :         GNUTLS_GROUP_FFDHE4096,
     167             :         GNUTLS_GROUP_FFDHE6144,
     168             :         GNUTLS_GROUP_FFDHE8192,
     169             :         0
     170             : };
     171             : static const int* supported_groups_normal = _supported_groups_normal;
     172             : 
     173             : static const int _supported_groups_secure128[] = {
     174             :         GNUTLS_GROUP_SECP256R1,
     175             :         GNUTLS_GROUP_SECP384R1,
     176             :         GNUTLS_GROUP_SECP521R1,
     177             :         GNUTLS_GROUP_X25519, /* RFC 8422 */
     178             :         GNUTLS_GROUP_X448, /* RFC 8422 */
     179             :         GNUTLS_GROUP_FFDHE2048,
     180             :         GNUTLS_GROUP_FFDHE3072,
     181             :         GNUTLS_GROUP_FFDHE4096,
     182             :         GNUTLS_GROUP_FFDHE6144,
     183             :         GNUTLS_GROUP_FFDHE8192,
     184             :         0
     185             : };
     186             : static const int* supported_groups_secure128 = _supported_groups_secure128;
     187             : 
     188             : static const int _supported_groups_suiteb128[] = {
     189             :         GNUTLS_GROUP_SECP256R1,
     190             :         GNUTLS_GROUP_SECP384R1,
     191             :         0
     192             : };
     193             : static const int* supported_groups_suiteb128 = _supported_groups_suiteb128;
     194             : 
     195             : static const int _supported_groups_suiteb192[] = {
     196             :         GNUTLS_GROUP_SECP384R1,
     197             :         0
     198             : };
     199             : static const int* supported_groups_suiteb192 = _supported_groups_suiteb192;
     200             : 
     201             : static const int _supported_groups_secure192[] = {
     202             :         GNUTLS_GROUP_SECP384R1,
     203             :         GNUTLS_GROUP_SECP521R1,
     204             :         GNUTLS_GROUP_FFDHE8192,
     205             :         0
     206             : };
     207             : static const int* supported_groups_secure192 = _supported_groups_secure192;
     208             : 
     209             : static const int protocol_priority[] = {
     210             :         GNUTLS_TLS1_3,
     211             :         GNUTLS_TLS1_2,
     212             :         GNUTLS_TLS1_1,
     213             :         GNUTLS_TLS1_0,
     214             :         GNUTLS_DTLS1_2,
     215             :         GNUTLS_DTLS1_0,
     216             :         0
     217             : };
     218             : 
     219             : /* contains all the supported TLS protocols, intended to be used for eliminating them
     220             :  */
     221             : static const int stream_protocol_priority[] = {
     222             :         GNUTLS_TLS1_3,
     223             :         GNUTLS_TLS1_2,
     224             :         GNUTLS_TLS1_1,
     225             :         GNUTLS_TLS1_0,
     226             :         0
     227             : };
     228             : 
     229             : /* contains all the supported DTLS protocols, intended to be used for eliminating them
     230             :  */
     231             : static const int dgram_protocol_priority[] = {
     232             :         GNUTLS_DTLS1_2,
     233             :         GNUTLS_DTLS1_0,
     234             :         GNUTLS_DTLS0_9,
     235             :         0
     236             : };
     237             : 
     238             : static const int dtls_protocol_priority[] = {
     239             :         GNUTLS_DTLS1_2,
     240             :         GNUTLS_DTLS1_0,
     241             :         0
     242             : };
     243             : 
     244             : static const int _protocol_priority_suiteb[] = {
     245             :         GNUTLS_TLS1_2,
     246             :         0
     247             : };
     248             : static const int* protocol_priority_suiteb = _protocol_priority_suiteb;
     249             : 
     250             : static const int _kx_priority_performance[] = {
     251             :         GNUTLS_KX_RSA,
     252             : #ifdef ENABLE_ECDHE
     253             :         GNUTLS_KX_ECDHE_ECDSA,
     254             :         GNUTLS_KX_ECDHE_RSA,
     255             : #endif
     256             : #ifdef ENABLE_DHE
     257             :         GNUTLS_KX_DHE_RSA,
     258             : #endif
     259             :         0
     260             : };
     261             : static const int* kx_priority_performance = _kx_priority_performance;
     262             : 
     263             : static const int _kx_priority_pfs[] = {
     264             : #ifdef ENABLE_ECDHE
     265             :         GNUTLS_KX_ECDHE_ECDSA,
     266             :         GNUTLS_KX_ECDHE_RSA,
     267             : #endif
     268             : #ifdef ENABLE_DHE
     269             :         GNUTLS_KX_DHE_RSA,
     270             : #endif
     271             :         0
     272             : };
     273             : static const int* kx_priority_pfs = _kx_priority_pfs;
     274             : 
     275             : static const int _kx_priority_suiteb[] = {
     276             :         GNUTLS_KX_ECDHE_ECDSA,
     277             :         0
     278             : };
     279             : static const int* kx_priority_suiteb = _kx_priority_suiteb;
     280             : 
     281             : static const int _kx_priority_secure[] = {
     282             :         /* The ciphersuites that offer forward secrecy take
     283             :          * precedence
     284             :          */
     285             : #ifdef ENABLE_ECDHE
     286             :         GNUTLS_KX_ECDHE_ECDSA,
     287             :         GNUTLS_KX_ECDHE_RSA,
     288             : #endif
     289             :         GNUTLS_KX_RSA,
     290             :         /* KX-RSA is now ahead of DHE-RSA and DHE-DSS due to the compatibility
     291             :          * issues the DHE ciphersuites have. That is, one cannot enforce a specific
     292             :          * security level without dropping the connection.
     293             :          */
     294             : #ifdef ENABLE_DHE
     295             :         GNUTLS_KX_DHE_RSA,
     296             : #endif
     297             :         /* GNUTLS_KX_ANON_DH: Man-in-the-middle prone, don't add!
     298             :          */
     299             :         0
     300             : };
     301             : static const int* kx_priority_secure = _kx_priority_secure;
     302             : 
     303             : static const int _kx_priority_gost[] = {
     304             :         GNUTLS_KX_VKO_GOST_12,
     305             :         0,
     306             : };
     307             : static const int* kx_priority_gost = _kx_priority_gost;
     308             : 
     309             : static const int _cipher_priority_performance_default[] = {
     310             :         GNUTLS_CIPHER_AES_128_GCM,
     311             :         GNUTLS_CIPHER_AES_256_GCM,
     312             :         GNUTLS_CIPHER_CHACHA20_POLY1305,
     313             :         GNUTLS_CIPHER_AES_128_CCM,
     314             :         GNUTLS_CIPHER_AES_256_CCM,
     315             :         GNUTLS_CIPHER_AES_128_CBC,
     316             :         GNUTLS_CIPHER_AES_256_CBC,
     317             :         0
     318             : };
     319             : 
     320             : static const int _cipher_priority_performance_no_aesni[] = {
     321             :         GNUTLS_CIPHER_CHACHA20_POLY1305,
     322             :         GNUTLS_CIPHER_AES_128_GCM,
     323             :         GNUTLS_CIPHER_AES_256_GCM,
     324             :         GNUTLS_CIPHER_AES_128_CCM,
     325             :         GNUTLS_CIPHER_AES_256_CCM,
     326             :         GNUTLS_CIPHER_AES_128_CBC,
     327             :         GNUTLS_CIPHER_AES_256_CBC,
     328             :         0
     329             : };
     330             : 
     331             : /* If GCM and AES acceleration is available then prefer
     332             :  * them over anything else. Overall we prioritise AEAD
     333             :  * over legacy ciphers, and 256-bit over 128 (for future
     334             :  * proof).
     335             :  */
     336             : static const int _cipher_priority_normal_default[] = {
     337             :         GNUTLS_CIPHER_AES_256_GCM,
     338             :         GNUTLS_CIPHER_CHACHA20_POLY1305,
     339             :         GNUTLS_CIPHER_AES_256_CCM,
     340             : 
     341             :         GNUTLS_CIPHER_AES_256_CBC,
     342             : 
     343             :         GNUTLS_CIPHER_AES_128_GCM,
     344             :         GNUTLS_CIPHER_AES_128_CCM,
     345             : 
     346             :         GNUTLS_CIPHER_AES_128_CBC,
     347             :         0
     348             : };
     349             : 
     350             : static const int cipher_priority_performance_fips[] = {
     351             :         GNUTLS_CIPHER_AES_128_GCM,
     352             :         GNUTLS_CIPHER_AES_128_CCM,
     353             :         GNUTLS_CIPHER_AES_256_GCM,
     354             :         GNUTLS_CIPHER_AES_256_CCM,
     355             : 
     356             :         GNUTLS_CIPHER_AES_128_CBC,
     357             :         GNUTLS_CIPHER_AES_256_CBC,
     358             :         0
     359             : };
     360             : 
     361             : static const int cipher_priority_normal_fips[] = {
     362             :         GNUTLS_CIPHER_AES_256_GCM,
     363             :         GNUTLS_CIPHER_AES_256_CCM,
     364             :         GNUTLS_CIPHER_AES_256_CBC,
     365             : 
     366             :         GNUTLS_CIPHER_AES_128_GCM,
     367             :         GNUTLS_CIPHER_AES_128_CBC,
     368             :         GNUTLS_CIPHER_AES_128_CCM,
     369             :         0
     370             : };
     371             : 
     372             : 
     373             : static const int _cipher_priority_suiteb128[] = {
     374             :         GNUTLS_CIPHER_AES_256_GCM,
     375             :         GNUTLS_CIPHER_AES_128_GCM,
     376             :         0
     377             : };
     378             : static const int* cipher_priority_suiteb128 = _cipher_priority_suiteb128;
     379             : 
     380             : static const int _cipher_priority_suiteb192[] = {
     381             :         GNUTLS_CIPHER_AES_256_GCM,
     382             :         0
     383             : };
     384             : static const int* cipher_priority_suiteb192 = _cipher_priority_suiteb192;
     385             : 
     386             : 
     387             : static const int _cipher_priority_secure128[] = {
     388             :         GNUTLS_CIPHER_AES_256_GCM,
     389             :         GNUTLS_CIPHER_CHACHA20_POLY1305,
     390             :         GNUTLS_CIPHER_AES_256_CBC,
     391             :         GNUTLS_CIPHER_AES_256_CCM,
     392             : 
     393             :         GNUTLS_CIPHER_AES_128_GCM,
     394             :         GNUTLS_CIPHER_AES_128_CBC,
     395             :         GNUTLS_CIPHER_AES_128_CCM,
     396             :         0
     397             : };
     398             : static const int *cipher_priority_secure128 = _cipher_priority_secure128;
     399             : 
     400             : 
     401             : static const int _cipher_priority_secure192[] = {
     402             :         GNUTLS_CIPHER_AES_256_GCM,
     403             :         GNUTLS_CIPHER_CHACHA20_POLY1305,
     404             :         GNUTLS_CIPHER_AES_256_CBC,
     405             :         GNUTLS_CIPHER_AES_256_CCM,
     406             :         0
     407             : };
     408             : static const int* cipher_priority_secure192 = _cipher_priority_secure192;
     409             : 
     410             : static const int _sign_priority_default[] = {
     411             :         GNUTLS_SIGN_RSA_SHA256,
     412             :         GNUTLS_SIGN_RSA_PSS_SHA256,
     413             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
     414             :         GNUTLS_SIGN_ECDSA_SHA256,
     415             :         GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
     416             : 
     417             :         GNUTLS_SIGN_EDDSA_ED25519,
     418             : 
     419             :         GNUTLS_SIGN_RSA_SHA384,
     420             :         GNUTLS_SIGN_RSA_PSS_SHA384,
     421             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
     422             :         GNUTLS_SIGN_ECDSA_SHA384,
     423             :         GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
     424             : 
     425             :         GNUTLS_SIGN_EDDSA_ED448,
     426             : 
     427             :         GNUTLS_SIGN_RSA_SHA512,
     428             :         GNUTLS_SIGN_RSA_PSS_SHA512,
     429             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
     430             : 
     431             :         GNUTLS_SIGN_ECDSA_SHA512,
     432             :         GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
     433             : 
     434             :         GNUTLS_SIGN_RSA_SHA1,
     435             :         GNUTLS_SIGN_ECDSA_SHA1,
     436             : 
     437             :         0
     438             : };
     439             : static const int* sign_priority_default = _sign_priority_default;
     440             : 
     441             : static const int _sign_priority_suiteb128[] = {
     442             :         GNUTLS_SIGN_ECDSA_SHA256,
     443             :         GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
     444             :         GNUTLS_SIGN_ECDSA_SHA384,
     445             :         GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
     446             :         0
     447             : };
     448             : static const int* sign_priority_suiteb128 = _sign_priority_suiteb128;
     449             : 
     450             : static const int _sign_priority_suiteb192[] = {
     451             :         GNUTLS_SIGN_ECDSA_SHA384,
     452             :         GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
     453             :         0
     454             : };
     455             : static const int* sign_priority_suiteb192 = _sign_priority_suiteb192;
     456             : 
     457             : static const int _sign_priority_secure128[] = {
     458             :         GNUTLS_SIGN_RSA_SHA256,
     459             :         GNUTLS_SIGN_RSA_PSS_SHA256,
     460             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
     461             :         GNUTLS_SIGN_ECDSA_SHA256,
     462             :         GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
     463             : 
     464             :         GNUTLS_SIGN_EDDSA_ED25519,
     465             : 
     466             :         GNUTLS_SIGN_RSA_SHA384,
     467             :         GNUTLS_SIGN_RSA_PSS_SHA384,
     468             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
     469             :         GNUTLS_SIGN_ECDSA_SHA384,
     470             :         GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
     471             : 
     472             :         GNUTLS_SIGN_EDDSA_ED448,
     473             : 
     474             :         GNUTLS_SIGN_RSA_SHA512,
     475             :         GNUTLS_SIGN_RSA_PSS_SHA512,
     476             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
     477             :         GNUTLS_SIGN_ECDSA_SHA512,
     478             :         GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
     479             : 
     480             :         0
     481             : };
     482             : static const int* sign_priority_secure128 = _sign_priority_secure128;
     483             : 
     484             : static const int _sign_priority_secure192[] = {
     485             :         GNUTLS_SIGN_RSA_SHA384,
     486             :         GNUTLS_SIGN_RSA_PSS_SHA384,
     487             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
     488             :         GNUTLS_SIGN_ECDSA_SHA384,
     489             :         GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
     490             :         GNUTLS_SIGN_EDDSA_ED448,
     491             :         GNUTLS_SIGN_RSA_SHA512,
     492             :         GNUTLS_SIGN_RSA_PSS_SHA512,
     493             :         GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
     494             :         GNUTLS_SIGN_ECDSA_SHA512,
     495             :         GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
     496             : 
     497             :         0
     498             : };
     499             : static const int* sign_priority_secure192 = _sign_priority_secure192;
     500             : 
     501             : static const int _sign_priority_gost[] = {
     502             :         GNUTLS_SIGN_GOST_256,
     503             :         GNUTLS_SIGN_GOST_512,
     504             : 
     505             :         0
     506             : };
     507             : static const int* sign_priority_gost = _sign_priority_gost;
     508             : 
     509             : static const int mac_priority_normal_default[] = {
     510             :         GNUTLS_MAC_SHA1,
     511             :         GNUTLS_MAC_AEAD,
     512             :         0
     513             : };
     514             : 
     515             : static const int mac_priority_normal_fips[] = {
     516             :         GNUTLS_MAC_SHA1,
     517             :         GNUTLS_MAC_AEAD,
     518             :         0
     519             : };
     520             : 
     521             : static const int *cipher_priority_performance = _cipher_priority_performance_default;
     522             : static const int *cipher_priority_normal = _cipher_priority_normal_default;
     523             : static const int *mac_priority_normal = mac_priority_normal_default;
     524             : 
     525             : static const int _cipher_priority_gost[] = {
     526             :         GNUTLS_CIPHER_GOST28147_TC26Z_CNT,
     527             :         0
     528             : };
     529             : static const int *cipher_priority_gost = _cipher_priority_gost;
     530             : 
     531             : static const int _mac_priority_gost[] = {
     532             :         GNUTLS_MAC_GOST28147_TC26Z_IMIT,
     533             :         0
     534             : };
     535             : static const int *mac_priority_gost = _mac_priority_gost;
     536             : 
     537             : /* if called with replace the default priorities with the FIPS140 ones */
     538           0 : void _gnutls_priority_update_fips(void)
     539             : {
     540           0 :         cipher_priority_performance = cipher_priority_performance_fips;
     541           0 :         cipher_priority_normal = cipher_priority_normal_fips;
     542           0 :         mac_priority_normal = mac_priority_normal_fips;
     543           0 : }
     544             : 
     545          11 : void _gnutls_priority_update_non_aesni(void)
     546             : {
     547             :         /* if we have no AES acceleration in performance mode
     548             :          * prefer fast stream ciphers */
     549          11 :         if (_gnutls_fips_mode_enabled() == 0) {
     550          11 :                 cipher_priority_performance = _cipher_priority_performance_no_aesni;
     551             :         }
     552          11 : }
     553             : 
     554             : static const int _mac_priority_suiteb[] = {
     555             :         GNUTLS_MAC_AEAD,
     556             :         0
     557             : };
     558             : static const int* mac_priority_suiteb = _mac_priority_suiteb;
     559             : 
     560             : static const int _mac_priority_secure128[] = {
     561             :         GNUTLS_MAC_SHA1,
     562             :         GNUTLS_MAC_AEAD,
     563             :         0
     564             : };
     565             : static const int* mac_priority_secure128 = _mac_priority_secure128;
     566             : 
     567             : static const int _mac_priority_secure192[] = {
     568             :         GNUTLS_MAC_AEAD,
     569             :         0
     570             : };
     571             : static const int* mac_priority_secure192 = _mac_priority_secure192;
     572             : 
     573             : static const int cert_type_priority_default[] = {
     574             :         GNUTLS_CRT_X509,
     575             :         0
     576             : };
     577             : 
     578             : static const int cert_type_priority_all[] = {
     579             :         GNUTLS_CRT_X509,
     580             :         GNUTLS_CRT_RAWPK,
     581             :         0
     582             : };
     583             : 
     584             : typedef void (rmadd_func) (priority_st * priority_list, unsigned int alg);
     585             : 
     586        4455 : static void prio_remove(priority_st * priority_list, unsigned int algo)
     587             : {
     588        4455 :         unsigned int i;
     589             : 
     590       16074 :         for (i = 0; i < priority_list->num_priorities; i++) {
     591       16057 :                 if (priority_list->priorities[i] == algo) {
     592        4438 :                         priority_list->num_priorities--;
     593        4438 :                         if ((priority_list->num_priorities - i) > 0)
     594        3976 :                                 memmove(&priority_list->priorities[i],
     595        3976 :                                         &priority_list->priorities[i + 1],
     596        3976 :                                         (priority_list->num_priorities -
     597             :                                          i) *
     598             :                                         sizeof(priority_list->
     599             :                                                priorities[0]));
     600        4438 :                         priority_list->priorities[priority_list->
     601        4438 :                                                 num_priorities] = 0;
     602        4438 :                         break;
     603             :                 }
     604             :         }
     605             : 
     606        4455 :         return;
     607             : }
     608             : 
     609      143034 : static void prio_add(priority_st * priority_list, unsigned int algo)
     610             : {
     611      143034 :         unsigned int i, l = priority_list->num_priorities;
     612             : 
     613      143034 :         if (l >= MAX_ALGOS)
     614             :                 return;         /* can't add it anyway */
     615             : 
     616      808356 :         for (i = 0; i < l; ++i) {
     617      682961 :                 if (algo == priority_list->priorities[i])
     618             :                         return; /* if it exists */
     619             :         }
     620             : 
     621      125395 :         priority_list->priorities[l] = algo;
     622      125395 :         priority_list->num_priorities++;
     623             : 
     624      125395 :         return;
     625             : }
     626             : 
     627             : 
     628             : /**
     629             :  * gnutls_priority_set:
     630             :  * @session: is a #gnutls_session_t type.
     631             :  * @priority: is a #gnutls_priority_t type.
     632             :  *
     633             :  * Sets the priorities to use on the ciphers, key exchange methods,
     634             :  * and macs. Note that this function is expected to be called once
     635             :  * per session; when called multiple times (e.g., before a re-handshake,
     636             :  * the caller should make sure that any new settings are not incompatible
     637             :  * with the original session).
     638             :  *
     639             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code on error.
     640             :  **/
     641             : int
     642       23311 : gnutls_priority_set(gnutls_session_t session, gnutls_priority_t priority)
     643             : {
     644       23311 :         int ret;
     645             : 
     646       23311 :         if (priority == NULL || priority->protocol.num_priorities == 0 ||
     647       23311 :             priority->cs.size == 0)
     648           0 :                 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
     649             : 
     650             :         /* set the current version to the first in the chain, if this is
     651             :          * the call before the initial handshake. During a re-handshake
     652             :          * we do not set the version to avoid overriding the currently
     653             :          * negotiated version. */
     654       23311 :         if (!session->internals.handshake_in_progress &&
     655       23101 :             !session->internals.initial_negotiation_completed) {
     656       23077 :                 ret = _gnutls_set_current_version(session,
     657             :                                                   priority->protocol.priorities[0]);
     658           0 :                 if (ret < 0)
     659           0 :                         return gnutls_assert_val(ret);
     660             :         }
     661             : 
     662             :         /* At this point the provided priorities passed the sanity tests */
     663             : 
     664       23311 :         if (session->internals.priorities)
     665         236 :                 gnutls_priority_deinit(session->internals.priorities);
     666             : 
     667       23311 :         gnutls_atomic_increment(&priority->usage_cnt);
     668       23311 :         session->internals.priorities = priority;
     669             : 
     670       23311 :         if (priority->no_tickets != 0) {
     671             :                 /* when PFS is explicitly requested, disable session tickets */
     672         129 :                 session->internals.flags |= GNUTLS_NO_TICKETS;
     673             :         }
     674             : 
     675       23311 :         ADD_PROFILE_VFLAGS(session, priority->additional_verify_flags);
     676             : 
     677             :         /* mirror variables */
     678             : #undef COPY_TO_INTERNALS
     679             : #define COPY_TO_INTERNALS(xx) session->internals.xx = priority->_##xx
     680       23311 :         COPY_TO_INTERNALS(allow_large_records);
     681       23311 :         COPY_TO_INTERNALS(allow_small_records);
     682       23311 :         COPY_TO_INTERNALS(no_etm);
     683       23311 :         COPY_TO_INTERNALS(no_ext_master_secret);
     684       23311 :         COPY_TO_INTERNALS(allow_key_usage_violation);
     685       23311 :         COPY_TO_INTERNALS(allow_wrong_pms);
     686       23311 :         COPY_TO_INTERNALS(dumbfw);
     687       23311 :         COPY_TO_INTERNALS(dh_prime_bits);
     688             : 
     689       23311 :         return 0;
     690             : }
     691             : 
     692             : 
     693             : #define LEVEL_NONE "NONE"
     694             : #define LEVEL_NORMAL "NORMAL"
     695             : #define LEVEL_PFS "PFS"
     696             : #define LEVEL_PERFORMANCE "PERFORMANCE"
     697             : #define LEVEL_SECURE128 "SECURE128"
     698             : #define LEVEL_SECURE192 "SECURE192"
     699             : #define LEVEL_SECURE256 "SECURE256"
     700             : #define LEVEL_SUITEB128 "SUITEB128"
     701             : #define LEVEL_SUITEB192 "SUITEB192"
     702             : #define LEVEL_LEGACY "LEGACY"
     703             : 
     704             : struct priority_groups_st {
     705             :         const char *name;
     706             :         const char *alias;
     707             :         const int **proto_list;
     708             :         const int **cipher_list;
     709             :         const int **mac_list;
     710             :         const int **kx_list;
     711             :         const int **sign_list;
     712             :         const int **group_list;
     713             :         unsigned profile;
     714             :         int sec_param;
     715             :         bool no_tickets;
     716             : };
     717             : 
     718             : static const struct priority_groups_st pgroups[] =
     719             : {
     720             :         {.name = LEVEL_NORMAL,
     721             :          .cipher_list = &cipher_priority_normal,
     722             :          .mac_list = &mac_priority_normal,
     723             :          .kx_list = &kx_priority_secure,
     724             :          .sign_list = &sign_priority_default,
     725             :          .group_list = &supported_groups_normal,
     726             :          .profile = GNUTLS_PROFILE_LOW,
     727             :          .sec_param = GNUTLS_SEC_PARAM_WEAK
     728             :         },
     729             :         {.name = LEVEL_PFS,
     730             :          .cipher_list = &cipher_priority_normal,
     731             :          .mac_list = &mac_priority_secure128,
     732             :          .kx_list = &kx_priority_pfs,
     733             :          .sign_list = &sign_priority_default,
     734             :          .group_list = &supported_groups_normal,
     735             :          .profile = GNUTLS_PROFILE_LOW,
     736             :          .sec_param = GNUTLS_SEC_PARAM_WEAK,
     737             :          .no_tickets = 1
     738             :         },
     739             :         {.name = LEVEL_SECURE128,
     740             :          .alias = "SECURE",
     741             :          .cipher_list = &cipher_priority_secure128,
     742             :          .mac_list = &mac_priority_secure128,
     743             :          .kx_list = &kx_priority_secure,
     744             :          .sign_list = &sign_priority_secure128,
     745             :          .group_list = &supported_groups_secure128,
     746             :                 /* The profile should have been HIGH but if we don't allow
     747             :                  * SHA-1 (80-bits) as signature algorithm we are not able
     748             :                  * to connect anywhere with this level */
     749             :          .profile = GNUTLS_PROFILE_LOW,
     750             :          .sec_param = GNUTLS_SEC_PARAM_LOW
     751             :         },
     752             :         {.name = LEVEL_SECURE192,
     753             :          .alias = LEVEL_SECURE256,
     754             :          .cipher_list = &cipher_priority_secure192,
     755             :          .mac_list = &mac_priority_secure192,
     756             :          .kx_list = &kx_priority_secure,
     757             :          .sign_list = &sign_priority_secure192,
     758             :          .group_list = &supported_groups_secure192,
     759             :          .profile = GNUTLS_PROFILE_HIGH,
     760             :          .sec_param = GNUTLS_SEC_PARAM_HIGH
     761             :         },
     762             :         {.name = LEVEL_SUITEB128,
     763             :          .proto_list = &protocol_priority_suiteb,
     764             :          .cipher_list = &cipher_priority_suiteb128,
     765             :          .mac_list = &mac_priority_suiteb,
     766             :          .kx_list = &kx_priority_suiteb,
     767             :          .sign_list = &sign_priority_suiteb128,
     768             :          .group_list = &supported_groups_suiteb128,
     769             :          .profile = GNUTLS_PROFILE_SUITEB128,
     770             :          .sec_param = GNUTLS_SEC_PARAM_HIGH
     771             :         },
     772             :         {.name = LEVEL_SUITEB192,
     773             :          .proto_list = &protocol_priority_suiteb,
     774             :          .cipher_list = &cipher_priority_suiteb192,
     775             :          .mac_list = &mac_priority_suiteb,
     776             :          .kx_list = &kx_priority_suiteb,
     777             :          .sign_list = &sign_priority_suiteb192,
     778             :          .group_list = &supported_groups_suiteb192,
     779             :          .profile = GNUTLS_PROFILE_SUITEB192,
     780             :          .sec_param = GNUTLS_SEC_PARAM_ULTRA
     781             :         },
     782             :         {.name = LEVEL_LEGACY,
     783             :          .cipher_list = &cipher_priority_normal,
     784             :          .mac_list = &mac_priority_normal,
     785             :          .kx_list = &kx_priority_secure,
     786             :          .sign_list = &sign_priority_default,
     787             :          .group_list = &supported_groups_normal,
     788             :          .sec_param = GNUTLS_SEC_PARAM_VERY_WEAK
     789             :         },
     790             :         {.name = LEVEL_PERFORMANCE,
     791             :          .cipher_list = &cipher_priority_performance,
     792             :          .mac_list = &mac_priority_normal,
     793             :          .kx_list = &kx_priority_performance,
     794             :          .sign_list = &sign_priority_default,
     795             :          .group_list = &supported_groups_normal,
     796             :          .profile = GNUTLS_PROFILE_LOW,
     797             :          .sec_param = GNUTLS_SEC_PARAM_WEAK
     798             :         },
     799             :         {
     800             :          .name = NULL,
     801             :         }
     802             : };
     803             : 
     804             : #define SET_PROFILE(to_set) \
     805             :         profile = GNUTLS_VFLAGS_TO_PROFILE(priority_cache->additional_verify_flags); \
     806             :         if (profile == 0 || profile > to_set) { \
     807             :                 priority_cache->additional_verify_flags &= ~GNUTLS_VFLAGS_PROFILE_MASK; \
     808             :                 priority_cache->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(to_set); \
     809             :         }
     810             : 
     811             : #define SET_LEVEL(to_set) \
     812             :                 if (priority_cache->level == 0 || (unsigned)priority_cache->level > (unsigned)to_set) \
     813             :                         priority_cache->level = to_set
     814             : 
     815             : static
     816      368788 : int check_level(const char *level, gnutls_priority_t priority_cache,
     817             :                 int add)
     818             : {
     819      368788 :         bulk_rmadd_func *func;
     820      368788 :         unsigned profile = 0;
     821      368788 :         unsigned i;
     822      368788 :         int j;
     823      368788 :         const cipher_entry_st *centry;
     824             : 
     825      368788 :         if (add)
     826             :                 func = _add_priority;
     827             :         else
     828       19937 :                 func = _set_priority;
     829             : 
     830     3159640 :         for (i=0;;i++) {
     831     3159640 :                 if (pgroups[i].name == NULL)
     832             :                         return 0;
     833             : 
     834     2810800 :                 if (c_strcasecmp(level, pgroups[i].name) == 0 ||
     835     2790860 :                         (pgroups[i].alias != NULL && c_strcasecmp(level, pgroups[i].alias) == 0)) {
     836       19940 :                         if (pgroups[i].proto_list != NULL)
     837           2 :                                 func(&priority_cache->protocol, *pgroups[i].proto_list);
     838       19940 :                         func(&priority_cache->_cipher, *pgroups[i].cipher_list);
     839       19940 :                         func(&priority_cache->_kx, *pgroups[i].kx_list);
     840       19940 :                         func(&priority_cache->_mac, *pgroups[i].mac_list);
     841       19940 :                         func(&priority_cache->_sign_algo, *pgroups[i].sign_list);
     842       19940 :                         func(&priority_cache->_supported_ecc, *pgroups[i].group_list);
     843             : 
     844       19940 :                         if (pgroups[i].profile != 0) {
     845       19940 :                                 SET_PROFILE(pgroups[i].profile); /* set certificate level */
     846             :                         }
     847       19940 :                         SET_LEVEL(pgroups[i].sec_param); /* set DH params level */
     848       19940 :                         priority_cache->no_tickets = pgroups[i].no_tickets;
     849       19940 :                         if (priority_cache->have_cbc == 0) {
     850       79752 :                                 for (j=0;(*pgroups[i].cipher_list)[j]!=0;j++) {
     851       79750 :                                         centry = cipher_to_entry((*pgroups[i].cipher_list)[j]);
     852       79750 :                                         if (centry != NULL && centry->type == CIPHER_BLOCK) {
     853       19935 :                                                 priority_cache->have_cbc = 1;
     854       19935 :                                                 break;
     855             :                                         }
     856             :                                 }
     857             :                         }
     858       19940 :                         return 1;
     859             :                 }
     860             :         }
     861             : }
     862             : 
     863          92 : static void enable_compat(gnutls_priority_t c)
     864             : {
     865          92 :         ENABLE_PRIO_COMPAT(c);
     866          92 : }
     867          10 : static void enable_server_key_usage_violations(gnutls_priority_t c)
     868             : {
     869          10 :         c->allow_server_key_usage_violation = 1;
     870          10 : }
     871         154 : static void enable_allow_small_records(gnutls_priority_t c)
     872             : {
     873         154 :         c->_allow_small_records = 1;
     874         154 : }
     875           2 : static void enable_dumbfw(gnutls_priority_t c)
     876             : {
     877           2 :         c->_dumbfw = 1;
     878           2 : }
     879           9 : static void enable_no_extensions(gnutls_priority_t c)
     880             : {
     881           9 :         c->no_extensions = 1;
     882           9 : }
     883          21 : static void enable_no_ext_master_secret(gnutls_priority_t c)
     884             : {
     885          21 :         c->_no_ext_master_secret = 1;
     886          21 : }
     887         157 : static void enable_no_etm(gnutls_priority_t c)
     888             : {
     889         157 :         c->_no_etm = 1;
     890         157 : }
     891          30 : static void enable_force_etm(gnutls_priority_t c)
     892             : {
     893          30 :         c->force_etm = 1;
     894          30 : }
     895         128 : static void enable_no_tickets(gnutls_priority_t c)
     896             : {
     897         128 :         c->no_tickets = 1;
     898         128 : }
     899           0 : static void disable_wildcards(gnutls_priority_t c)
     900             : {
     901           0 :         c->additional_verify_flags |= GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS;
     902           0 : }
     903           3 : static void enable_profile_very_weak(gnutls_priority_t c)
     904             : {
     905           3 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_VERY_WEAK);
     906           3 : }
     907           5 : static void enable_profile_low(gnutls_priority_t c)
     908             : {
     909           5 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_LOW);
     910           5 : }
     911           3 : static void enable_profile_legacy(gnutls_priority_t c)
     912             : {
     913           3 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_LEGACY);
     914           3 : }
     915           2 : static void enable_profile_medium(gnutls_priority_t c)
     916             : {
     917           2 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_MEDIUM);
     918           2 : }
     919           3 : static void enable_profile_high(gnutls_priority_t c)
     920             : {
     921           3 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_HIGH);
     922           3 : }
     923           4 : static void enable_profile_ultra(gnutls_priority_t c)
     924             : {
     925           4 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_ULTRA);
     926           4 : }
     927           3 : static void enable_profile_future(gnutls_priority_t c)
     928             : {
     929           3 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_FUTURE);
     930           3 : }
     931           0 : static void enable_profile_suiteb128(gnutls_priority_t c)
     932             : {
     933           0 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_SUITEB128);
     934           0 : }
     935           0 : static void enable_profile_suiteb192(gnutls_priority_t c)
     936             : {
     937           0 :         ENABLE_PROFILE(c, GNUTLS_PROFILE_SUITEB128);
     938           0 : }
     939          30 : static void enable_safe_renegotiation(gnutls_priority_t c)
     940             : {
     941          30 :         c->sr = SR_SAFE;
     942             : 
     943          30 : }
     944         257 : static void enable_unsafe_renegotiation(gnutls_priority_t c)
     945             : {
     946         257 :         c->sr = SR_UNSAFE;
     947         257 : }
     948           0 : static void enable_partial_safe_renegotiation(gnutls_priority_t c)
     949             : {
     950           0 :         c->sr = SR_PARTIAL;
     951           0 : }
     952          27 : static void disable_safe_renegotiation(gnutls_priority_t c)
     953             : {
     954          27 :         c->sr = SR_DISABLED;
     955          27 : }
     956           7 : static void enable_fallback_scsv(gnutls_priority_t c)
     957             : {
     958           7 :         c->fallback = 1;
     959           7 : }
     960           1 : static void enable_latest_record_version(gnutls_priority_t c)
     961             : {
     962           1 :         c->min_record_version = 0;
     963           1 : }
     964           5 : static void enable_ssl3_record_version(gnutls_priority_t c)
     965             : {
     966           5 :         c->min_record_version = 1;
     967           5 : }
     968           0 : static void enable_verify_allow_rsa_md5(gnutls_priority_t c)
     969             : {
     970           0 :         c->additional_verify_flags |=
     971             :             GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5;
     972           0 : }
     973        5847 : static void enable_verify_allow_sha1(gnutls_priority_t c)
     974             : {
     975        5847 :         c->additional_verify_flags |=
     976             :             GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1;
     977        5847 : }
     978           0 : static void enable_verify_allow_broken(gnutls_priority_t c)
     979             : {
     980           0 :         c->additional_verify_flags |=
     981             :             GNUTLS_VERIFY_ALLOW_BROKEN;
     982           0 : }
     983           0 : static void disable_crl_checks(gnutls_priority_t c)
     984             : {
     985           0 :         c->additional_verify_flags |=
     986             :                 GNUTLS_VERIFY_DISABLE_CRL_CHECKS;
     987           0 : }
     988         162 : static void enable_server_precedence(gnutls_priority_t c)
     989             : {
     990         162 :         c->server_precedence = 1;
     991         162 : }
     992           0 : static void dummy_func(gnutls_priority_t c)
     993             : {
     994           0 : }
     995             : 
     996             : #include <priority_options.h>
     997             : 
     998             : static gnutls_certificate_verification_profiles_t system_wide_verification_profile = GNUTLS_PROFILE_UNKNOWN;
     999             : static name_val_array_t system_wide_priority_strings = NULL;
    1000             : static unsigned system_wide_priority_strings_init = 0;
    1001             : static unsigned system_wide_default_priority_string = 0;
    1002             : static unsigned fail_on_invalid_config = 0;
    1003             : static unsigned system_wide_disabled_ciphers[MAX_ALGOS+1] = {0};
    1004             : static unsigned system_wide_disabled_macs[MAX_ALGOS+1] = {0};
    1005             : static unsigned system_wide_disabled_groups[MAX_ALGOS+1] = {0};
    1006             : static unsigned system_wide_disabled_kxs[MAX_ALGOS+1] = {0};
    1007             : 
    1008             : static const char *system_priority_file = SYSTEM_PRIORITY_FILE;
    1009             : static time_t system_priority_last_mod = 0;
    1010             : 
    1011             : #define CUSTOM_PRIORITY_SECTION "priorities"
    1012             : #define OVERRIDES_SECTION "overrides"
    1013             : #define MAX_ALGO_NAME 2048
    1014             : 
    1015        2189 : static void _clear_default_system_priority(void)
    1016             : {
    1017        2189 :         if (system_wide_default_priority_string) {
    1018           0 :                 gnutls_free(_gnutls_default_priority_string);
    1019           0 :                 _gnutls_default_priority_string = DEFAULT_PRIORITY_STRING;
    1020           0 :                 system_wide_default_priority_string = 0;
    1021             :         }
    1022             : 
    1023        2189 : }
    1024             : 
    1025        1702 : gnutls_certificate_verification_profiles_t _gnutls_get_system_wide_verification_profile(void)
    1026             : {
    1027        1702 :         return system_wide_verification_profile;
    1028             : }
    1029             : 
    1030             : /* removes spaces */
    1031          60 : static char *clear_spaces(const char *str, char out[MAX_ALGO_NAME])
    1032             : {
    1033          60 :         const char *p = str;
    1034          60 :         unsigned i = 0;
    1035             : 
    1036          60 :         while (c_isspace(*p))
    1037           0 :                 p++;
    1038             : 
    1039         616 :         while (!c_isspace(*p) && *p != 0) {
    1040         556 :                 out[i++] = *p;
    1041         556 :                 p++;
    1042             : 
    1043         556 :                 if (i >= MAX_ALGO_NAME-1)
    1044             :                         break;
    1045             :         }
    1046          60 :         out[i] = 0;
    1047          60 :         return out;
    1048             : }
    1049             : 
    1050             : /* This function parses a gnutls configuration file and updates internal
    1051             :  * settings accordingly.
    1052             :  */
    1053       10023 : static int cfg_ini_handler(void *_ctx, const char *section, const char *name, const char *value)
    1054             : {
    1055       10023 :         char *p;
    1056       10023 :         int ret, type;
    1057       10023 :         unsigned i;
    1058       10023 :         char str[MAX_ALGO_NAME];
    1059             : 
    1060             :         /* Note that we intentionally overwrite the value above; inih does
    1061             :          * not use that value after we handle it. */
    1062             : 
    1063             :         /* Parse sections */
    1064       10023 :         if (section == NULL || section[0] == 0 || c_strcasecmp(section, CUSTOM_PRIORITY_SECTION)==0) {
    1065        9959 :                 if (system_wide_priority_strings_init == 0) {
    1066        3316 :                         _name_val_array_init(&system_wide_priority_strings);
    1067        3316 :                         system_wide_priority_strings_init = 1;
    1068             :                 }
    1069             : 
    1070        9959 :                 _gnutls_debug_log("cfg: adding priority: %s -> %s\n", name, value);
    1071             : 
    1072        9959 :                 ret = _name_val_array_append(&system_wide_priority_strings, name, value);
    1073        9959 :                 if (ret < 0)
    1074           0 :                         return 0;
    1075          64 :         } else if (c_strcasecmp(section, OVERRIDES_SECTION)==0) {
    1076          64 :                 if (c_strcasecmp(name, "default-priority-string")==0) {
    1077           4 :                         _clear_default_system_priority();
    1078           4 :                         p = clear_spaces(value, str);
    1079           4 :                         _gnutls_debug_log("cfg: setting default-priority-string to %s\n", p);
    1080           4 :                         if (strlen(p) > 0) {
    1081           2 :                                 _gnutls_default_priority_string = gnutls_strdup(p);
    1082           2 :                                 if (!_gnutls_default_priority_string) {
    1083           0 :                                         _gnutls_default_priority_string = DEFAULT_PRIORITY_STRING;
    1084           0 :                                         _gnutls_debug_log("cfg: failed setting default-priority-string\n");
    1085           0 :                                         return 0;
    1086             :                                 }
    1087           2 :                                 system_wide_default_priority_string = 1;
    1088             :                         } else {
    1089           2 :                                 _gnutls_debug_log("cfg: empty default-priority-string, using default\n");
    1090           2 :                                 if (fail_on_invalid_config)
    1091           0 :                                         return 0;
    1092             :                         }
    1093          60 :                 } else if (c_strcasecmp(name, "insecure-hash")==0) {
    1094           2 :                         p = clear_spaces(value, str);
    1095             : 
    1096           2 :                         _gnutls_debug_log("cfg: marking hash %s as insecure\n",
    1097             :                                           p);
    1098             : 
    1099           2 :                         ret = _gnutls_digest_mark_insecure(p);
    1100           2 :                         if (ret < 0) {
    1101           0 :                                 _gnutls_debug_log("cfg: found unknown hash %s in %s\n",
    1102             :                                                   p, name);
    1103           0 :                                 if (fail_on_invalid_config)
    1104           0 :                                         return 0;
    1105             :                         }
    1106          58 :                 } else if (c_strcasecmp(name, "insecure-sig")==0 || c_strcasecmp(name, "insecure-sig-for-cert")==0) {
    1107           3 :                         p = clear_spaces(value, str);
    1108             : 
    1109           3 :                         if (c_strcasecmp(name, "insecure-sig")==0) {
    1110           2 :                                 type = _INSECURE;
    1111           2 :                                 _gnutls_debug_log("cfg: marking signature %s as insecure\n",
    1112             :                                                   p);
    1113             :                         } else {
    1114           1 :                                 _gnutls_debug_log("cfg: marking signature %s as insecure for certs\n",
    1115             :                                                   p);
    1116             :                                 type = _INSECURE_FOR_CERTS;
    1117             :                         }
    1118             : 
    1119           3 :                         ret = _gnutls_sign_mark_insecure(p, type);
    1120           3 :                         if (ret < 0) {
    1121           0 :                                 _gnutls_debug_log("cfg: found unknown signature algorithm %s in %s\n",
    1122             :                                                   p, name);
    1123           0 :                                 if (fail_on_invalid_config)
    1124           0 :                                         return 0;
    1125             :                         }
    1126          55 :                 } else if (c_strcasecmp(name, "disabled-version")==0) {
    1127           8 :                         p = clear_spaces(value, str);
    1128             : 
    1129           8 :                         _gnutls_debug_log("cfg: disabling version %s\n",
    1130             :                                           p);
    1131             : 
    1132           8 :                         ret = _gnutls_version_mark_disabled(p);
    1133           8 :                         if (ret < 0) {
    1134           0 :                                 _gnutls_debug_log("cfg: found unknown version %s in %s\n",
    1135             :                                                   p, name);
    1136           0 :                                 if (fail_on_invalid_config)
    1137           0 :                                         return 0;
    1138             :                         }
    1139          47 :                 } else if (c_strcasecmp(name, "disabled-curve")==0) {
    1140           6 :                         p = clear_spaces(value, str);
    1141             : 
    1142           6 :                         _gnutls_debug_log("cfg: disabling curve %s\n",
    1143             :                                           p);
    1144             : 
    1145           6 :                         ret = _gnutls_ecc_curve_mark_disabled(p);
    1146           6 :                         if (ret < 0) {
    1147           0 :                                 _gnutls_debug_log("cfg: found unknown curve %s in %s\n",
    1148             :                                                   p, name);
    1149           0 :                                 if (fail_on_invalid_config)
    1150           0 :                                         return 0;
    1151             :                         }
    1152          41 :                 } else if (c_strcasecmp(name, "min-verification-profile")==0) {
    1153           4 :                         gnutls_certificate_verification_profiles_t profile;
    1154           4 :                         profile = gnutls_certificate_verification_profile_get_id(value);
    1155             : 
    1156           4 :                         if (profile == GNUTLS_PROFILE_UNKNOWN) {
    1157           0 :                                 _gnutls_debug_log("cfg: found unknown profile %s in %s\n",
    1158             :                                                   value, name);
    1159           0 :                                 if (fail_on_invalid_config)
    1160             :                                         return 0;
    1161             :                         }
    1162             : 
    1163           4 :                         system_wide_verification_profile = profile;
    1164          37 :                 } else if (c_strcasecmp(name, "tls-disabled-cipher")==0) {
    1165          18 :                         unsigned algo;
    1166             : 
    1167          18 :                         p = clear_spaces(value, str);
    1168             : 
    1169          18 :                         _gnutls_debug_log("cfg: disabling cipher %s for TLS\n",
    1170             :                                           p);
    1171             : 
    1172             : 
    1173          18 :                         algo = gnutls_cipher_get_id(p);
    1174          18 :                         if (algo == 0) {
    1175           0 :                                 _gnutls_debug_log("cfg: unknown algorithm %s listed at %s\n",
    1176             :                                                   p, name);
    1177           0 :                                 if (fail_on_invalid_config)
    1178             :                                         return 0;
    1179             :                         }
    1180             : 
    1181          18 :                         i = 0;
    1182          27 :                         while (system_wide_disabled_ciphers[i] != 0)
    1183           9 :                                 i++;
    1184             : 
    1185          18 :                         if (i > MAX_ALGOS-1) {
    1186           0 :                                 _gnutls_debug_log("cfg: too many (%d) disabled ciphers from %s\n",
    1187             :                                                   i, name);
    1188           0 :                                 if (fail_on_invalid_config)
    1189             :                                         return 0;
    1190           0 :                                 goto exit;
    1191             :                         }
    1192          18 :                         system_wide_disabled_ciphers[i] = algo;
    1193          18 :                         system_wide_disabled_ciphers[i+1] = 0;
    1194             : 
    1195          19 :                 } else if (c_strcasecmp(name, "tls-disabled-mac")==0) {
    1196           8 :                         unsigned algo;
    1197             : 
    1198           8 :                         p = clear_spaces(value, str);
    1199             : 
    1200           8 :                         _gnutls_debug_log("cfg: disabling MAC %s for TLS\n",
    1201             :                                           p);
    1202             : 
    1203           8 :                         algo = gnutls_mac_get_id(p);
    1204           8 :                         if (algo == 0) {
    1205           0 :                                 _gnutls_debug_log("cfg: unknown algorithm %s listed at %s\n",
    1206             :                                                   p, name);
    1207           0 :                                 if (fail_on_invalid_config)
    1208             :                                         return 0;
    1209           0 :                                 goto exit;
    1210             :                         }
    1211             : 
    1212             :                         i = 0;
    1213           8 :                         while (system_wide_disabled_macs[i] != 0)
    1214           0 :                                 i++;
    1215             : 
    1216           8 :                         if (i > MAX_ALGOS-1) {
    1217           0 :                                 _gnutls_debug_log("cfg: too many (%d) disabled MACs from %s\n",
    1218             :                                                   i, name);
    1219           0 :                                 if (fail_on_invalid_config)
    1220             :                                         return 0;
    1221           0 :                                 goto exit;
    1222             :                         }
    1223           8 :                         system_wide_disabled_macs[i] = algo;
    1224           8 :                         system_wide_disabled_macs[i+1] = 0;
    1225          11 :                 } else if (c_strcasecmp(name, "tls-disabled-group")==0) {
    1226           8 :                         unsigned algo;
    1227             : 
    1228           8 :                         p = clear_spaces(value, str);
    1229             : 
    1230           8 :                         if (strlen(p) > 6)
    1231           8 :                                 p += 6; // skip GROUP-
    1232             : 
    1233           8 :                         _gnutls_debug_log("cfg: disabling group %s for TLS\n",
    1234             :                                           p);
    1235             : 
    1236           8 :                         algo = gnutls_group_get_id(p);
    1237           8 :                         if (algo == 0) {
    1238           0 :                                 _gnutls_debug_log("cfg: unknown group %s listed at %s\n",
    1239             :                                                   p, name);
    1240           0 :                                 if (fail_on_invalid_config)
    1241             :                                         return 0;
    1242           0 :                                 goto exit;
    1243             :                         }
    1244             : 
    1245             :                         i = 0;
    1246           8 :                         while (system_wide_disabled_groups[i] != 0)
    1247           0 :                                 i++;
    1248             : 
    1249           8 :                         if (i > MAX_ALGOS-1) {
    1250           0 :                                 _gnutls_debug_log("cfg: too many (%d) disabled groups from %s\n",
    1251             :                                                   i, name);
    1252           0 :                                 if (fail_on_invalid_config)
    1253             :                                         return 0;
    1254           0 :                                 goto exit;
    1255             :                         }
    1256           8 :                         system_wide_disabled_groups[i] = algo;
    1257           8 :                         system_wide_disabled_groups[i+1] = 0;
    1258           3 :                 } else if (c_strcasecmp(name, "tls-disabled-kx")==0) {
    1259           3 :                         unsigned algo;
    1260             : 
    1261           3 :                         p = clear_spaces(value, str);
    1262             : 
    1263           3 :                         _gnutls_debug_log("cfg: disabling key exchange %s for TLS\n",
    1264             :                                           p);
    1265             : 
    1266           3 :                         algo = gnutls_kx_get_id(p);
    1267           3 :                         if (algo == 0) {
    1268           1 :                                 _gnutls_debug_log("cfg: unknown key exchange %s listed at %s\n",
    1269             :                                                   p, name);
    1270           1 :                                 if (fail_on_invalid_config)
    1271             :                                         return 0;
    1272           1 :                                 goto exit;
    1273             :                         }
    1274             : 
    1275             :                         i = 0;
    1276           3 :                         while (system_wide_disabled_kxs[i] != 0)
    1277           1 :                                 i++;
    1278             : 
    1279           2 :                         if (i > MAX_ALGOS-1) {
    1280           0 :                                 _gnutls_debug_log("cfg: too many (%d) disabled key exchanges from %s\n",
    1281             :                                                   i, name);
    1282           0 :                                 if (fail_on_invalid_config)
    1283             :                                         return 0;
    1284           0 :                                 goto exit;
    1285             :                         }
    1286           2 :                         system_wide_disabled_kxs[i] = algo;
    1287           2 :                         system_wide_disabled_kxs[i+1] = 0;
    1288             :                 } else {
    1289           0 :                         _gnutls_debug_log("unknown parameter %s\n", name);
    1290           0 :                         if (fail_on_invalid_config)
    1291           0 :                                 return 0;
    1292             :                 }
    1293             :         } else {
    1294           0 :                 _gnutls_debug_log("cfg: unknown section %s\n",
    1295             :                                   section);
    1296           0 :                 if (fail_on_invalid_config)
    1297           0 :                         return 0;
    1298             :         }
    1299             : 
    1300           0 :  exit:
    1301             :         return 1;
    1302             : }
    1303             : 
    1304        3410 : static void _gnutls_update_system_priorities(void)
    1305             : {
    1306        3410 :         int ret;
    1307        3410 :         struct stat sb;
    1308        3410 :         FILE *fp;
    1309             : 
    1310        3410 :         if (stat(system_priority_file, &sb) < 0) {
    1311          37 :                 _gnutls_debug_log("cfg: unable to access: %s: %d\n",
    1312             :                                   system_priority_file, errno);
    1313          64 :                 return;
    1314             :         }
    1315             : 
    1316        3373 :         if (system_wide_priority_strings_init != 0 &&
    1317          32 :             sb.st_mtime == system_priority_last_mod) {
    1318          27 :                 _gnutls_debug_log("cfg: system priority %s has not changed\n",
    1319             :                                   system_priority_file);
    1320          27 :                 return;
    1321             :         }
    1322             : 
    1323        3346 :         if (system_wide_priority_strings_init != 0)
    1324           5 :                 _name_val_array_clear(&system_wide_priority_strings);
    1325             : 
    1326        3346 :         fp = fopen(system_priority_file, "re");
    1327        3346 :         if (fp == NULL) {
    1328           0 :                 _gnutls_debug_log("cfg: unable to open: %s: %d\n",
    1329             :                                   system_priority_file, errno);
    1330           0 :                 return;
    1331             :         }
    1332        3346 :         ret = ini_parse_file(fp, cfg_ini_handler, NULL);
    1333        3346 :         fclose(fp);
    1334        3346 :         if (ret != 0) {
    1335           0 :                 _gnutls_debug_log("cfg: unable to parse: %s: %d\n",
    1336             :                                   system_priority_file, ret);
    1337           0 :                 if (fail_on_invalid_config)
    1338           0 :                         exit(1);
    1339             :                 return;
    1340             :         }
    1341             : 
    1342        3346 :         _gnutls_debug_log("cfg: loaded system priority %s mtime %lld\n",
    1343             :                           system_priority_file,
    1344             :                           (unsigned long long)sb.st_mtime);
    1345             : 
    1346        3346 :         system_priority_last_mod = sb.st_mtime;
    1347             : }
    1348             : 
    1349        3383 : void _gnutls_load_system_priorities(void)
    1350             : {
    1351        3383 :         const char *p;
    1352             : 
    1353        3383 :         p = secure_getenv("GNUTLS_SYSTEM_PRIORITY_FILE");
    1354        3383 :         if (p != NULL)
    1355        3346 :                 system_priority_file = p;
    1356             : 
    1357        3383 :         p = secure_getenv("GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID");
    1358        3383 :         if (p != NULL && p[0] == '1' && p[1] == 0)
    1359          62 :                 fail_on_invalid_config = 1;
    1360             : 
    1361        3383 :         _gnutls_update_system_priorities();
    1362        3383 : }
    1363             : 
    1364        2185 : void _gnutls_unload_system_priorities(void)
    1365             : {
    1366        2185 :         _name_val_array_clear(&system_wide_priority_strings);
    1367        2185 :         _clear_default_system_priority();
    1368        2185 :         system_priority_last_mod = 0;
    1369        2185 : }
    1370             : 
    1371             : /**
    1372             :  * gnutls_get_system_config_file:
    1373             :  *
    1374             :  * Returns the filename of the system wide configuration
    1375             :  * file loaded by the library. The returned pointer is valid
    1376             :  * until the library is unloaded.
    1377             :  *
    1378             :  * Returns: a constant pointer to the config file loaded, or %NULL if none
    1379             :  *
    1380             :  * Since: 3.6.9
    1381             :  **/
    1382          16 : const char *gnutls_get_system_config_file(void)
    1383             : {
    1384          16 :         if (system_wide_priority_strings_init)
    1385          16 :                 return system_priority_file;
    1386             :         else
    1387             :                 return NULL;
    1388             : }
    1389             : 
    1390             : #define S(str) ((str!=NULL)?str:"")
    1391             : 
    1392             : /* Returns the new priorities if a priority string prefixed
    1393             :  * with '@' is provided, or just a copy of the provided
    1394             :  * priorities, appended with any additional present in
    1395             :  * the priorities string.
    1396             :  *
    1397             :  * The returned string must be released using gnutls_free().
    1398             :  */
    1399       23381 : char *_gnutls_resolve_priorities(const char* priorities)
    1400             : {
    1401       23381 :         const char *p = priorities;
    1402       23381 :         char *additional = NULL;
    1403       23381 :         char *ret = NULL;
    1404       23381 :         const char *ss, *ss_next;
    1405       23381 :         unsigned ss_len, ss_next_len;
    1406       23381 :         size_t n, n2 = 0;
    1407             : 
    1408       23381 :         while (c_isspace(*p))
    1409           0 :                 p++;
    1410             : 
    1411       23381 :         if (*p == '@') {
    1412          20 :                 ss = p+1;
    1413          20 :                 additional = strchr(ss, ':');
    1414          20 :                 if (additional != NULL) {
    1415           7 :                         additional++;
    1416             :                 }
    1417             : 
    1418          27 :                 do {
    1419          27 :                         ss_next = strchr(ss, ',');
    1420          27 :                         if (ss_next != NULL) {
    1421          14 :                                 if (additional && ss_next > additional)
    1422             :                                         ss_next = NULL;
    1423             :                                 else
    1424          14 :                                         ss_next++;
    1425             :                         }
    1426             : 
    1427          27 :                         if (ss_next) {
    1428          14 :                                 ss_len = ss_next - ss - 1;
    1429          14 :                                 ss_next_len = additional - ss_next - 1;
    1430          13 :                         } else if (additional) {
    1431           6 :                                 ss_len = additional - ss - 1;
    1432           6 :                                 ss_next_len = 0;
    1433             :                         } else {
    1434           7 :                                 ss_len = strlen(ss);
    1435           7 :                                 ss_next_len = 0;
    1436             :                         }
    1437             : 
    1438             :                         /* Always try to refresh the cached data, to
    1439             :                          * allow it to be updated without restarting
    1440             :                          * all applications
    1441             :                          */
    1442          27 :                         _gnutls_update_system_priorities();
    1443             : 
    1444          27 :                         p = _name_val_array_value(system_wide_priority_strings, ss, ss_len);
    1445             : 
    1446          27 :                         _gnutls_debug_log("resolved '%.*s' to '%s', next '%.*s'\n",
    1447             :                                           ss_len, ss, S(p), ss_next_len, S(ss_next));
    1448          27 :                         ss = ss_next;
    1449          27 :                 } while (ss && p == NULL);
    1450             : 
    1451          20 :                 if (p == NULL) {
    1452           6 :                         _gnutls_debug_log("unable to resolve %s\n", priorities);
    1453           6 :                         ret = NULL;
    1454           6 :                         goto finish;
    1455             :                 }
    1456             : 
    1457          14 :                 n = strlen(p);
    1458          14 :                 if (additional)
    1459           3 :                         n2 = strlen(additional);
    1460             : 
    1461          14 :                 ret = gnutls_malloc(n+n2+1+1);
    1462          14 :                 if (ret == NULL) {
    1463           0 :                         goto finish;
    1464             :                 }
    1465             : 
    1466          14 :                 memcpy(ret, p, n);
    1467          14 :                 if (additional != NULL) {
    1468           3 :                         ret[n] = ':';
    1469           3 :                         memcpy(&ret[n+1], additional, n2);
    1470           3 :                         ret[n+n2+1] = 0;
    1471             :                 } else {
    1472          11 :                         ret[n] = 0;
    1473             :                 }
    1474             :         } else {
    1475       23361 :                 return gnutls_strdup(p);
    1476             :         }
    1477             : 
    1478          14 : finish:
    1479          20 :         if (ret != NULL) {
    1480          14 :                 _gnutls_debug_log("selected priority string: %s\n", ret);
    1481             :         }
    1482             : 
    1483             :         return ret;
    1484             : }
    1485             : 
    1486       19674 : static void add_ec(gnutls_priority_t priority_cache)
    1487             : {
    1488       19674 :         const gnutls_group_entry_st *ge;
    1489       19674 :         unsigned i;
    1490             : 
    1491      211513 :         for (i = 0; i < priority_cache->_supported_ecc.num_priorities; i++) {
    1492      191839 :                 ge = _gnutls_id_to_group(priority_cache->_supported_ecc.priorities[i]);
    1493      191839 :                 if (ge != NULL && priority_cache->groups.size < sizeof(priority_cache->groups.entry)/sizeof(priority_cache->groups.entry[0])) {
    1494             :                         /* do not add groups which do not correspond to enabled ciphersuites */
    1495      190222 :                         if (!ge->curve)
    1496       94116 :                                 continue;
    1497       96106 :                         priority_cache->groups.entry[priority_cache->groups.size++] = ge;
    1498             :                 }
    1499             :         }
    1500       19674 : }
    1501             : 
    1502       18699 : static void add_dh(gnutls_priority_t priority_cache)
    1503             : {
    1504       18699 :         const gnutls_group_entry_st *ge;
    1505       18699 :         unsigned i;
    1506             : 
    1507      199534 :         for (i = 0; i < priority_cache->_supported_ecc.num_priorities; i++) {
    1508      180835 :                 ge = _gnutls_id_to_group(priority_cache->_supported_ecc.priorities[i]);
    1509      180835 :                 if (ge != NULL && priority_cache->groups.size < sizeof(priority_cache->groups.entry)/sizeof(priority_cache->groups.entry[0])) {
    1510             :                         /* do not add groups which do not correspond to enabled ciphersuites */
    1511      179463 :                         if (!ge->prime)
    1512       90596 :                                 continue;
    1513       88867 :                         priority_cache->groups.entry[priority_cache->groups.size++] = ge;
    1514       88867 :                         priority_cache->groups.have_ffdhe = 1;
    1515             :                 }
    1516             :         }
    1517       18699 : }
    1518             : 
    1519             : /* This function was originally precalculating ciphersuite-specific items, however
    1520             :  * it has now extended to much more than that. It provides a consistency check to
    1521             :  * set parameters, and in cases it applies policy specific items.
    1522             :  */
    1523       23347 : static int set_ciphersuite_list(gnutls_priority_t priority_cache)
    1524             : {
    1525       23347 :         unsigned i, j, z;
    1526       23347 :         const gnutls_cipher_suite_entry_st *ce;
    1527       23347 :         const gnutls_sign_entry_st *se;
    1528       23347 :         unsigned have_ec = 0;
    1529       23347 :         unsigned have_dh = 0;
    1530       23347 :         unsigned tls_sig_sem = 0;
    1531       23347 :         const version_entry_st *tlsmax = NULL, *vers;
    1532       23347 :         const version_entry_st *dtlsmax = NULL;
    1533       23347 :         const version_entry_st *tlsmin = NULL;
    1534       23347 :         const version_entry_st *dtlsmin = NULL;
    1535       23347 :         unsigned have_tls13 = 0, have_srp = 0;
    1536       23347 :         unsigned have_pre_tls12 = 0, have_tls12 = 0;
    1537       23347 :         unsigned have_psk = 0, have_null = 0, have_rsa_psk = 0;
    1538             : 
    1539             :         /* have_psk indicates that a PSK key exchange compatible
    1540             :          * with TLS1.3 is enabled. */
    1541             : 
    1542       23347 :         priority_cache->cs.size = 0;
    1543       23347 :         priority_cache->sigalg.size = 0;
    1544       23347 :         priority_cache->groups.size = 0;
    1545       23347 :         priority_cache->groups.have_ffdhe = 0;
    1546             : 
    1547             :         /* disable key exchanges which are globally disabled */
    1548       23347 :         z = 0;
    1549       23349 :         while (system_wide_disabled_kxs[z] != 0) {
    1550          10 :                 for (i = j = 0; i < priority_cache->_kx.num_priorities; i++) {
    1551           8 :                         if (priority_cache->_kx.priorities[i] != system_wide_disabled_kxs[z])
    1552           7 :                                 priority_cache->_kx.priorities[j++] = priority_cache->_kx.priorities[i];
    1553             :                 }
    1554           2 :                 priority_cache->_kx.num_priorities = j;
    1555           2 :                 z++;
    1556             :         }
    1557             : 
    1558             :         /* disable groups which are globally disabled */
    1559             :         z = 0;
    1560       23355 :         while (system_wide_disabled_groups[z] != 0) {
    1561          71 :                 for (i = j = 0; i < priority_cache->_supported_ecc.num_priorities; i++) {
    1562          63 :                         if (priority_cache->_supported_ecc.priorities[i] != system_wide_disabled_groups[z])
    1563          55 :                                 priority_cache->_supported_ecc.priorities[j++] = priority_cache->_supported_ecc.priorities[i];
    1564             :                 }
    1565           8 :                 priority_cache->_supported_ecc.num_priorities = j;
    1566           8 :                 z++;
    1567             :         }
    1568             : 
    1569             :         /* disable ciphers which are globally disabled */
    1570             :         z = 0;
    1571       23465 :         while (system_wide_disabled_ciphers[z] != 0) {
    1572        1006 :                 for (i = j = 0; i < priority_cache->_cipher.num_priorities; i++) {
    1573         888 :                         if (priority_cache->_cipher.priorities[i] != system_wide_disabled_ciphers[z])
    1574         872 :                                 priority_cache->_cipher.priorities[j++] = priority_cache->_cipher.priorities[i];
    1575             :                 }
    1576         118 :                 priority_cache->_cipher.num_priorities = j;
    1577         118 :                 z++;
    1578             :         }
    1579             : 
    1580             :         /* disable MACs which are globally disabled */
    1581             :         z = 0;
    1582       23355 :         while (system_wide_disabled_macs[z] != 0) {
    1583          23 :                 for (i = j = 0; i < priority_cache->_mac.num_priorities; i++) {
    1584          15 :                         if (priority_cache->_mac.priorities[i] != system_wide_disabled_macs[z])
    1585           7 :                                 priority_cache->_mac.priorities[j++] = priority_cache->_mac.priorities[i];
    1586             :                 }
    1587           8 :                 priority_cache->_mac.num_priorities = j;
    1588           8 :                 z++;
    1589             :         }
    1590             : 
    1591      202663 :         for (j=0;j<priority_cache->_cipher.num_priorities;j++) {
    1592      179358 :                 if (priority_cache->_cipher.priorities[j] == GNUTLS_CIPHER_NULL) {
    1593             :                         have_null = 1;
    1594             :                         break;
    1595             :                 }
    1596             :         }
    1597             : 
    1598      109508 :         for (i = 0; i < priority_cache->_kx.num_priorities; i++) {
    1599       86161 :                 if (IS_SRP_KX(priority_cache->_kx.priorities[i])) {
    1600             :                         have_srp = 1;
    1601      169392 :                 } else if (_gnutls_kx_is_psk(priority_cache->_kx.priorities[i])) {
    1602        9436 :                         if (priority_cache->_kx.priorities[i] == GNUTLS_KX_RSA_PSK)
    1603             :                                 have_rsa_psk = 1;
    1604             :                         else
    1605        8592 :                                 have_psk = 1;
    1606             :                 }
    1607             :         }
    1608             : 
    1609             :         /* disable TLS versions which are added but are unsupported */
    1610      108104 :         for (i = j = 0; i < priority_cache->protocol.num_priorities; i++) {
    1611       84757 :                 vers = version_to_entry(priority_cache->protocol.priorities[i]);
    1612       84757 :                 if (!vers || vers->supported)
    1613       75839 :                         priority_cache->protocol.priorities[j++] = priority_cache->protocol.priorities[i];
    1614             :         }
    1615       23347 :         priority_cache->protocol.num_priorities = j;
    1616             : 
    1617             : 
    1618             :         /* if we have NULL ciphersuites, SRP, or RSA-PSK enabled remove TLS1.3+
    1619             :          * protocol versions; they cannot be negotiated under TLS1.3. */
    1620       23347 :         if (have_null || have_srp || have_rsa_psk || priority_cache->no_extensions) {
    1621       11039 :                 for (i = j = 0; i < priority_cache->protocol.num_priorities; i++) {
    1622        9086 :                         vers = version_to_entry(priority_cache->protocol.priorities[i]);
    1623        9086 :                         if (!vers || !vers->tls13_sem)
    1624        7316 :                                 priority_cache->protocol.priorities[j++] = priority_cache->protocol.priorities[i];
    1625             :                 }
    1626        1953 :                 priority_cache->protocol.num_priorities = j;
    1627             :         }
    1628             : 
    1629       97416 :         for (i = 0; i < priority_cache->protocol.num_priorities; i++) {
    1630       74069 :                 vers = version_to_entry(priority_cache->protocol.priorities[i]);
    1631       74069 :                 if (!vers)
    1632           0 :                         continue;
    1633             : 
    1634       74069 :                 if (vers->transport == GNUTLS_STREAM) { /* TLS */
    1635       63253 :                         tls_sig_sem |= vers->tls_sig_sem;
    1636       63253 :                         if (vers->tls13_sem)
    1637       15622 :                                 have_tls13 = 1;
    1638             : 
    1639       63253 :                         if (vers->id == GNUTLS_TLS1_2)
    1640             :                                 have_tls12 = 1;
    1641       43061 :                         else if (vers->id < GNUTLS_TLS1_2)
    1642       27439 :                                 have_pre_tls12 = 1;
    1643             : 
    1644       63253 :                         if (tlsmax == NULL || vers->age > tlsmax->age)
    1645       23061 :                                 tlsmax = vers;
    1646       63253 :                         if (tlsmin == NULL || vers->age < tlsmin->age)
    1647       63204 :                                 tlsmin = vers;
    1648             :                 } else { /* dtls */
    1649       10816 :                         tls_sig_sem |= vers->tls_sig_sem;
    1650             : 
    1651             :                         /* we need to introduce similar handling to above
    1652             :                          * when DTLS1.3 is supported */
    1653             : 
    1654       10816 :                         if (dtlsmax == NULL || vers->age > dtlsmax->age)
    1655        5622 :                                 dtlsmax = vers;
    1656       10816 :                         if (dtlsmin == NULL || vers->age < dtlsmin->age)
    1657       10816 :                                 dtlsmin = vers;
    1658             :                 }
    1659             :         }
    1660             : 
    1661             :         /* DTLS or TLS protocols must be present */
    1662       23347 :         if ((!tlsmax || !tlsmin) && (!dtlsmax || !dtlsmin))
    1663           1 :                 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
    1664             : 
    1665             : 
    1666       23346 :         priority_cache->have_psk = have_psk;
    1667             : 
    1668             :         /* if we are have TLS1.3+ do not enable any key exchange algorithms,
    1669             :          * the protocol doesn't require any. */
    1670       23346 :         if (tlsmin && tlsmin->tls13_sem && !have_psk) {
    1671         686 :                 if (!dtlsmin || (dtlsmin && dtlsmin->tls13_sem))
    1672         589 :                         priority_cache->_kx.num_priorities = 0;
    1673             :         }
    1674             : 
    1675             :         /* Add TLS 1.3 ciphersuites (no KX) */
    1676      202739 :         for (j=0;j<priority_cache->_cipher.num_priorities;j++) {
    1677      621414 :                 for (z=0;z<priority_cache->_mac.num_priorities;z++) {
    1678      884042 :                         ce = cipher_suite_get(
    1679      442021 :                                 0, priority_cache->_cipher.priorities[j],
    1680      442021 :                                 priority_cache->_mac.priorities[z]);
    1681             : 
    1682      442021 :                         if (ce != NULL && priority_cache->cs.size < MAX_CIPHERSUITE_SIZE) {
    1683       96375 :                                 priority_cache->cs.entry[priority_cache->cs.size++] = ce;
    1684             :                         }
    1685             :                 }
    1686             :         }
    1687             : 
    1688      107621 :         for (i = 0; i < priority_cache->_kx.num_priorities; i++) {
    1689      758236 :                 for (j=0;j<priority_cache->_cipher.num_priorities;j++) {
    1690     2441540 :                         for (z=0;z<priority_cache->_mac.num_priorities;z++) {
    1691     3535170 :                                 ce = cipher_suite_get(
    1692     1767580 :                                         priority_cache->_kx.priorities[i],
    1693     1767580 :                                         priority_cache->_cipher.priorities[j],
    1694     1767580 :                                         priority_cache->_mac.priorities[z]);
    1695             : 
    1696     1767580 :                                 if (ce != NULL && priority_cache->cs.size < MAX_CIPHERSUITE_SIZE) {
    1697      586498 :                                         priority_cache->cs.entry[priority_cache->cs.size++] = ce;
    1698      586498 :                                         if (!have_ec && (_gnutls_kx_is_ecc(ce->kx_algorithm) ||
    1699       29282 :                                                          _gnutls_kx_is_vko_gost(ce->kx_algorithm))) {
    1700       18597 :                                                 have_ec = 1;
    1701       18597 :                                                 add_ec(priority_cache);
    1702             :                                         }
    1703     1785250 :                                         if (!have_dh && _gnutls_kx_is_dhe(ce->kx_algorithm)) {
    1704       17670 :                                                 have_dh = 1;
    1705       17670 :                                                 add_dh(priority_cache);
    1706             :                                         }
    1707             :                                 }
    1708             :                         }
    1709             :                 }
    1710             :         }
    1711             : 
    1712       23346 :         if (have_tls13 && (!have_ec || !have_dh)) {
    1713             :                 /* scan groups to determine have_ec and have_dh */
    1714        6236 :                 for (i=0; i < priority_cache->_supported_ecc.num_priorities; i++) {
    1715        6172 :                         const gnutls_group_entry_st *ge;
    1716        6172 :                         ge = _gnutls_id_to_group(priority_cache->_supported_ecc.priorities[i]);
    1717        6172 :                         if (ge) {
    1718        6172 :                                 if (ge->curve && !have_ec) {
    1719        1077 :                                         add_ec(priority_cache);
    1720        1077 :                                         have_ec = 1;
    1721        5095 :                                 } else if (ge->prime && !have_dh) {
    1722        1029 :                                         add_dh(priority_cache);
    1723        1029 :                                         have_dh = 1;
    1724             :                                 }
    1725             : 
    1726        6172 :                                 if (have_dh && have_ec)
    1727             :                                         break;
    1728             :                         }
    1729             :                 }
    1730             : 
    1731             :         }
    1732             : 
    1733      478326 :         for (i = 0; i < priority_cache->_sign_algo.num_priorities; i++) {
    1734      454980 :                 se = _gnutls_sign_to_entry(priority_cache->_sign_algo.priorities[i]);
    1735      454980 :                 if (se != NULL && priority_cache->sigalg.size < sizeof(priority_cache->sigalg.entry)/sizeof(priority_cache->sigalg.entry[0])) {
    1736             :                         /* if the signature algorithm semantics are not compatible with
    1737             :                          * the protocol's, then skip. */
    1738      454980 :                         if ((se->aid.tls_sem & tls_sig_sem) == 0)
    1739       35524 :                                 continue;
    1740      419456 :                         priority_cache->sigalg.entry[priority_cache->sigalg.size++] = se;
    1741             :                 }
    1742             :         }
    1743             : 
    1744       23346 :         _gnutls_debug_log("added %d protocols, %d ciphersuites, %d sig algos and %d groups into priority list\n",
    1745             :                           priority_cache->protocol.num_priorities,
    1746             :                           priority_cache->cs.size, priority_cache->sigalg.size,
    1747             :                           priority_cache->groups.size);
    1748             : 
    1749       23346 :         if (priority_cache->sigalg.size == 0) {
    1750             :                 /* no signature algorithms; eliminate TLS 1.2 or DTLS 1.2 and later */
    1751          11 :                 priority_st newp;
    1752          11 :                 newp.num_priorities = 0;
    1753             : 
    1754             :                 /* we need to eliminate TLS 1.2 or DTLS 1.2 and later protocols */
    1755          26 :                 for (i = 0; i < priority_cache->protocol.num_priorities; i++) {
    1756          15 :                         if (priority_cache->protocol.priorities[i] < GNUTLS_TLS1_2) {
    1757           1 :                                 newp.priorities[newp.num_priorities++] = priority_cache->protocol.priorities[i];
    1758          14 :                         } else if (priority_cache->protocol.priorities[i] >= GNUTLS_DTLS_VERSION_MIN &&
    1759             :                                    priority_cache->protocol.priorities[i] < GNUTLS_DTLS1_2) {
    1760           8 :                                 newp.priorities[newp.num_priorities++] = priority_cache->protocol.priorities[i];
    1761             :                         }
    1762             :                 }
    1763          11 :                 memcpy(&priority_cache->protocol, &newp, sizeof(newp));
    1764             :         }
    1765             : 
    1766       23346 :         if (unlikely(priority_cache->protocol.num_priorities == 0))
    1767           3 :                 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
    1768             : #ifndef ENABLE_SSL3
    1769       23343 :         else if (unlikely(priority_cache->protocol.num_priorities == 1 && priority_cache->protocol.priorities[0] == GNUTLS_SSL3))
    1770           0 :                 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
    1771             : #endif
    1772             : 
    1773       23343 :         if (unlikely(priority_cache->cs.size == 0))
    1774           4 :                 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
    1775             : 
    1776             :         /* when TLS 1.3 is available we must have groups set; additionally
    1777             :          * we require TLS1.2 to be enabled if TLS1.3 is asked for, and
    1778             :          * a pre-TLS1.2 protocol is there; that is because servers which
    1779             :          * do not support TLS1.3 will negotiate TLS1.2 if seen a TLS1.3 handshake */
    1780       23339 :         if (unlikely((!have_psk && tlsmax && tlsmax->id >= GNUTLS_TLS1_3 && priority_cache->groups.size == 0)) ||
    1781       23334 :             (!have_tls12 && have_pre_tls12 && have_tls13)) {
    1782          35 :                 for (i = j = 0; i < priority_cache->protocol.num_priorities; i++) {
    1783          28 :                         vers = version_to_entry(priority_cache->protocol.priorities[i]);
    1784          28 :                         if (!vers || vers->transport != GNUTLS_STREAM || !vers->tls13_sem)
    1785          21 :                                 priority_cache->protocol.priorities[j++] = priority_cache->protocol.priorities[i];
    1786             :                 }
    1787           7 :                 priority_cache->protocol.num_priorities = j;
    1788             :         }
    1789             : 
    1790             :         /* ensure that the verification profile is not lower from the configured */
    1791       23339 :         if (system_wide_verification_profile) {
    1792           4 :                 gnutls_sec_param_t level = priority_cache->level;
    1793           4 :                 gnutls_sec_param_t system_wide_level = _gnutls_profile_to_sec_level(system_wide_verification_profile);
    1794             : 
    1795           4 :                 if (level < system_wide_level) {
    1796           3 :                         ENABLE_PROFILE(priority_cache, system_wide_verification_profile);
    1797             :                 }
    1798             :         }
    1799             : 
    1800             :         return 0;
    1801             : }
    1802             : 
    1803             : /**
    1804             :  * gnutls_priority_init2:
    1805             :  * @priority_cache: is a #gnutls_prioritity_t type.
    1806             :  * @priorities: is a string describing priorities (may be %NULL)
    1807             :  * @err_pos: In case of an error this will have the position in the string the error occurred
    1808             :  * @flags: zero or %GNUTLS_PRIORITY_INIT_DEF_APPEND
    1809             :  *
    1810             :  * Sets priorities for the ciphers, key exchange methods, and macs.
    1811             :  * The @priority_cache should be deinitialized
    1812             :  * using gnutls_priority_deinit().
    1813             :  *
    1814             :  * The #priorities option allows you to specify a colon
    1815             :  * separated list of the cipher priorities to enable.
    1816             :  * Some keywords are defined to provide quick access
    1817             :  * to common preferences.
    1818             :  *
    1819             :  * When @flags is set to %GNUTLS_PRIORITY_INIT_DEF_APPEND then the @priorities
    1820             :  * specified will be appended to the default options.
    1821             :  *
    1822             :  * Unless there is a special need, use the "NORMAL" keyword to
    1823             :  * apply a reasonable security level, or "NORMAL:%%COMPAT" for compatibility.
    1824             :  *
    1825             :  * "PERFORMANCE" means all the "secure" ciphersuites are enabled,
    1826             :  * limited to 128 bit ciphers and sorted by terms of speed
    1827             :  * performance.
    1828             :  *
    1829             :  * "LEGACY" the NORMAL settings for GnuTLS 3.2.x or earlier. There is
    1830             :  * no verification profile set, and the allowed DH primes are considered
    1831             :  * weak today.
    1832             :  *
    1833             :  * "NORMAL" means all "secure" ciphersuites. The 256-bit ciphers are
    1834             :  * included as a fallback only.  The ciphers are sorted by security
    1835             :  * margin.
    1836             :  *
    1837             :  * "PFS" means all "secure" ciphersuites that support perfect forward secrecy.
    1838             :  * The 256-bit ciphers are included as a fallback only.
    1839             :  * The ciphers are sorted by security margin.
    1840             :  *
    1841             :  * "SECURE128" means all "secure" ciphersuites of security level 128-bit
    1842             :  * or more.
    1843             :  *
    1844             :  * "SECURE192" means all "secure" ciphersuites of security level 192-bit
    1845             :  * or more.
    1846             :  *
    1847             :  * "SUITEB128" means all the NSA SuiteB ciphersuites with security level
    1848             :  * of 128.
    1849             :  *
    1850             :  * "SUITEB192" means all the NSA SuiteB ciphersuites with security level
    1851             :  * of 192.
    1852             :  *
    1853             :  * "NONE" means nothing is enabled.  This disables everything, including protocols.
    1854             :  *
    1855             :  * "@@KEYWORD1,KEYWORD2,..." The system administrator imposed settings.
    1856             :  * The provided keyword(s) will be expanded from a configuration-time
    1857             :  * provided file - default is: /etc/gnutls/config.
    1858             :  * Any attributes that follow it, will be appended to the expanded
    1859             :  * string. If multiple keywords are provided, separated by commas,
    1860             :  * then the first keyword that exists in the configuration file
    1861             :  * will be used. At least one of the keywords must exist, or this
    1862             :  * function will return an error. Typical usage would be to specify
    1863             :  * an application specified keyword first, followed by "SYSTEM" as
    1864             :  * a default fallback. e.g., "@LIBVIRT,SYSTEM:!-VERS-SSL3.0" will
    1865             :  * first try to find a config file entry matching "LIBVIRT", but if
    1866             :  * that does not exist will use the entry for "SYSTEM". If "SYSTEM"
    1867             :  * does not exist either, an error will be returned. In all cases,
    1868             :  * the SSL3.0 protocol will be disabled. The system priority file
    1869             :  * entries should be formatted as "KEYWORD=VALUE", e.g.,
    1870             :  * "SYSTEM=NORMAL:+ARCFOUR-128".
    1871             :  *
    1872             :  * Special keywords are "!", "-" and "+".
    1873             :  * "!" or "-" appended with an algorithm will remove this algorithm.
    1874             :  * "+" appended with an algorithm will add this algorithm.
    1875             :  *
    1876             :  * Check the GnuTLS manual section "Priority strings" for detailed
    1877             :  * information.
    1878             :  *
    1879             :  * Examples:
    1880             :  *
    1881             :  * "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"
    1882             :  *
    1883             :  * "NORMAL:+ARCFOUR-128" means normal ciphers plus ARCFOUR-128.
    1884             :  *
    1885             :  * "SECURE128:-VERS-SSL3.0" means that only secure ciphers are
    1886             :  * and enabled, SSL3.0 is disabled.
    1887             :  *
    1888             :  * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1",
    1889             :  *
    1890             :  * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+ECDHE-RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1:+CURVE-SECP256R1",
    1891             :  *
    1892             :  * "SECURE256:+SECURE128",
    1893             :  *
    1894             :  * Note that "NORMAL:%%COMPAT" is the most compatible mode.
    1895             :  *
    1896             :  * A %NULL @priorities string indicates the default priorities to be
    1897             :  * used (this is available since GnuTLS 3.3.0).
    1898             :  *
    1899             :  * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
    1900             :  * %GNUTLS_E_SUCCESS on success, or an error code.
    1901             :  *
    1902             :  * Since: 3.6.3
    1903             :  **/
    1904             : int
    1905          12 : gnutls_priority_init2(gnutls_priority_t * priority_cache,
    1906             :                       const char *priorities, const char **err_pos,
    1907             :                       unsigned flags)
    1908             : {
    1909          12 :         gnutls_buffer_st buf;
    1910          12 :         const char *ep;
    1911          12 :         int ret;
    1912             : 
    1913          12 :         if (flags & GNUTLS_PRIORITY_INIT_DEF_APPEND) {
    1914          12 :                 if (priorities == NULL)
    1915           0 :                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    1916             : 
    1917          12 :                 if (err_pos)
    1918          12 :                         *err_pos = priorities;
    1919             : 
    1920          12 :                 _gnutls_buffer_init(&buf);
    1921             : 
    1922          12 :                 ret = _gnutls_buffer_append_str(&buf, _gnutls_default_priority_string);
    1923          12 :                 if (ret < 0) {
    1924           0 :                         _gnutls_buffer_clear(&buf);
    1925           0 :                         return gnutls_assert_val(ret);
    1926             :                 }
    1927             : 
    1928          12 :                 ret = _gnutls_buffer_append_str(&buf, ":");
    1929          12 :                 if (ret < 0) {
    1930           0 :                         _gnutls_buffer_clear(&buf);
    1931           0 :                         return gnutls_assert_val(ret);
    1932             :                 }
    1933             : 
    1934          12 :                 ret = _gnutls_buffer_append_str(&buf, priorities);
    1935          12 :                 if (ret < 0) {
    1936           0 :                         _gnutls_buffer_clear(&buf);
    1937           0 :                         return gnutls_assert_val(ret);
    1938             :                 }
    1939             : 
    1940          12 :                 ret = gnutls_priority_init(priority_cache, (const char*)buf.data, &ep);
    1941          12 :                 if (ret < 0 && ep != (const char*)buf.data && ep != NULL) {
    1942           6 :                         ptrdiff_t diff = (ptrdiff_t)ep-(ptrdiff_t)buf.data;
    1943           6 :                         unsigned hlen = strlen(_gnutls_default_priority_string)+1;
    1944             : 
    1945           6 :                         if (err_pos && diff > hlen) {
    1946           4 :                                 *err_pos = priorities + diff - hlen;
    1947             :                         }
    1948             :                 }
    1949          12 :                 _gnutls_buffer_clear(&buf);
    1950          12 :                 return ret;
    1951             :         } else {
    1952           0 :                 return gnutls_priority_init(priority_cache, priorities, err_pos);
    1953             :         }
    1954             : }
    1955             : 
    1956             : #define PRIO_MATCH(name) c_strncasecmp(&broken_list[i][1], name, sizeof(name) - 1)
    1957             : 
    1958             : /**
    1959             :  * gnutls_priority_init:
    1960             :  * @priority_cache: is a #gnutls_prioritity_t type.
    1961             :  * @priorities: is a string describing priorities (may be %NULL)
    1962             :  * @err_pos: In case of an error this will have the position in the string the error occurred
    1963             :  *
    1964             :  * For applications that do not modify their crypto settings per release, consider
    1965             :  * using gnutls_priority_init2() with %GNUTLS_PRIORITY_INIT_DEF_APPEND flag
    1966             :  * instead. We suggest to use centralized crypto settings handled by the GnuTLS
    1967             :  * library, and applications modifying the default settings to their needs.
    1968             :  *
    1969             :  * This function is identical to gnutls_priority_init2() with zero
    1970             :  * flags.
    1971             :  *
    1972             :  * A %NULL @priorities string indicates the default priorities to be
    1973             :  * used (this is available since GnuTLS 3.3.0).
    1974             :  *
    1975             :  * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
    1976             :  * %GNUTLS_E_SUCCESS on success, or an error code.
    1977             :  **/
    1978             : int
    1979       23361 : gnutls_priority_init(gnutls_priority_t * priority_cache,
    1980             :                      const char *priorities, const char **err_pos)
    1981             : {
    1982       23361 :         char *broken_list[MAX_ELEMENTS];
    1983       23361 :         int broken_list_size = 0, i = 0, j;
    1984       23361 :         char *darg = NULL;
    1985       23361 :         unsigned ikeyword_set = 0;
    1986       23361 :         int algo;
    1987       23361 :         int ret;
    1988       23361 :         rmadd_func *fn;
    1989       23361 :         bulk_rmadd_func *bulk_fn;
    1990       23361 :         bulk_rmadd_func *bulk_given_fn;
    1991       23361 :         const cipher_entry_st *centry;
    1992       23361 :         unsigned resolved_match = 1;
    1993             : 
    1994       23361 :         if (err_pos)
    1995       11125 :                 *err_pos = priorities;
    1996             : 
    1997       46722 :         *priority_cache =
    1998       23361 :             gnutls_calloc(1, sizeof(struct gnutls_priority_st));
    1999       23361 :         if (*priority_cache == NULL) {
    2000           0 :                 gnutls_assert();
    2001           0 :                 return GNUTLS_E_MEMORY_ERROR;
    2002             :         }
    2003             : 
    2004             :         /* for now unsafe renegotiation is default on everyone. To be removed
    2005             :          * when we make it the default.
    2006             :          */
    2007       23361 :         (*priority_cache)->sr = SR_PARTIAL;
    2008       23361 :         (*priority_cache)->min_record_version = 1;
    2009       23361 :         gnutls_atomic_init(&(*priority_cache)->usage_cnt);
    2010             : 
    2011       23361 :         if (priorities == NULL) {
    2012         154 :                 priorities = _gnutls_default_priority_string;
    2013         154 :                 resolved_match = 0;
    2014             :         }
    2015             : 
    2016       23361 :         darg = _gnutls_resolve_priorities(priorities);
    2017       23361 :         if (darg == NULL) {
    2018           2 :                 gnutls_assert();
    2019           2 :                 goto error;
    2020             :         }
    2021             : 
    2022       23359 :         if (strcmp(darg, priorities) != 0)
    2023           0 :                 resolved_match = 0;
    2024             : 
    2025       23359 :         break_list(darg, broken_list, &broken_list_size);
    2026             :         /* This is our default set of protocol version, certificate types.
    2027             :          */
    2028       23359 :         if (c_strcasecmp(broken_list[0], LEVEL_NONE) != 0) {
    2029       19937 :                 _set_priority(&(*priority_cache)->protocol,
    2030             :                               protocol_priority);
    2031       19937 :                 _set_priority(&(*priority_cache)->client_ctype,
    2032             :                               cert_type_priority_default);
    2033       19937 :                 _set_priority(&(*priority_cache)->server_ctype,
    2034             :                               cert_type_priority_default);
    2035       19937 :                 _set_priority(&(*priority_cache)->_sign_algo,
    2036             :                               sign_priority_default);
    2037       19937 :                 _set_priority(&(*priority_cache)->_supported_ecc,
    2038             :                               supported_groups_normal);
    2039             :                 i = 0;
    2040             :         } else {
    2041             :                 ikeyword_set = 1;
    2042             :                 i = 1;
    2043             :         }
    2044             : 
    2045      232433 :         for (; i < broken_list_size; i++) {
    2046      209086 :                 if (check_level(broken_list[i], *priority_cache, ikeyword_set) != 0) {
    2047       19937 :                         ikeyword_set = 1;
    2048       19937 :                         continue;
    2049      189149 :                 } else if (broken_list[i][0] == '!'
    2050      189149 :                            || broken_list[i][0] == '+'
    2051       29447 :                            || broken_list[i][0] == '-') {
    2052      182181 :                         if (broken_list[i][0] == '+') {
    2053             :                                 fn = prio_add;
    2054             :                                 bulk_fn = _add_priority;
    2055             :                                 bulk_given_fn = _add_priority;
    2056             :                         } else {
    2057       22479 :                                 fn = prio_remove;
    2058       22479 :                                 bulk_fn = _clear_priorities;
    2059       22479 :                                 bulk_given_fn = _clear_given_priorities;
    2060             :                         }
    2061             : 
    2062      182181 :                         if (broken_list[i][0] == '+'
    2063      159702 :                             && check_level(&broken_list[i][1],
    2064             :                                            *priority_cache, 1) != 0) {
    2065           3 :                                 continue;
    2066      182178 :                         } else if ((algo =
    2067      182178 :                                     gnutls_mac_get_id(&broken_list[i][1]))
    2068             :                                    != GNUTLS_MAC_UNKNOWN) {
    2069        8335 :                                 fn(&(*priority_cache)->_mac, algo);
    2070      173843 :                         } else if ((centry = cipher_name_to_entry(&broken_list[i][1])) != NULL) {
    2071       38852 :                                 if (_gnutls_cipher_exists(centry->id)) {
    2072       38851 :                                         fn(&(*priority_cache)->_cipher, centry->id);
    2073       38851 :                                         if (centry->type == CIPHER_BLOCK)
    2074        6539 :                                                 (*priority_cache)->have_cbc = 1;
    2075             :                                 }
    2076      269982 :                         } else if ((algo =
    2077      134991 :                                   _gnutls_kx_get_id(&broken_list[i][1])) !=
    2078             :                                  GNUTLS_KX_UNKNOWN) {
    2079       26149 :                                 if (algo != GNUTLS_KX_INVALID)
    2080       26148 :                                         fn(&(*priority_cache)->_kx, algo);
    2081      108842 :                         } else if (PRIO_MATCH("VERS-") == 0) {
    2082       70108 :                                 if (PRIO_MATCH("VERS-TLS-ALL") == 0) {
    2083         282 :                                         bulk_given_fn(&(*priority_cache)->
    2084             :                                                 protocol,
    2085             :                                                 stream_protocol_priority);
    2086       69826 :                                 } else if (PRIO_MATCH("VERS-DTLS-ALL") == 0) {
    2087           9 :                                         bulk_given_fn(&(*priority_cache)->
    2088             :                                                 protocol,
    2089             :                                                 (bulk_given_fn==_add_priority)?dtls_protocol_priority:dgram_protocol_priority);
    2090       69818 :                                 } else if (PRIO_MATCH("VERS-ALL") == 0) {
    2091       15046 :                                         bulk_fn(&(*priority_cache)->
    2092             :                                                 protocol,
    2093             :                                                 protocol_priority);
    2094             :                                 } else {
    2095       54772 :                                         if ((algo =
    2096       54772 :                                              gnutls_protocol_get_id
    2097       54772 :                                              (&broken_list[i][6])) !=
    2098             :                                             GNUTLS_VERSION_UNKNOWN) {
    2099       54772 :                                                 fn(&(*priority_cache)->
    2100             :                                                    protocol, algo);
    2101             :                                         } else
    2102           0 :                                                 goto error;
    2103             : 
    2104             :                                 }
    2105             :                         } /* now check if the element is something like -ALGO */
    2106       38734 :                         else if (PRIO_MATCH("COMP-") == 0) {
    2107             :                                 /* ignore all compression methods */
    2108        3402 :                                 continue;
    2109             :                         } /* now check if the element is something like -ALGO */
    2110       35332 :                         else if (PRIO_MATCH("CURVE-") == 0) {
    2111        3251 :                                 if (PRIO_MATCH("CURVE-ALL") == 0) {
    2112        2949 :                                         bulk_fn(&(*priority_cache)->
    2113             :                                                 _supported_ecc,
    2114             :                                                 supported_groups_normal);
    2115             :                                 } else {
    2116         302 :                                         if ((algo =
    2117         302 :                                              gnutls_ecc_curve_get_id
    2118         302 :                                              (&broken_list[i][7])) !=
    2119             :                                             GNUTLS_ECC_CURVE_INVALID)
    2120         297 :                                                 fn(&(*priority_cache)->
    2121             :                                                    _supported_ecc, algo);
    2122             :                                         else
    2123           5 :                                                 goto error;
    2124             :                                 }
    2125       32081 :                         } else if (PRIO_MATCH("GROUP-") == 0) {
    2126        1971 :                                 if (PRIO_MATCH("GROUP-ALL") == 0) {
    2127         757 :                                         bulk_fn(&(*priority_cache)->
    2128             :                                                 _supported_ecc,
    2129             :                                                 supported_groups_normal);
    2130        1214 :                                 } else if (PRIO_MATCH("GROUP-DH-ALL") == 0) {
    2131         450 :                                         bulk_given_fn(&(*priority_cache)->
    2132             :                                                 _supported_ecc,
    2133             :                                                 _supported_groups_dh);
    2134         764 :                                 } else if (PRIO_MATCH("GROUP-EC-ALL") == 0) {
    2135         198 :                                         bulk_given_fn(&(*priority_cache)->
    2136             :                                                 _supported_ecc,
    2137             :                                                 _supported_groups_ecdh);
    2138         566 :                                 } else if (PRIO_MATCH("GROUP-GOST-ALL") == 0) {
    2139         299 :                                         bulk_given_fn(&(*priority_cache)->
    2140             :                                                 _supported_ecc,
    2141             :                                                 _supported_groups_gost);
    2142             :                                 } else {
    2143         267 :                                         if ((algo =
    2144         267 :                                              gnutls_group_get_id
    2145         267 :                                              (&broken_list[i][7])) !=
    2146             :                                             GNUTLS_GROUP_INVALID)
    2147         267 :                                                 fn(&(*priority_cache)->
    2148             :                                                    _supported_ecc, algo);
    2149             :                                         else
    2150           0 :                                                 goto error;
    2151             :                                 }
    2152       30110 :                         } else if (PRIO_MATCH("CTYPE-") == 0) {
    2153             :                                 // Certificate types
    2154         205 :                                 if (PRIO_MATCH("CTYPE-ALL") == 0) {
    2155             :                                         // Symmetric cert types, all types allowed
    2156         106 :                                         bulk_fn(&(*priority_cache)->client_ctype,
    2157             :                                                 cert_type_priority_all);
    2158         106 :                                         bulk_fn(&(*priority_cache)->server_ctype,
    2159             :                                                 cert_type_priority_all);
    2160          99 :                                 } else if (PRIO_MATCH("CTYPE-CLI-") == 0) {
    2161             :                                         // Client certificate types
    2162          43 :                                         if (PRIO_MATCH("CTYPE-CLI-ALL") == 0) {
    2163             :                                                 // All client cert types allowed
    2164          17 :                                                 bulk_fn(&(*priority_cache)->client_ctype,
    2165             :                                                         cert_type_priority_all);
    2166          26 :                                         } else if ((algo = gnutls_certificate_type_get_id
    2167          26 :                                                         (&broken_list[i][11])) != GNUTLS_CRT_UNKNOWN) {
    2168             :                                                 // Specific client cert type allowed
    2169          26 :                                                 fn(&(*priority_cache)->client_ctype, algo);
    2170           0 :                                         } else goto error;
    2171          56 :                                 } else if (PRIO_MATCH("CTYPE-SRV-") == 0) {
    2172             :                                         // Server certificate types
    2173          44 :                                         if (PRIO_MATCH("CTYPE-SRV-ALL") == 0) {
    2174             :                                                 // All server cert types allowed
    2175          14 :                                                 bulk_fn(&(*priority_cache)->server_ctype,
    2176             :                                                         cert_type_priority_all);
    2177          30 :                                         } else if ((algo = gnutls_certificate_type_get_id
    2178          30 :                                                         (&broken_list[i][11])) != GNUTLS_CRT_UNKNOWN) {
    2179             :                                                         // Specific server cert type allowed
    2180          30 :                                                 fn(&(*priority_cache)->server_ctype, algo);
    2181           0 :                                         } else goto error;
    2182             :                                 } else { // Symmetric certificate type
    2183          12 :                                         if ((algo = gnutls_certificate_type_get_id
    2184          12 :                                              (&broken_list[i][7])) != GNUTLS_CRT_UNKNOWN) {
    2185          10 :                                                 fn(&(*priority_cache)->client_ctype, algo);
    2186          10 :                                                 fn(&(*priority_cache)->server_ctype, algo);
    2187           2 :                                         } else if (PRIO_MATCH("CTYPE-OPENPGP") == 0) {
    2188             :                                                 /* legacy openpgp option - ignore */
    2189           2 :                                                 continue;
    2190           0 :                                         } else goto error;
    2191             :                                 }
    2192       29905 :                         } else if (PRIO_MATCH("SIGN-") == 0) {
    2193       17960 :                                 if (PRIO_MATCH("SIGN-ALL") == 0) {
    2194        3468 :                                         bulk_fn(&(*priority_cache)->
    2195             :                                                 _sign_algo,
    2196             :                                                 sign_priority_default);
    2197       14492 :                                 } else if (PRIO_MATCH("SIGN-GOST-ALL") == 0) {
    2198          40 :                                         bulk_fn(&(*priority_cache)->
    2199             :                                                 _sign_algo,
    2200             :                                                 sign_priority_gost);
    2201             :                                 } else {
    2202       14452 :                                         if ((algo =
    2203       14452 :                                              gnutls_sign_get_id
    2204       14452 :                                              (&broken_list[i][6])) !=
    2205             :                                             GNUTLS_SIGN_UNKNOWN)
    2206       14452 :                                                 fn(&(*priority_cache)->
    2207             :                                                    _sign_algo, algo);
    2208             :                                         else
    2209           0 :                                                 goto error;
    2210             :                                 }
    2211       11945 :                         } else if (PRIO_MATCH("MAC-") == 0) {
    2212        3194 :                                 if (PRIO_MATCH("MAC-ALL") == 0) {
    2213        3152 :                                         bulk_fn(&(*priority_cache)->_mac,
    2214             :                                                         mac_priority_normal);
    2215          42 :                                 } else if (PRIO_MATCH("MAC-GOST-ALL") == 0) {
    2216          42 :                                         bulk_fn(&(*priority_cache)->_mac,
    2217             :                                                         mac_priority_gost);
    2218             :                                 }
    2219        8751 :                         } else if (PRIO_MATCH("CIPHER-") == 0) {
    2220        4065 :                                 if (PRIO_MATCH("CIPHER-ALL") == 0) {
    2221        4023 :                                         bulk_fn(&(*priority_cache)->_cipher,
    2222             :                                                         cipher_priority_normal);
    2223          42 :                                 } else if (PRIO_MATCH("CIPHER-GOST-ALL") == 0) {
    2224          42 :                                         bulk_fn(&(*priority_cache)->_cipher,
    2225             :                                                         cipher_priority_gost);
    2226             :                                 }
    2227        4686 :                         } else if (PRIO_MATCH("KX-") == 0) {
    2228        4631 :                                 if (PRIO_MATCH("KX-ALL") == 0) {
    2229        4631 :                                         bulk_fn(&(*priority_cache)->_kx,
    2230             :                                                         kx_priority_secure);
    2231           0 :                                 } else if (PRIO_MATCH("KX-GOST-ALL") == 0) {
    2232           0 :                                         bulk_fn(&(*priority_cache)->_kx,
    2233             :                                                         kx_priority_gost);
    2234             :                                 }
    2235          55 :                         } else if (PRIO_MATCH("GOST") == 0) {
    2236          54 :                                 bulk_given_fn(&(*priority_cache)->_supported_ecc,
    2237             :                                         _supported_groups_gost);
    2238          54 :                                 bulk_fn(&(*priority_cache)->_sign_algo,
    2239             :                                         sign_priority_gost);
    2240          54 :                                 bulk_fn(&(*priority_cache)->_mac,
    2241             :                                                 mac_priority_gost);
    2242          54 :                                 bulk_fn(&(*priority_cache)->_cipher,
    2243             :                                                 cipher_priority_gost);
    2244          54 :                                 bulk_fn(&(*priority_cache)->_kx,
    2245             :                                                 kx_priority_gost);
    2246             :                         } else
    2247           1 :                                 goto error;
    2248        6968 :                 } else if (broken_list[i][0] == '%') {
    2249        6964 :                         const struct priority_options_st * o;
    2250             :                         /* to add a new option modify
    2251             :                          * priority_options.gperf */
    2252        6964 :                         o = in_word_set(&broken_list[i][1], strlen(&broken_list[i][1]));
    2253        6964 :                         if (o == NULL) {
    2254           2 :                                 goto error;
    2255             :                         }
    2256        6962 :                         o->func(*priority_cache);
    2257             :                 } else
    2258           4 :                         goto error;
    2259             :         }
    2260             : 
    2261       23347 :         ret = set_ciphersuite_list(*priority_cache);
    2262       23347 :         if (ret < 0) {
    2263           8 :                 if (err_pos)
    2264           4 :                         *err_pos = priorities;
    2265           8 :                 goto error_cleanup;
    2266             :         }
    2267             : 
    2268       23339 :         gnutls_free(darg);
    2269             : 
    2270       23339 :         return 0;
    2271             : 
    2272          14 :  error:
    2273          14 :         if (err_pos != NULL && i < broken_list_size && resolved_match) {
    2274          12 :                 *err_pos = priorities;
    2275          56 :                 for (j = 0; j < i; j++) {
    2276          44 :                         (*err_pos) += strlen(broken_list[j]) + 1;
    2277             :                 }
    2278             :         }
    2279             :         ret = GNUTLS_E_INVALID_REQUEST;
    2280             : 
    2281          22 :  error_cleanup:
    2282          22 :         free(darg);
    2283          22 :         gnutls_priority_deinit(*priority_cache);
    2284          22 :         *priority_cache = NULL;
    2285             : 
    2286          22 :         return ret;
    2287             : }
    2288             : 
    2289             : /**
    2290             :  * gnutls_priority_deinit:
    2291             :  * @priority_cache: is a #gnutls_prioritity_t type.
    2292             :  *
    2293             :  * Deinitializes the priority cache.
    2294             :  **/
    2295       46602 : void gnutls_priority_deinit(gnutls_priority_t priority_cache)
    2296             : {
    2297       46602 :         if (priority_cache == NULL)
    2298             :                 return;
    2299             : 
    2300             :         /* Note that here we care about the following two cases:
    2301             :          * 1. Multiple sessions or different threads holding a reference + a global reference
    2302             :          * 2. One session holding a reference with a possible global reference
    2303             :          *
    2304             :          * As such, it will never be that two threads reach the
    2305             :          * zero state at the same time, unless the global reference
    2306             :          * is cleared too, which is invalid state.
    2307             :          */
    2308       46581 :         if (gnutls_atomic_val(&priority_cache->usage_cnt) == 0) {
    2309       23270 :                 gnutls_atomic_deinit(&priority_cache->usage_cnt);
    2310       23270 :                 gnutls_free(priority_cache);
    2311       23270 :                 return;
    2312             :         } else {
    2313       23311 :                 gnutls_atomic_decrement(&priority_cache->usage_cnt);
    2314             :         }
    2315             : }
    2316             : 
    2317             : 
    2318             : /**
    2319             :  * gnutls_priority_set_direct:
    2320             :  * @session: is a #gnutls_session_t type.
    2321             :  * @priorities: is a string describing priorities
    2322             :  * @err_pos: In case of an error this will have the position in the string the error occurred
    2323             :  *
    2324             :  * Sets the priorities to use on the ciphers, key exchange methods,
    2325             :  * and macs.  This function avoids keeping a
    2326             :  * priority cache and is used to directly set string priorities to a
    2327             :  * TLS session.  For documentation check the gnutls_priority_init().
    2328             :  *
    2329             :  * To use a reasonable default, consider using gnutls_set_default_priority(),
    2330             :  * or gnutls_set_default_priority_append() instead of this function.
    2331             :  *
    2332             :  * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
    2333             :  * %GNUTLS_E_SUCCESS on success, or an error code.
    2334             :  **/
    2335             : int
    2336       23310 : gnutls_priority_set_direct(gnutls_session_t session,
    2337             :                            const char *priorities, const char **err_pos)
    2338             : {
    2339       23310 :         gnutls_priority_t prio;
    2340       23310 :         int ret;
    2341             : 
    2342       23310 :         ret = gnutls_priority_init(&prio, priorities, err_pos);
    2343       23310 :         if (ret < 0) {
    2344           7 :                 gnutls_assert();
    2345           7 :                 return ret;
    2346             :         }
    2347             : 
    2348       23303 :         ret = gnutls_priority_set(session, prio);
    2349       23303 :         if (ret < 0) {
    2350           0 :                 gnutls_assert();
    2351           0 :                 return ret;
    2352             :         }
    2353             : 
    2354             :         /* ensure that the session holds the only reference for the struct */
    2355       23303 :         gnutls_priority_deinit(prio);
    2356             : 
    2357       23303 :         return 0;
    2358             : }
    2359             : 
    2360             : /* Breaks a list of "xxx", "yyy", to a character array, of
    2361             :  * MAX_COMMA_SEP_ELEMENTS size; Note that the given string is modified.
    2362             :   */
    2363             : static void
    2364       23359 : break_list(char *list,
    2365             :                  char *broken_list[MAX_ELEMENTS], int *size)
    2366             : {
    2367       23359 :         char *p = list;
    2368             : 
    2369       23359 :         *size = 0;
    2370             : 
    2371      212535 :         do {
    2372      212535 :                 broken_list[*size] = p;
    2373             : 
    2374      212535 :                 (*size)++;
    2375             : 
    2376      212535 :                 p = strchr(p, ':');
    2377      212535 :                 if (p) {
    2378      189176 :                         *p = 0;
    2379      189176 :                         p++;    /* move to next entry and skip white
    2380             :                                  * space.
    2381             :                                  */
    2382      189176 :                         while (*p == ' ')
    2383           0 :                                 p++;
    2384             :                 }
    2385             :         }
    2386      212535 :         while (p != NULL && *size < MAX_ELEMENTS);
    2387       23359 : }
    2388             : 
    2389             : /**
    2390             :  * gnutls_set_default_priority:
    2391             :  * @session: is a #gnutls_session_t type.
    2392             :  *
    2393             :  * Sets the default priority on the ciphers, key exchange methods,
    2394             :  * and macs. This is the recommended method of
    2395             :  * setting the defaults, in order to promote consistency between applications
    2396             :  * using GnuTLS, and to allow GnuTLS using applications to update settings
    2397             :  * in par with the library. For client applications which require
    2398             :  * maximum compatibility consider calling gnutls_session_enable_compatibility_mode()
    2399             :  * after this function.
    2400             :  *
    2401             :  * For an application to specify additional options to priority string
    2402             :  * consider using gnutls_set_default_priority_append().
    2403             :  *
    2404             :  * To allow a user to override the defaults (e.g., when a user interface
    2405             :  * or configuration file is available), the functions
    2406             :  * gnutls_priority_set_direct() or gnutls_priority_set() can
    2407             :  * be used.
    2408             :  *
    2409             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
    2410             :  *
    2411             :  * Since: 2.1.4
    2412             :  **/
    2413         151 : int gnutls_set_default_priority(gnutls_session_t session)
    2414             : {
    2415         151 :         return gnutls_priority_set_direct(session, NULL, NULL);
    2416             : }
    2417             : 
    2418             : /**
    2419             :  * gnutls_set_default_priority_append:
    2420             :  * @session: is a #gnutls_session_t type.
    2421             :  * @add_prio: is a string describing priorities to be appended to default
    2422             :  * @err_pos: In case of an error this will have the position in the string the error occurred
    2423             :  * @flags: must be zero
    2424             :  *
    2425             :  * Sets the default priority on the ciphers, key exchange methods,
    2426             :  * and macs with the additional options in @add_prio. This is the recommended method of
    2427             :  * setting the defaults when only few additional options are to be added. This promotes
    2428             :  * consistency between applications using GnuTLS, and allows GnuTLS using applications
    2429             :  * to update settings in par with the library.
    2430             :  *
    2431             :  * The @add_prio string should start as a normal priority string, e.g.,
    2432             :  * '-VERS-TLS-ALL:+VERS-TLS1.3:%%COMPAT' or '%%FORCE_ETM'. That is, it must not start
    2433             :  * with ':'.
    2434             :  *
    2435             :  * To allow a user to override the defaults (e.g., when a user interface
    2436             :  * or configuration file is available), the functions
    2437             :  * gnutls_priority_set_direct() or gnutls_priority_set() can
    2438             :  * be used.
    2439             :  *
    2440             :  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
    2441             :  *
    2442             :  * Since: 3.6.3
    2443             :  **/
    2444           6 : int gnutls_set_default_priority_append(gnutls_session_t session,
    2445             :                                        const char *add_prio,
    2446             :                                        const char **err_pos,
    2447             :                                        unsigned flags)
    2448             : {
    2449           6 :         gnutls_priority_t prio;
    2450           6 :         int ret;
    2451             : 
    2452           6 :         ret = gnutls_priority_init2(&prio, add_prio, err_pos, GNUTLS_PRIORITY_INIT_DEF_APPEND);
    2453           6 :         if (ret < 0) {
    2454           4 :                 gnutls_assert();
    2455           4 :                 return ret;
    2456             :         }
    2457             : 
    2458           2 :         ret = gnutls_priority_set(session, prio);
    2459           2 :         if (ret < 0) {
    2460           0 :                 gnutls_assert();
    2461           0 :                 return ret;
    2462             :         }
    2463             : 
    2464             :         /* ensure that the session holds the only reference for the struct */
    2465           2 :         gnutls_priority_deinit(prio);
    2466             : 
    2467           2 :         return 0;
    2468             : }
    2469             : 
    2470             : /**
    2471             :  * gnutls_priority_ecc_curve_list:
    2472             :  * @pcache: is a #gnutls_prioritity_t type.
    2473             :  * @list: will point to an integer list
    2474             :  *
    2475             :  * Get a list of available elliptic curves in the priority
    2476             :  * structure.
    2477             :  *
    2478             :  * Deprecated: This function has been replaced by
    2479             :  * gnutls_priority_group_list() since 3.6.0.
    2480             :  *
    2481             :  * Returns: the number of items, or an error code.
    2482             :  *
    2483             :  * Since: 3.0
    2484             :  **/
    2485             : int
    2486           3 : gnutls_priority_ecc_curve_list(gnutls_priority_t pcache,
    2487             :                                const unsigned int **list)
    2488             : {
    2489           3 :         unsigned i;
    2490             : 
    2491           3 :         if (pcache->_supported_ecc.num_priorities == 0)
    2492             :                 return 0;
    2493             : 
    2494           3 :         *list = pcache->_supported_ecc.priorities;
    2495             : 
    2496             :         /* to ensure we don't confuse the caller, we do not include
    2497             :          * any FFDHE groups. This may return an incomplete list. */
    2498           8 :         for (i=0;i<pcache->_supported_ecc.num_priorities;i++)
    2499           7 :                 if (pcache->_supported_ecc.priorities[i] > GNUTLS_ECC_CURVE_MAX)
    2500           2 :                         return i;
    2501             : 
    2502           1 :         return pcache->_supported_ecc.num_priorities;
    2503             : }
    2504             : 
    2505             : /**
    2506             :  * gnutls_priority_group_list:
    2507             :  * @pcache: is a #gnutls_prioritity_t type.
    2508             :  * @list: will point to an integer list
    2509             :  *
    2510             :  * Get a list of available groups in the priority
    2511             :  * structure.
    2512             :  *
    2513             :  * Returns: the number of items, or an error code.
    2514             :  *
    2515             :  * Since: 3.6.0
    2516             :  **/
    2517             : int
    2518          13 : gnutls_priority_group_list(gnutls_priority_t pcache,
    2519             :                                const unsigned int **list)
    2520             : {
    2521          13 :         if (pcache->_supported_ecc.num_priorities == 0)
    2522             :                 return 0;
    2523             : 
    2524           9 :         *list = pcache->_supported_ecc.priorities;
    2525           9 :         return pcache->_supported_ecc.num_priorities;
    2526             : }
    2527             : 
    2528             : /**
    2529             :  * gnutls_priority_kx_list:
    2530             :  * @pcache: is a #gnutls_prioritity_t type.
    2531             :  * @list: will point to an integer list
    2532             :  *
    2533             :  * Get a list of available key exchange methods in the priority
    2534             :  * structure.
    2535             :  *
    2536             :  * Returns: the number of items, or an error code.
    2537             :  * Since: 3.2.3
    2538             :  **/
    2539             : int
    2540          10 : gnutls_priority_kx_list(gnutls_priority_t pcache,
    2541             :                         const unsigned int **list)
    2542             : {
    2543          10 :         if (pcache->_kx.num_priorities == 0)
    2544             :                 return 0;
    2545             : 
    2546          10 :         *list = pcache->_kx.priorities;
    2547          10 :         return pcache->_kx.num_priorities;
    2548             : }
    2549             : 
    2550             : /**
    2551             :  * gnutls_priority_cipher_list:
    2552             :  * @pcache: is a #gnutls_prioritity_t type.
    2553             :  * @list: will point to an integer list
    2554             :  *
    2555             :  * Get a list of available ciphers in the priority
    2556             :  * structure.
    2557             :  *
    2558             :  * Returns: the number of items, or an error code.
    2559             :  * Since: 3.2.3
    2560             :  **/
    2561             : int
    2562          26 : gnutls_priority_cipher_list(gnutls_priority_t pcache,
    2563             :                             const unsigned int **list)
    2564             : {
    2565          26 :         if (pcache->_cipher.num_priorities == 0)
    2566             :                 return 0;
    2567             : 
    2568          26 :         *list = pcache->_cipher.priorities;
    2569          26 :         return pcache->_cipher.num_priorities;
    2570             : }
    2571             : 
    2572             : /**
    2573             :  * gnutls_priority_mac_list:
    2574             :  * @pcache: is a #gnutls_prioritity_t type.
    2575             :  * @list: will point to an integer list
    2576             :  *
    2577             :  * Get a list of available MAC algorithms in the priority
    2578             :  * structure.
    2579             :  *
    2580             :  * Returns: the number of items, or an error code.
    2581             :  * Since: 3.2.3
    2582             :  **/
    2583             : int
    2584          10 : gnutls_priority_mac_list(gnutls_priority_t pcache,
    2585             :                          const unsigned int **list)
    2586             : {
    2587          10 :         if (pcache->_mac.num_priorities == 0)
    2588             :                 return 0;
    2589             : 
    2590          10 :         *list = pcache->_mac.priorities;
    2591          10 :         return pcache->_mac.num_priorities;
    2592             : }
    2593             : 
    2594             : /**
    2595             :  * gnutls_priority_compression_list:
    2596             :  * @pcache: is a #gnutls_prioritity_t type.
    2597             :  * @list: will point to an integer list
    2598             :  *
    2599             :  * Get a list of available compression method in the priority
    2600             :  * structure.
    2601             :  *
    2602             :  * Returns: the number of methods, or an error code.
    2603             :  * Since: 3.0
    2604             :  **/
    2605             : int
    2606           0 : gnutls_priority_compression_list(gnutls_priority_t pcache,
    2607             :                                  const unsigned int **list)
    2608             : {
    2609           0 :         static const unsigned int priority[1] = {GNUTLS_COMP_NULL};
    2610             : 
    2611           0 :         *list = priority;
    2612           0 :         return 1;
    2613             : }
    2614             : 
    2615             : /**
    2616             :  * gnutls_priority_protocol_list:
    2617             :  * @pcache: is a #gnutls_prioritity_t type.
    2618             :  * @list: will point to an integer list
    2619             :  *
    2620             :  * Get a list of available TLS version numbers in the priority
    2621             :  * structure.
    2622             :  *
    2623             :  * Returns: the number of protocols, or an error code.
    2624             :  * Since: 3.0
    2625             :  **/
    2626             : int
    2627          10 : gnutls_priority_protocol_list(gnutls_priority_t pcache,
    2628             :                               const unsigned int **list)
    2629             : {
    2630          10 :         if (pcache->protocol.num_priorities == 0)
    2631             :                 return 0;
    2632             : 
    2633          10 :         *list = pcache->protocol.priorities;
    2634          10 :         return pcache->protocol.num_priorities;
    2635             : }
    2636             : 
    2637             : /**
    2638             :  * gnutls_priority_sign_list:
    2639             :  * @pcache: is a #gnutls_prioritity_t type.
    2640             :  * @list: will point to an integer list
    2641             :  *
    2642             :  * Get a list of available signature algorithms in the priority
    2643             :  * structure.
    2644             :  *
    2645             :  * Returns: the number of algorithms, or an error code.
    2646             :  * Since: 3.0
    2647             :  **/
    2648             : int
    2649          10 : gnutls_priority_sign_list(gnutls_priority_t pcache,
    2650             :                           const unsigned int **list)
    2651             : {
    2652          10 :         if (pcache->_sign_algo.num_priorities == 0)
    2653             :                 return 0;
    2654             : 
    2655          10 :         *list = pcache->_sign_algo.priorities;
    2656          10 :         return pcache->_sign_algo.num_priorities;
    2657             : }
    2658             : 
    2659             : /**
    2660             :  * gnutls_priority_certificate_type_list:
    2661             :  * @pcache: is a #gnutls_prioritity_t type.
    2662             :  * @list: will point to an integer list
    2663             :  *
    2664             :  * Get a list of available certificate types in the priority
    2665             :  * structure.
    2666             :  *
    2667             :  * As of version 3.6.4 this function is an alias for
    2668             :  * gnutls_priority_certificate_type_list2 with the target parameter
    2669             :  * set to:
    2670             :  * - GNUTLS_CTYPE_SERVER, if the %SERVER_PRECEDENCE option is set
    2671             :  * - GNUTLS_CTYPE_CLIENT, otherwise.
    2672             :  *
    2673             :  * Returns: the number of certificate types, or an error code.
    2674             :  * Since: 3.0
    2675             :  **/
    2676             : int
    2677           0 : gnutls_priority_certificate_type_list(gnutls_priority_t pcache,
    2678             :                                       const unsigned int **list)
    2679             : {
    2680           0 :         gnutls_ctype_target_t target =
    2681           0 :                 pcache->server_precedence ? GNUTLS_CTYPE_SERVER : GNUTLS_CTYPE_CLIENT;
    2682             : 
    2683           0 :         return gnutls_priority_certificate_type_list2(pcache, list, target);
    2684             : }
    2685             : 
    2686             : /**
    2687             :  * gnutls_priority_certificate_type_list2:
    2688             :  * @pcache: is a #gnutls_prioritity_t type.
    2689             :  * @list: will point to an integer list.
    2690             :  * @target: is a #gnutls_ctype_target_t type. Valid arguments are
    2691             :  *   GNUTLS_CTYPE_CLIENT and GNUTLS_CTYPE_SERVER
    2692             :  *
    2693             :  * Get a list of available certificate types for the given target
    2694             :  * in the priority structure.
    2695             :  *
    2696             :  * Returns: the number of certificate types, or an error code.
    2697             :  *
    2698             :  * Since: 3.6.4
    2699             :  **/
    2700             : int
    2701           0 : gnutls_priority_certificate_type_list2(gnutls_priority_t pcache,
    2702             :                                       const unsigned int **list, gnutls_ctype_target_t target)
    2703             : {
    2704           0 :         switch (target) {
    2705           0 :                 case GNUTLS_CTYPE_CLIENT:
    2706           0 :                         if(pcache->client_ctype.num_priorities > 0) {
    2707           0 :                                 *list = pcache->client_ctype.priorities;
    2708           0 :                                 return pcache->client_ctype.num_priorities;
    2709             :                         }
    2710             :                         break;
    2711           0 :                 case GNUTLS_CTYPE_SERVER:
    2712           0 :                         if(pcache->server_ctype.num_priorities > 0)       {
    2713           0 :                                 *list = pcache->server_ctype.priorities;
    2714           0 :                                 return pcache->server_ctype.num_priorities;
    2715             :                         }
    2716             :                         break;
    2717             :                 default:
    2718             :                         // Invalid target given
    2719           0 :                         gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    2720             :         }
    2721             : 
    2722             :         // Found a matching target but non of them had any ctypes set
    2723             :         return 0;
    2724             : }
    2725             : 
    2726             : /**
    2727             :  * gnutls_priority_string_list:
    2728             :  * @iter: an integer counter starting from zero
    2729             :  * @flags: one of %GNUTLS_PRIORITY_LIST_INIT_KEYWORDS, %GNUTLS_PRIORITY_LIST_SPECIAL
    2730             :  *
    2731             :  * Can be used to iterate all available priority strings.
    2732             :  * Due to internal implementation details, there are cases where this
    2733             :  * function can return the empty string. In that case that string should be ignored.
    2734             :  * When no strings are available it returns %NULL.
    2735             :  *
    2736             :  * Returns: a priority string
    2737             :  * Since: 3.4.0
    2738             :  **/
    2739             : const char *
    2740           0 : gnutls_priority_string_list(unsigned iter, unsigned int flags)
    2741             : {
    2742           0 :         if (flags & GNUTLS_PRIORITY_LIST_INIT_KEYWORDS) {
    2743           0 :                 if (iter >= (sizeof(pgroups)/sizeof(pgroups[0]))-1)
    2744             :                         return NULL;
    2745           0 :                 return pgroups[iter].name;
    2746           0 :         } else if (flags & GNUTLS_PRIORITY_LIST_SPECIAL) {
    2747           0 :                 if (iter >= (sizeof(wordlist)/sizeof(wordlist[0]))-1)
    2748             :                         return NULL;
    2749           0 :                 return wordlist[iter].name;
    2750             :         }
    2751             :         return NULL;
    2752             : }

Generated by: LCOV version 1.14