DSA signatures and DHE-DSS are disabled by default
[gnutls:gnutls.git] / lib / gnutls_priority.c
1 /*
2  * Copyright (C) 2004-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 /* Here lies the code of the gnutls_*_set_priority() functions.
24  */
25
26 #include "gnutls_int.h"
27 #include "algorithms.h"
28 #include "gnutls_errors.h"
29 #include <gnutls_num.h>
30 #include <gnutls/x509.h>
31 #include <c-ctype.h>
32 #include <gnutls_extensions.h>
33
34 #define MAX_ELEMENTS 64
35
36 static void prio_remove(priority_st * priority_list, unsigned int algo);
37 static void prio_add(priority_st * priority_list, unsigned int algo);
38 static void
39 break_list(char *etag,
40                  char *broken_etag[MAX_ELEMENTS], int *size);
41
42 typedef void (bulk_rmadd_func) (priority_st * priority_list, const int *);
43
44 inline static void _set_priority(priority_st * st, const int *list)
45 {
46         int num = 0, i;
47
48         while (list[num] != 0)
49                 num++;
50         if (num > MAX_ALGOS)
51                 num = MAX_ALGOS;
52         st->algorithms = num;
53
54         for (i = 0; i < num; i++) {
55                 st->priority[i] = list[i];
56         }
57
58         return;
59 }
60
61 inline static void _add_priority(priority_st * st, const int *list)
62 {
63         int num, i, j, init;
64
65         init = i = st->algorithms;
66
67         for (num = 0; list[num] != 0; ++num) {
68                 if (i + 1 > MAX_ALGOS) {
69                         return;
70                 }
71
72                 for (j = 0; j < init; j++) {
73                         if (st->priority[j] == (unsigned) list[num]) {
74                                 break;
75                         }
76                 }
77
78                 if (j == init) {
79                         st->priority[i++] = list[num];
80                         st->algorithms++;
81                 }
82         }
83
84         return;
85 }
86
87 static void _clear_priorities(priority_st * st, const int *list)
88 {
89         memset(st, 0, sizeof(*st));
90 }
91
92 static void _clear_given_priorities(priority_st * st, const int *list)
93 {
94         unsigned i;
95
96         for (i=0;list[i]!=0;i++) {
97                 prio_remove(st, list[i]);
98         }
99 }
100
101 static const int _supported_ecc_normal[] = {
102         GNUTLS_ECC_CURVE_SECP256R1,
103         GNUTLS_ECC_CURVE_SECP384R1,
104         GNUTLS_ECC_CURVE_SECP521R1,
105 #ifdef ENABLE_NON_SUITEB_CURVES
106         GNUTLS_ECC_CURVE_SECP224R1,
107         GNUTLS_ECC_CURVE_SECP192R1,
108 #endif
109         0
110 };
111 static const int* supported_ecc_normal = _supported_ecc_normal;
112
113 static const int _supported_ecc_secure128[] = {
114         GNUTLS_ECC_CURVE_SECP256R1,
115         GNUTLS_ECC_CURVE_SECP384R1,
116         GNUTLS_ECC_CURVE_SECP521R1,
117         0
118 };
119 static const int* supported_ecc_secure128 = _supported_ecc_secure128;
120
121 static const int _supported_ecc_suiteb128[] = {
122         GNUTLS_ECC_CURVE_SECP256R1,
123         GNUTLS_ECC_CURVE_SECP384R1,
124         0
125 };
126 static const int* supported_ecc_suiteb128 = _supported_ecc_suiteb128;
127
128 static const int _supported_ecc_suiteb192[] = {
129         GNUTLS_ECC_CURVE_SECP384R1,
130         0
131 };
132 static const int* supported_ecc_suiteb192 = _supported_ecc_suiteb192;
133
134 static const int _supported_ecc_secure192[] = {
135         GNUTLS_ECC_CURVE_SECP384R1,
136         GNUTLS_ECC_CURVE_SECP521R1,
137         0
138 };
139 static const int* supported_ecc_secure192 = _supported_ecc_secure192;
140
141 static const int protocol_priority[] = {
142         GNUTLS_TLS1_2,
143         GNUTLS_TLS1_1,
144         GNUTLS_TLS1_0,
145         GNUTLS_DTLS1_2,
146         GNUTLS_DTLS1_0,
147         0
148 };
149
150 static const int stream_protocol_priority[] = {
151         GNUTLS_TLS1_2,
152         GNUTLS_TLS1_1,
153         GNUTLS_TLS1_0,
154         0
155 };
156
157 static const int dgram_protocol_priority[] = {
158         GNUTLS_DTLS1_2,
159         GNUTLS_DTLS1_0,
160         GNUTLS_DTLS0_9,
161         0
162 };
163
164 static const int dtls_protocol_priority[] = {
165         GNUTLS_DTLS1_2,
166         GNUTLS_DTLS1_0,
167         0
168 };
169
170 static const int _protocol_priority_suiteb[] = {
171         GNUTLS_TLS1_2,
172         0
173 };
174 static const int* protocol_priority_suiteb = _protocol_priority_suiteb;
175
176 static const int _kx_priority_performance[] = {
177         GNUTLS_KX_RSA,
178 #ifdef ENABLE_ECDHE
179         GNUTLS_KX_ECDHE_ECDSA,
180         GNUTLS_KX_ECDHE_RSA,
181 #endif
182 #ifdef ENABLE_DHE
183         GNUTLS_KX_DHE_RSA,
184 #endif
185         0
186 };
187 static const int* kx_priority_performance = _kx_priority_performance;
188
189 static const int _kx_priority_pfs[] = {
190 #ifdef ENABLE_ECDHE
191         GNUTLS_KX_ECDHE_ECDSA,
192         GNUTLS_KX_ECDHE_RSA,
193 #endif
194 #ifdef ENABLE_DHE
195         GNUTLS_KX_DHE_RSA,
196 #endif
197         0
198 };
199 static const int* kx_priority_pfs = _kx_priority_pfs;
200
201 static const int _kx_priority_suiteb[] = {
202         GNUTLS_KX_ECDHE_ECDSA,
203         0
204 };
205 static const int* kx_priority_suiteb = _kx_priority_suiteb;
206
207 static const int _kx_priority_secure[] = {
208         /* The ciphersuites that offer forward secrecy take
209          * precedence
210          */
211 #ifdef ENABLE_ECDHE
212         GNUTLS_KX_ECDHE_ECDSA,
213         GNUTLS_KX_ECDHE_RSA,
214 #endif
215         GNUTLS_KX_RSA,
216         /* KX-RSA is now ahead of DHE-RSA and DHE-DSS due to the compatibility
217          * issues the DHE ciphersuites have. That is, one cannot enforce a specific
218          * security level without dropping the connection. 
219          */
220 #ifdef ENABLE_DHE
221         GNUTLS_KX_DHE_RSA,
222 #endif
223         /* GNUTLS_KX_ANON_DH: Man-in-the-middle prone, don't add!
224          */
225         0
226 };
227 static const int* kx_priority_secure = _kx_priority_secure;
228
229 static const int _cipher_priority_performance_default[] = {
230         GNUTLS_CIPHER_AES_128_GCM,
231         GNUTLS_CIPHER_AES_256_GCM,
232         GNUTLS_CIPHER_CAMELLIA_128_GCM,
233         GNUTLS_CIPHER_CAMELLIA_256_GCM,
234         GNUTLS_CIPHER_AES_128_CBC,
235         GNUTLS_CIPHER_AES_256_CBC,
236         GNUTLS_CIPHER_CAMELLIA_128_CBC,
237         GNUTLS_CIPHER_CAMELLIA_256_CBC,
238         GNUTLS_CIPHER_AES_128_CCM,
239         GNUTLS_CIPHER_AES_256_CCM,
240         GNUTLS_CIPHER_3DES_CBC,
241         0
242 };
243
244 /* If GCM and AES acceleration is available then prefer
245  * them over anything else.
246  */
247 static const int _cipher_priority_normal_default[] = {
248         GNUTLS_CIPHER_AES_128_GCM,
249         GNUTLS_CIPHER_AES_256_GCM,
250         GNUTLS_CIPHER_CAMELLIA_128_GCM,
251         GNUTLS_CIPHER_CAMELLIA_256_GCM,
252         GNUTLS_CIPHER_AES_128_CBC,
253         GNUTLS_CIPHER_AES_256_CBC,
254         GNUTLS_CIPHER_CAMELLIA_128_CBC,
255         GNUTLS_CIPHER_CAMELLIA_256_CBC,
256         GNUTLS_CIPHER_AES_128_CCM,
257         GNUTLS_CIPHER_AES_256_CCM,
258         GNUTLS_CIPHER_3DES_CBC,
259         0
260 };
261
262 static const int cipher_priority_performance_fips[] = {
263         GNUTLS_CIPHER_AES_128_GCM,
264         GNUTLS_CIPHER_AES_256_GCM,
265         GNUTLS_CIPHER_AES_128_CBC,
266         GNUTLS_CIPHER_AES_256_CBC,
267         GNUTLS_CIPHER_AES_128_CCM,
268         GNUTLS_CIPHER_AES_256_CCM,
269         GNUTLS_CIPHER_3DES_CBC,
270         0
271 };
272
273 static const int cipher_priority_normal_fips[] = {
274         GNUTLS_CIPHER_AES_128_GCM,
275         GNUTLS_CIPHER_AES_256_GCM,
276         GNUTLS_CIPHER_AES_128_CBC,
277         GNUTLS_CIPHER_AES_256_CBC,
278         GNUTLS_CIPHER_AES_128_CCM,
279         GNUTLS_CIPHER_AES_256_CCM,
280         GNUTLS_CIPHER_3DES_CBC,
281         0
282 };
283
284
285 static const int _cipher_priority_suiteb128[] = {
286         GNUTLS_CIPHER_AES_128_GCM,
287         GNUTLS_CIPHER_AES_256_GCM,
288         0
289 };
290 static const int* cipher_priority_suiteb128 = _cipher_priority_suiteb128;
291
292 static const int _cipher_priority_suiteb192[] = {
293         GNUTLS_CIPHER_AES_256_GCM,
294         0
295 };
296 static const int* cipher_priority_suiteb192 = _cipher_priority_suiteb192;
297
298
299 static const int _cipher_priority_secure128[] = {
300         GNUTLS_CIPHER_AES_128_GCM,
301         GNUTLS_CIPHER_CAMELLIA_128_GCM,
302
303         GNUTLS_CIPHER_AES_256_GCM,
304         GNUTLS_CIPHER_CAMELLIA_256_GCM,
305
306         GNUTLS_CIPHER_AES_128_CBC,
307         GNUTLS_CIPHER_CAMELLIA_128_CBC,
308         GNUTLS_CIPHER_AES_256_CBC,
309         GNUTLS_CIPHER_CAMELLIA_256_CBC,
310
311         GNUTLS_CIPHER_AES_128_CCM,
312         GNUTLS_CIPHER_AES_256_CCM,
313         0
314 };
315 static const int *cipher_priority_secure128 = _cipher_priority_secure128;
316
317
318 static const int _cipher_priority_secure192[] = {
319         GNUTLS_CIPHER_AES_256_GCM,
320         GNUTLS_CIPHER_CAMELLIA_256_GCM,
321         GNUTLS_CIPHER_AES_256_CBC,
322         GNUTLS_CIPHER_CAMELLIA_256_CBC,
323         GNUTLS_CIPHER_AES_256_CCM,
324         0
325 };
326 static const int* cipher_priority_secure192 = _cipher_priority_secure192;
327
328 static const int comp_priority[] = {
329         /* compression should be explicitly requested to be enabled */
330         GNUTLS_COMP_NULL,
331         0
332 };
333
334 static const int _sign_priority_default[] = {
335         GNUTLS_SIGN_RSA_SHA256,
336         GNUTLS_SIGN_ECDSA_SHA256,
337
338         GNUTLS_SIGN_RSA_SHA384,
339         GNUTLS_SIGN_ECDSA_SHA384,
340
341         GNUTLS_SIGN_RSA_SHA512,
342         GNUTLS_SIGN_ECDSA_SHA512,
343
344         GNUTLS_SIGN_RSA_SHA224,
345         GNUTLS_SIGN_ECDSA_SHA224,
346
347         GNUTLS_SIGN_RSA_SHA1,
348         GNUTLS_SIGN_ECDSA_SHA1,
349         0
350 };
351 static const int* sign_priority_default = _sign_priority_default;
352
353 static const int _sign_priority_suiteb128[] = {
354         GNUTLS_SIGN_ECDSA_SHA256,
355         GNUTLS_SIGN_ECDSA_SHA384,
356         0
357 };
358 static const int* sign_priority_suiteb128 = _sign_priority_suiteb128;
359
360 static const int _sign_priority_suiteb192[] = {
361         GNUTLS_SIGN_ECDSA_SHA384,
362         0
363 };
364 static const int* sign_priority_suiteb192 = _sign_priority_suiteb192;
365
366 static const int _sign_priority_secure128[] = {
367         GNUTLS_SIGN_RSA_SHA256,
368         GNUTLS_SIGN_ECDSA_SHA256,
369         GNUTLS_SIGN_RSA_SHA384,
370         GNUTLS_SIGN_ECDSA_SHA384,
371         GNUTLS_SIGN_RSA_SHA512,
372         GNUTLS_SIGN_ECDSA_SHA512,
373         0
374 };
375 static const int* sign_priority_secure128 = _sign_priority_secure128;
376
377 static const int _sign_priority_secure192[] = {
378         GNUTLS_SIGN_RSA_SHA384,
379         GNUTLS_SIGN_ECDSA_SHA384,
380         GNUTLS_SIGN_RSA_SHA512,
381         GNUTLS_SIGN_ECDSA_SHA512,
382         0
383 };
384 static const int* sign_priority_secure192 = _sign_priority_secure192;
385
386 static const int mac_priority_normal_default[] = {
387         GNUTLS_MAC_SHA1,
388         GNUTLS_MAC_SHA256,
389         GNUTLS_MAC_SHA384,
390         GNUTLS_MAC_AEAD,
391         GNUTLS_MAC_MD5,
392         0
393 };
394
395 static const int mac_priority_normal_fips[] = {
396         GNUTLS_MAC_SHA1,
397         GNUTLS_MAC_SHA256,
398         GNUTLS_MAC_SHA384,
399         GNUTLS_MAC_AEAD,
400         0
401 };
402
403 static const int *cipher_priority_performance = _cipher_priority_performance_default;
404 static const int *cipher_priority_normal = _cipher_priority_normal_default;
405 static const int *mac_priority_normal = mac_priority_normal_default;
406
407 /* if called with replace the default priorities with the FIPS140 ones */
408 void _gnutls_priority_update_fips(void)
409 {
410         cipher_priority_performance = cipher_priority_performance_fips;
411         cipher_priority_normal = cipher_priority_normal_fips;
412         mac_priority_normal = mac_priority_normal_fips;
413 }
414
415 static const int _mac_priority_suiteb[] = {
416         GNUTLS_MAC_AEAD,
417         0
418 };
419 static const int* mac_priority_suiteb = _mac_priority_suiteb;
420
421 static const int _mac_priority_secure128[] = {
422         GNUTLS_MAC_SHA1,
423         GNUTLS_MAC_SHA256,
424         GNUTLS_MAC_SHA384,
425         GNUTLS_MAC_AEAD,
426         0
427 };
428 static const int* mac_priority_secure128 = _mac_priority_secure128;
429
430 static const int _mac_priority_secure192[] = {
431         GNUTLS_MAC_SHA256,
432         GNUTLS_MAC_SHA384,
433         GNUTLS_MAC_AEAD,
434         0
435 };
436 static const int* mac_priority_secure192 = _mac_priority_secure192;
437
438 static const int cert_type_priority_default[] = {
439         GNUTLS_CRT_X509,
440         0
441 };
442
443 static const int cert_type_priority_all[] = {
444         GNUTLS_CRT_X509,
445         GNUTLS_CRT_OPENPGP,
446         0
447 };
448
449 typedef void (rmadd_func) (priority_st * priority_list, unsigned int alg);
450
451 static void prio_remove(priority_st * priority_list, unsigned int algo)
452 {
453         unsigned int i;
454
455         for (i = 0; i < priority_list->algorithms; i++) {
456                 if (priority_list->priority[i] == algo) {
457                         priority_list->algorithms--;
458                         if ((priority_list->algorithms - i) > 0)
459                                 memmove(&priority_list->priority[i],
460                                         &priority_list->priority[i + 1],
461                                         (priority_list->algorithms -
462                                          i) *
463                                         sizeof(priority_list->
464                                                priority[0]));
465                         priority_list->priority[priority_list->
466                                                 algorithms] = 0;
467                         break;
468                 }
469         }
470
471         return;
472 }
473
474 static void prio_add(priority_st * priority_list, unsigned int algo)
475 {
476         unsigned int i, l = priority_list->algorithms;
477
478         if (l >= MAX_ALGOS)
479                 return;         /* can't add it anyway */
480
481         for (i = 0; i < l; ++i) {
482                 if (algo == priority_list->priority[i])
483                         return; /* if it exists */
484         }
485
486         priority_list->priority[l] = algo;
487         priority_list->algorithms++;
488
489         return;
490 }
491
492
493 /**
494  * gnutls_priority_set:
495  * @session: is a #gnutls_session_t structure.
496  * @priority: is a #gnutls_priority_t structure.
497  *
498  * Sets the priorities to use on the ciphers, key exchange methods,
499  * macs and compression methods.
500  *
501  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
502  **/
503 int
504 gnutls_priority_set(gnutls_session_t session, gnutls_priority_t priority)
505 {
506         if (priority == NULL) {
507                 gnutls_assert();
508                 return GNUTLS_E_NO_CIPHER_SUITES;
509         }
510
511         memcpy(&session->internals.priorities, priority,
512                sizeof(struct gnutls_priority_st));
513
514         /* set the current version to the first in the chain.
515          * This will be overridden later.
516          */
517         if (session->internals.priorities.protocol.algorithms > 0) {
518                 if (_gnutls_set_current_version(session,
519                                             session->internals.priorities.
520                                             protocol.priority[0]) < 0) {
521                         return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
522                 }
523         }
524
525         if (priority->no_tickets != 0) {
526                 /* when PFS is explicitly requested, disable session tickets */
527                 _gnutls_ext_unset_session_data(session, GNUTLS_EXTENSION_SESSION_TICKET);
528         }
529
530         if (session->internals.priorities.protocol.algorithms == 0 ||
531             session->internals.priorities.cipher.algorithms == 0 ||
532             session->internals.priorities.mac.algorithms == 0 ||
533             session->internals.priorities.kx.algorithms == 0 ||
534             session->internals.priorities.compression.algorithms == 0)
535                 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
536
537         return 0;
538 }
539
540
541 #define LEVEL_NONE "NONE"
542 #define LEVEL_NORMAL "NORMAL"
543 #define LEVEL_PFS "PFS"
544 #define LEVEL_PERFORMANCE "PERFORMANCE"
545 #define LEVEL_SECURE128 "SECURE128"
546 #define LEVEL_SECURE192 "SECURE192"
547 #define LEVEL_SECURE256 "SECURE256"
548 #define LEVEL_SUITEB128 "SUITEB128"
549 #define LEVEL_SUITEB192 "SUITEB192"
550 #define LEVEL_LEGACY "LEGACY"
551
552 struct priority_groups_st {
553         const char *name;
554         const char *alias;
555         const int **proto_list;
556         const int **cipher_list;
557         const int **mac_list;
558         const int **kx_list;
559         const int **sign_list;
560         const int **ecc_list;
561         unsigned profile;
562         int sec_param;
563         bool no_tickets;
564 };
565
566 static const struct priority_groups_st pgroups[] = 
567 {
568         {.name = LEVEL_NORMAL,
569          .cipher_list = &cipher_priority_normal,
570          .mac_list = &mac_priority_normal,
571          .kx_list = &kx_priority_secure,
572          .sign_list = &sign_priority_default,
573          .ecc_list = &supported_ecc_normal,
574          .profile = GNUTLS_PROFILE_LOW,
575          .sec_param = GNUTLS_SEC_PARAM_WEAK
576         },
577         {.name = LEVEL_PFS,
578          .cipher_list = &cipher_priority_normal,
579          .mac_list = &mac_priority_secure128,
580          .kx_list = &kx_priority_pfs,
581          .sign_list = &sign_priority_default,
582          .ecc_list = &supported_ecc_normal,
583          .profile = GNUTLS_PROFILE_LOW,
584          .sec_param = GNUTLS_SEC_PARAM_WEAK,
585          .no_tickets = 1
586         },
587         {.name = LEVEL_SECURE128,
588          .alias = "SECURE",
589          .cipher_list = &cipher_priority_secure128,
590          .mac_list = &mac_priority_secure128,
591          .kx_list = &kx_priority_secure,
592          .sign_list = &sign_priority_secure128,
593          .ecc_list = &supported_ecc_secure128,
594                 /* The profile should have been HIGH but if we don't allow
595                  * SHA-1 (80-bits) as signature algorithm we are not able
596                  * to connect anywhere with this level */
597          .profile = GNUTLS_PROFILE_LOW,
598          .sec_param = GNUTLS_SEC_PARAM_LOW
599         },
600         {.name = LEVEL_SECURE192,
601          .alias = LEVEL_SECURE256,
602          .cipher_list = &cipher_priority_secure192,
603          .mac_list = &mac_priority_secure192,
604          .kx_list = &kx_priority_secure,
605          .sign_list = &sign_priority_secure192,
606          .ecc_list = &supported_ecc_secure192,
607          .profile = GNUTLS_PROFILE_HIGH,
608          .sec_param = GNUTLS_SEC_PARAM_HIGH
609         },
610         {.name = LEVEL_SUITEB128,
611          .proto_list = &protocol_priority_suiteb,
612          .cipher_list = &cipher_priority_suiteb128,
613          .mac_list = &mac_priority_suiteb,
614          .kx_list = &kx_priority_suiteb,
615          .sign_list = &sign_priority_suiteb128,
616          .ecc_list = &supported_ecc_suiteb128,
617          .profile = GNUTLS_PROFILE_SUITEB128,
618          .sec_param = GNUTLS_SEC_PARAM_HIGH
619         },
620         {.name = LEVEL_SUITEB192,
621          .proto_list = &protocol_priority_suiteb,
622          .cipher_list = &cipher_priority_suiteb192,
623          .mac_list = &mac_priority_suiteb,
624          .kx_list = &kx_priority_suiteb,
625          .sign_list = &sign_priority_suiteb192,
626          .ecc_list = &supported_ecc_suiteb192,
627          .profile = GNUTLS_PROFILE_SUITEB192,
628          .sec_param = GNUTLS_SEC_PARAM_ULTRA
629         },
630         {.name = LEVEL_LEGACY,
631          .cipher_list = &cipher_priority_normal,
632          .mac_list = &mac_priority_normal,
633          .kx_list = &kx_priority_secure,
634          .sign_list = &sign_priority_default,
635          .ecc_list = &supported_ecc_normal,
636          .sec_param = GNUTLS_SEC_PARAM_VERY_WEAK
637         },
638         {.name = LEVEL_PERFORMANCE,
639          .cipher_list = &cipher_priority_performance,
640          .mac_list = &mac_priority_normal,
641          .kx_list = &kx_priority_performance,
642          .sign_list = &sign_priority_default,
643          .ecc_list = &supported_ecc_normal,
644          .profile = GNUTLS_PROFILE_LOW,
645          .sec_param = GNUTLS_SEC_PARAM_WEAK
646         },
647         {
648          .name = NULL,
649         }
650 };
651
652 #define SET_PROFILE(to_set) \
653         profile = GNUTLS_VFLAGS_TO_PROFILE(priority_cache->additional_verify_flags); \
654         if (profile == 0 || profile > to_set) { \
655                 priority_cache->additional_verify_flags &= ~GNUTLS_VFLAGS_PROFILE_MASK; \
656                 priority_cache->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(to_set); \
657         }
658
659 #define SET_LEVEL(to_set) \
660                 if (priority_cache->level == 0 || (unsigned)priority_cache->level > (unsigned)to_set) \
661                         priority_cache->level = to_set
662
663 static
664 int check_level(const char *level, gnutls_priority_t priority_cache,
665                 int add)
666 {
667         bulk_rmadd_func *func;
668         unsigned profile = 0;
669         unsigned i;
670
671         if (add)
672                 func = _add_priority;
673         else
674                 func = _set_priority;
675
676         for (i=0;;i++) {
677                 if (pgroups[i].name == NULL)
678                         return 0;
679
680                 if (strcasecmp(level, pgroups[i].name) == 0 ||
681                         (pgroups[i].alias != NULL && strcasecmp(level, pgroups[i].alias) == 0)) {
682                         if (pgroups[i].proto_list != NULL)
683                                 func(&priority_cache->protocol, *pgroups[i].proto_list);
684                         func(&priority_cache->cipher, *pgroups[i].cipher_list);
685                         func(&priority_cache->kx, *pgroups[i].kx_list);
686                         func(&priority_cache->mac, *pgroups[i].mac_list);
687                         func(&priority_cache->sign_algo, *pgroups[i].sign_list);
688                         func(&priority_cache->supported_ecc, *pgroups[i].ecc_list);
689
690                         if (pgroups[i].profile != 0) {
691                                 SET_PROFILE(pgroups[i].profile); /* set certificate level */
692                         }
693                         SET_LEVEL(pgroups[i].sec_param); /* set DH params level */
694                         priority_cache->no_tickets = pgroups[i].no_tickets;
695                         return 1;
696                 }
697         }
698 }
699
700 static void enable_compat(gnutls_priority_t c)
701 {
702         ENABLE_COMPAT(c);
703 }
704 static void enable_dumbfw(gnutls_priority_t c)
705 {
706         c->dumbfw = 1;
707 }
708 static void enable_no_extensions(gnutls_priority_t c)
709 {
710         c->no_extensions = 1;
711 }
712 static void enable_no_ext_master_secret(gnutls_priority_t c)
713 {
714         c->no_ext_master_secret = 1;
715 }
716 static void enable_no_etm(gnutls_priority_t c)
717 {
718         c->no_etm = 1;
719 }
720 static void enable_no_tickets(gnutls_priority_t c)
721 {
722         c->no_tickets = 1;
723 }
724 static void enable_stateless_compression(gnutls_priority_t c)
725 {
726         c->stateless_compression = 1;
727 }
728 static void disable_wildcards(gnutls_priority_t c)
729 {
730         c->additional_verify_flags |= GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS;
731 }
732 static void enable_profile_very_weak(gnutls_priority_t c)
733 {
734         c->additional_verify_flags &= 0x00ffffff;
735         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_VERY_WEAK);
736         c->level = GNUTLS_SEC_PARAM_VERY_WEAK;
737 }
738 static void enable_profile_low(gnutls_priority_t c)
739 {
740         c->additional_verify_flags &= 0x00ffffff;
741         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_LOW);
742         c->level = GNUTLS_SEC_PARAM_LOW;
743 }
744 static void enable_profile_legacy(gnutls_priority_t c)
745 {
746         c->additional_verify_flags &= 0x00ffffff;
747         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_LEGACY);
748         c->level = GNUTLS_SEC_PARAM_LEGACY;
749 }
750 static void enable_profile_high(gnutls_priority_t c)
751 {
752         c->additional_verify_flags &= 0x00ffffff;
753         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_HIGH);
754         c->level = GNUTLS_SEC_PARAM_HIGH;
755 }
756 static void enable_profile_ultra(gnutls_priority_t c)
757 {
758         c->additional_verify_flags &= 0x00ffffff;
759         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_ULTRA);
760         c->level = GNUTLS_SEC_PARAM_ULTRA;
761 }
762 static void enable_profile_medium(gnutls_priority_t c)
763 {
764         c->additional_verify_flags &= 0x00ffffff;
765         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_MEDIUM);
766         c->level = GNUTLS_SEC_PARAM_MEDIUM;
767 }
768 static void enable_profile_suiteb128(gnutls_priority_t c)
769 {
770         c->additional_verify_flags &= 0x00ffffff;
771         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_SUITEB128);
772         c->level = GNUTLS_SEC_PARAM_HIGH;
773 }
774 static void enable_profile_suiteb192(gnutls_priority_t c)
775 {
776         c->additional_verify_flags &= 0x00ffffff;
777         c->additional_verify_flags |= GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_SUITEB192);
778         c->level = GNUTLS_SEC_PARAM_ULTRA;
779 }
780 static void enable_safe_renegotiation(gnutls_priority_t c)
781 {
782         c->sr = SR_SAFE;
783
784 }
785 static void enable_unsafe_renegotiation(gnutls_priority_t c)
786 {
787         c->sr = SR_UNSAFE;
788 }
789 static void enable_partial_safe_renegotiation(gnutls_priority_t c)
790 {
791         c->sr = SR_PARTIAL;
792 }
793 static void disable_safe_renegotiation(gnutls_priority_t c)
794 {
795         c->sr = SR_DISABLED;
796 }
797 static void enable_latest_record_version(gnutls_priority_t c)
798 {
799         c->min_record_version = 0;
800 }
801 static void enable_ssl3_record_version(gnutls_priority_t c)
802 {
803         c->min_record_version = 1;
804 }
805 static void enable_verify_allow_rsa_md5(gnutls_priority_t c)
806 {
807         c->additional_verify_flags |=
808             GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5;
809 }
810 static void disable_crl_checks(gnutls_priority_t c)
811 {
812         c->additional_verify_flags |=
813                 GNUTLS_VERIFY_DISABLE_CRL_CHECKS;
814 }
815 static void enable_server_precedence(gnutls_priority_t c)
816 {
817         c->server_precedence = 1;
818 }
819 static void dummy_func(gnutls_priority_t c)
820 {
821 }
822
823 #include <priority_options.h>
824
825 static char *check_str(char *line, size_t line_size, const char *needle, size_t needle_size)
826 {
827         char *p;
828         unsigned n;
829
830         while (c_isspace(*line)) {
831                 line++;
832                 line_size--;
833         }
834
835         if (line[0] == '#' || needle_size >= line_size)
836                 return NULL;
837
838         if (memcmp(line, needle, needle_size) == 0) {
839                 p = &line[needle_size];
840                 while (c_isspace(*p)) {
841                         p++;
842                 }
843                 if (*p != '=') {
844                         return NULL;
845                 } else
846                         p++;
847
848                 while (c_isspace(*p)) {
849                         p++;
850                 }
851
852                 n = strlen(p);
853
854                 if (n > 1 && p[n-1] == '\n') {
855                         n--;
856                         p[n] = 0;
857                 }
858
859                 if (n > 1 && p[n-1] == '\r') {
860                         n--;
861                         p[n] = 0;
862                 }
863                 return p;
864         }
865
866         return NULL;
867 }
868
869 /* Returns the new priorities if SYSTEM is specified in
870  * an allocated string, or just a copy of the provided
871  * priorities, appended with any additional present in
872  * the priorities string.
873  *
874  * The returned string must be released using free().
875  */
876 static char *resolve_priorities(const char* priorities)
877 {
878 char *p = (char*)priorities;
879 char *additional = NULL;
880 char *ret = NULL;
881 char *ss, *line = NULL;
882 unsigned ss_len;
883 int l;
884 FILE* fp = NULL;
885 size_t n, n2 = 0, line_size;
886
887         while (c_isspace(*p))
888                 p++;
889
890         if (*p == '@') {
891                 ss = p+1;
892
893                 additional = strchr(p, ':');
894                 if (additional != NULL) {
895                         ss_len = additional - ss;
896                         additional++;
897                 } else {
898                         ss_len = strlen(ss);
899                 }
900
901                 fp = fopen(SYSTEM_PRIORITY_FILE, "r");
902                 if (fp == NULL) {/* fail */
903                         ret = NULL;
904                         goto finish;
905                 }
906
907                 do {
908                         l = getline(&line, &line_size, fp);
909                         if (l > 0) {
910                                 p = check_str(line, line_size, ss, ss_len);
911                                 if (p != NULL)
912                                         break;
913                         }
914                 } while (l>0);
915
916                 if (p == NULL) {
917                         ret = NULL;
918                         goto finish;
919                 }
920
921                 n = strlen(p);
922                 if (additional)
923                         n2 = strlen(additional);
924
925                 ret = malloc(n+n2+1+1);
926                 if (ret == NULL) {
927                         goto finish;
928                 }
929
930                 memcpy(ret, p, n);
931                 if (additional != NULL) {
932                         ret[n] = ':';
933                         memcpy(&ret[n+1], additional, n2);
934                         ret[n+n2+1] = 0;
935                 } else {
936                         ret[n] = 0;
937                 }
938         } else {
939                 return strdup(p);
940         }
941
942 finish:
943         if (ret != NULL) {
944                 _gnutls_debug_log("selected priority string: %s\n", ret);
945         }
946         free(line);
947         if (fp != NULL)
948                 fclose(fp);
949
950         return ret;
951 }
952
953 /**
954  * gnutls_priority_init:
955  * @priority_cache: is a #gnutls_prioritity_t structure.
956  * @priorities: is a string describing priorities
957  * @err_pos: In case of an error this will have the position in the string the error occurred
958  *
959  * Sets priorities for the ciphers, key exchange methods, macs and
960  * compression methods.
961  *
962  * The #priorities option allows you to specify a colon
963  * separated list of the cipher priorities to enable.
964  * Some keywords are defined to provide quick access
965  * to common preferences.
966  *
967  * Unless there is a special need, use the "NORMAL" keyword to
968  * apply a reasonable security level, or "NORMAL:%COMPAT" for compatibility.
969  *
970  * "PERFORMANCE" means all the "secure" ciphersuites are enabled,
971  * limited to 128 bit ciphers and sorted by terms of speed
972  * performance.
973  *
974  * "LEGACY" the NORMAL settings for GnuTLS 3.2.x or earlier. There is
975  * no verification profile set, and the allowed DH primes are considered
976  * weak today.
977  *
978  * "NORMAL" means all "secure" ciphersuites. The 256-bit ciphers are
979  * included as a fallback only.  The ciphers are sorted by security
980  * margin.
981  *
982  * "PFS" means all "secure" ciphersuites that support perfect forward secrecy. 
983  * The 256-bit ciphers are included as a fallback only.  
984  * The ciphers are sorted by security margin.
985  *
986  * "SECURE128" means all "secure" ciphersuites of security level 128-bit
987  * or more.
988  *
989  * "SECURE192" means all "secure" ciphersuites of security level 192-bit
990  * or more.
991  *
992  * "SUITEB128" means all the NSA SuiteB ciphersuites with security level
993  * of 128.
994  *
995  * "SUITEB192" means all the NSA SuiteB ciphersuites with security level
996  * of 192.
997  *
998  * "NONE" means nothing is enabled.  This disables even protocols and
999  * compression methods.
1000  *
1001  * "@KEYWORD" The system administrator imposed settings. The provided keywords
1002  * will be expanded from a configuration-time provided file - default is:
1003  * /etc/gnutls/default-priorities. Any keywords that follow it, will 
1004  * be appended to the expanded string. If there is no system string,
1005  * then the function will fail. The system file should be formatted
1006  * as "KEYWORD=VALUE", e.g., "SYSTEM=NORMAL:+ARCFOUR-128".
1007  *
1008  * Special keywords are "!", "-" and "+".
1009  * "!" or "-" appended with an algorithm will remove this algorithm.
1010  * "+" appended with an algorithm will add this algorithm.
1011  *
1012  * Check the GnuTLS manual section "Priority strings" for detailed
1013  * information.
1014  *
1015  * Examples:
1016  *
1017  * "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"
1018  *
1019  * "NORMAL:+ARCFOUR-128" means normal ciphers plus ARCFOUR-128.
1020  *
1021  * "SECURE128:-VERS-SSL3.0:+COMP-DEFLATE" means that only secure ciphers are
1022  * enabled, SSL3.0 is disabled, and libz compression enabled.
1023  *
1024  * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1", 
1025  *
1026  * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+ECDHE-RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1:+CURVE-SECP256R1", 
1027  *
1028  * "SECURE256:+SECURE128",
1029  *
1030  * Note that "NORMAL:%COMPAT" is the most compatible mode.
1031  *
1032  * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
1033  * %GNUTLS_E_SUCCESS on success, or an error code.
1034  **/
1035 int
1036 gnutls_priority_init(gnutls_priority_t * priority_cache,
1037                      const char *priorities, const char **err_pos)
1038 {
1039         char *broken_list[MAX_ELEMENTS];
1040         int broken_list_size = 0, i = 0, j;
1041         char *darg = NULL;
1042         unsigned ikeyword_set = 0;
1043         int algo;
1044         rmadd_func *fn;
1045         bulk_rmadd_func *bulk_fn;
1046         bulk_rmadd_func *bulk_given_fn;
1047
1048         if (err_pos)
1049                 *err_pos = priorities;
1050
1051         *priority_cache =
1052             gnutls_calloc(1, sizeof(struct gnutls_priority_st));
1053         if (*priority_cache == NULL) {
1054                 gnutls_assert();
1055                 return GNUTLS_E_MEMORY_ERROR;
1056         }
1057
1058         /* for now unsafe renegotiation is default on everyone. To be removed
1059          * when we make it the default.
1060          */
1061         (*priority_cache)->sr = SR_PARTIAL;
1062         (*priority_cache)->min_record_version = 1;
1063
1064         (*priority_cache)->max_empty_records = DEFAULT_MAX_EMPTY_RECORDS;
1065
1066         if (priorities == NULL)
1067                 priorities = "NORMAL";
1068
1069         darg = resolve_priorities(priorities);
1070         if (darg == NULL) {
1071                 gnutls_assert();
1072                 goto error;
1073         }
1074
1075         break_list(darg, broken_list, &broken_list_size);
1076         /* This is our default set of protocol version, certificate types and
1077          * compression methods.
1078          */
1079         if (strcasecmp(broken_list[0], LEVEL_NONE) != 0) {
1080                 _set_priority(&(*priority_cache)->protocol,
1081                               protocol_priority);
1082                 _set_priority(&(*priority_cache)->compression,
1083                               comp_priority);
1084                 _set_priority(&(*priority_cache)->cert_type,
1085                               cert_type_priority_default);
1086                 _set_priority(&(*priority_cache)->sign_algo,
1087                               sign_priority_default);
1088                 _set_priority(&(*priority_cache)->supported_ecc,
1089                               supported_ecc_normal);
1090                 i = 0;
1091         } else {
1092                 ikeyword_set = 1;
1093                 i = 1;
1094         }
1095
1096         for (; i < broken_list_size; i++) {
1097                 if (check_level(broken_list[i], *priority_cache, ikeyword_set) != 0) {
1098                         ikeyword_set = 1;
1099                         continue;
1100                 } else if (broken_list[i][0] == '!'
1101                            || broken_list[i][0] == '+'
1102                            || broken_list[i][0] == '-') {
1103                         if (broken_list[i][0] == '+') {
1104                                 fn = prio_add;
1105                                 bulk_fn = _add_priority;
1106                                 bulk_given_fn = _add_priority;
1107                         } else {
1108                                 fn = prio_remove;
1109                                 bulk_fn = _clear_priorities;
1110                                 bulk_given_fn = _clear_given_priorities;
1111                         }
1112
1113                         if (broken_list[i][0] == '+'
1114                             && check_level(&broken_list[i][1],
1115                                            *priority_cache, 1) != 0) {
1116                                 continue;
1117                         } else if ((algo =
1118                                     gnutls_mac_get_id(&broken_list[i][1]))
1119                                    != GNUTLS_MAC_UNKNOWN)
1120                                 fn(&(*priority_cache)->mac, algo);
1121                         else if ((algo =
1122                                   gnutls_cipher_get_id(&broken_list[i][1]))
1123                                  != GNUTLS_CIPHER_UNKNOWN)
1124                                 fn(&(*priority_cache)->cipher, algo);
1125                         else if ((algo =
1126                                   gnutls_kx_get_id(&broken_list[i][1])) !=
1127                                  GNUTLS_KX_UNKNOWN)
1128                                 fn(&(*priority_cache)->kx, algo);
1129                         else if (strncasecmp
1130                                  (&broken_list[i][1], "VERS-", 5) == 0) {
1131                                 if (strncasecmp
1132                                     (&broken_list[i][1], "VERS-TLS-ALL",
1133                                      12) == 0) {
1134                                         bulk_given_fn(&(*priority_cache)->
1135                                                 protocol,
1136                                                 stream_protocol_priority);
1137                                 } else if (strncasecmp
1138                                         (&broken_list[i][1],
1139                                          "VERS-DTLS-ALL", 13) == 0) {
1140                                         bulk_given_fn(&(*priority_cache)->
1141                                                 protocol,
1142                                                 (bulk_given_fn==_add_priority)?dtls_protocol_priority:dgram_protocol_priority);
1143                                 } else if (strncasecmp
1144                                         (&broken_list[i][1],
1145                                          "VERS-ALL", 8) == 0) {
1146                                         bulk_fn(&(*priority_cache)->
1147                                                 protocol,
1148                                                 protocol_priority);
1149                                 } else {
1150                                         if ((algo =
1151                                              gnutls_protocol_get_id
1152                                              (&broken_list[i][6])) !=
1153                                             GNUTLS_VERSION_UNKNOWN)
1154                                                 fn(&(*priority_cache)->
1155                                                    protocol, algo);
1156                                         else
1157                                                 goto error;
1158
1159                                 }
1160                         } /* now check if the element is something like -ALGO */
1161                         else if (strncasecmp
1162                                  (&broken_list[i][1], "COMP-", 5) == 0) {
1163                                 if (strncasecmp
1164                                     (&broken_list[i][1], "COMP-ALL",
1165                                      8) == 0) {
1166                                         bulk_fn(&(*priority_cache)->
1167                                                 compression,
1168                                                 comp_priority);
1169                                 } else {
1170                                         if ((algo =
1171                                              gnutls_compression_get_id
1172                                              (&broken_list[i][6])) !=
1173                                             GNUTLS_COMP_UNKNOWN)
1174                                                 fn(&(*priority_cache)->
1175                                                    compression, algo);
1176                                         else
1177                                                 goto error;
1178                                 }
1179                         } /* now check if the element is something like -ALGO */
1180                         else if (strncasecmp
1181                                  (&broken_list[i][1], "CURVE-", 6) == 0) {
1182                                 if (strncasecmp
1183                                     (&broken_list[i][1], "CURVE-ALL",
1184                                      9) == 0) {
1185                                         bulk_fn(&(*priority_cache)->
1186                                                 supported_ecc,
1187                                                 supported_ecc_normal);
1188                                 } else {
1189                                         if ((algo =
1190                                              _gnutls_ecc_curve_get_id
1191                                              (&broken_list[i][7])) !=
1192                                             GNUTLS_ECC_CURVE_INVALID)
1193                                                 fn(&(*priority_cache)->
1194                                                    supported_ecc, algo);
1195                                         else
1196                                                 goto error;
1197                                 }
1198                         } /* now check if the element is something like -ALGO */
1199                         else if (strncasecmp
1200                                  (&broken_list[i][1], "CTYPE-", 6) == 0) {
1201                                 if (strncasecmp
1202                                     (&broken_list[i][1], "CTYPE-ALL",
1203                                      9) == 0) {
1204                                         bulk_fn(&(*priority_cache)->
1205                                                 cert_type,
1206                                                 cert_type_priority_all);
1207                                 } else {
1208                                         if ((algo =
1209                                              gnutls_certificate_type_get_id
1210                                              (&broken_list[i][7])) !=
1211                                             GNUTLS_CRT_UNKNOWN)
1212                                                 fn(&(*priority_cache)->
1213                                                    cert_type, algo);
1214                                         else
1215                                                 goto error;
1216                                 }
1217                         } /* now check if the element is something like -ALGO */
1218                         else if (strncasecmp
1219                                  (&broken_list[i][1], "SIGN-", 5) == 0) {
1220                                 if (strncasecmp
1221                                     (&broken_list[i][1], "SIGN-ALL",
1222                                      8) == 0) {
1223                                         bulk_fn(&(*priority_cache)->
1224                                                 sign_algo,
1225                                                 sign_priority_default);
1226                                 } else {
1227                                         if ((algo =
1228                                              gnutls_sign_get_id
1229                                              (&broken_list[i][6])) !=
1230                                             GNUTLS_SIGN_UNKNOWN)
1231                                                 fn(&(*priority_cache)->
1232                                                    sign_algo, algo);
1233                                         else
1234                                                 goto error;
1235                                 }
1236                         } else
1237                             if (strncasecmp
1238                                 (&broken_list[i][1], "MAC-ALL", 7) == 0) {
1239                                 bulk_fn(&(*priority_cache)->mac,
1240                                         mac_priority_normal);
1241                         } else
1242                             if (strncasecmp
1243                                 (&broken_list[i][1], "CIPHER-ALL",
1244                                  10) == 0) {
1245                                 bulk_fn(&(*priority_cache)->cipher,
1246                                         cipher_priority_normal);
1247                         } else
1248                             if (strncasecmp
1249                                 (&broken_list[i][1], "KX-ALL", 6) == 0) {
1250                                 bulk_fn(&(*priority_cache)->kx,
1251                                         kx_priority_secure);
1252                         } else
1253                                 goto error;
1254                 } else if (broken_list[i][0] == '%') {
1255                         const struct priority_options_st * o;
1256                         /* to add a new option modify
1257                          * priority_options.gperf */
1258                         o = in_word_set(&broken_list[i][1], strlen(&broken_list[i][1]));
1259                         if (o == NULL) {
1260                                 goto error;
1261                         }
1262                         o->func(*priority_cache);
1263                 } else
1264                         goto error;
1265         }
1266
1267         free(darg);
1268         return 0;
1269
1270       error:
1271         if (err_pos != NULL && i < broken_list_size) {
1272                 *err_pos = priorities;
1273                 for (j = 0; j < i; j++) {
1274                         (*err_pos) += strlen(broken_list[j]) + 1;
1275                 }
1276         }
1277         free(darg);
1278         gnutls_free(*priority_cache);
1279         *priority_cache = NULL;
1280
1281         return GNUTLS_E_INVALID_REQUEST;
1282
1283 }
1284
1285 /**
1286  * gnutls_priority_deinit:
1287  * @priority_cache: is a #gnutls_prioritity_t structure.
1288  *
1289  * Deinitializes the priority cache.
1290  **/
1291 void gnutls_priority_deinit(gnutls_priority_t priority_cache)
1292 {
1293         gnutls_free(priority_cache);
1294 }
1295
1296
1297 /**
1298  * gnutls_priority_set_direct:
1299  * @session: is a #gnutls_session_t structure.
1300  * @priorities: is a string describing priorities
1301  * @err_pos: In case of an error this will have the position in the string the error occured
1302  *
1303  * Sets the priorities to use on the ciphers, key exchange methods,
1304  * macs and compression methods.  This function avoids keeping a
1305  * priority cache and is used to directly set string priorities to a
1306  * TLS session.  For documentation check the gnutls_priority_init().
1307  *
1308  * To simply use a reasonable default, consider using gnutls_set_default_priority().
1309  *
1310  * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
1311  * %GNUTLS_E_SUCCESS on success, or an error code.
1312  **/
1313 int
1314 gnutls_priority_set_direct(gnutls_session_t session,
1315                            const char *priorities, const char **err_pos)
1316 {
1317         gnutls_priority_t prio;
1318         int ret;
1319
1320         ret = gnutls_priority_init(&prio, priorities, err_pos);
1321         if (ret < 0) {
1322                 gnutls_assert();
1323                 return ret;
1324         }
1325
1326         ret = gnutls_priority_set(session, prio);
1327         if (ret < 0) {
1328                 gnutls_assert();
1329                 return ret;
1330         }
1331
1332         gnutls_priority_deinit(prio);
1333
1334         return 0;
1335 }
1336
1337 /* Breaks a list of "xxx", "yyy", to a character array, of
1338  * MAX_COMMA_SEP_ELEMENTS size; Note that the given string is modified.
1339   */
1340 static void
1341 break_list(char *list,
1342                  char *broken_list[MAX_ELEMENTS], int *size)
1343 {
1344         char *p = list;
1345
1346         *size = 0;
1347
1348         do {
1349                 broken_list[*size] = p;
1350
1351                 (*size)++;
1352
1353                 p = strchr(p, ':');
1354                 if (p) {
1355                         *p = 0;
1356                         p++;    /* move to next entry and skip white
1357                                  * space.
1358                                  */
1359                         while (*p == ' ')
1360                                 p++;
1361                 }
1362         }
1363         while (p != NULL && *size < MAX_ELEMENTS);
1364 }
1365
1366 /**
1367  * gnutls_set_default_priority:
1368  * @session: is a #gnutls_session_t structure.
1369  *
1370  * Sets some default priority on the ciphers, key exchange methods,
1371  * macs and compression methods.
1372  *
1373  * This typically sets a default priority that is considered
1374  * sufficiently secure to establish encrypted sessions.
1375  *
1376  * This function is kept around for backwards compatibility, but
1377  * because of its wide use it is still fully supported.  If you wish
1378  * to allow users to provide a string that specify which ciphers to
1379  * use (which is recommended), you should use
1380  * gnutls_priority_set_direct() or gnutls_priority_set() instead.
1381  *
1382  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
1383  **/
1384 int gnutls_set_default_priority(gnutls_session_t session)
1385 {
1386         return gnutls_priority_set_direct(session, NULL, NULL);
1387 }
1388
1389 /**
1390  * gnutls_priority_ecc_curve_list:
1391  * @pcache: is a #gnutls_prioritity_t structure.
1392  * @list: will point to an integer list
1393  *
1394  * Get a list of available elliptic curves in the priority
1395  * structure. 
1396  *
1397  * Returns: the number of curves, or an error code.
1398  * Since: 3.0
1399  **/
1400 int
1401 gnutls_priority_ecc_curve_list(gnutls_priority_t pcache,
1402                                const unsigned int **list)
1403 {
1404         if (pcache->supported_ecc.algorithms == 0)
1405                 return 0;
1406
1407         *list = pcache->supported_ecc.priority;
1408         return pcache->supported_ecc.algorithms;
1409 }
1410
1411 /**
1412  * gnutls_priority_kx_list:
1413  * @pcache: is a #gnutls_prioritity_t structure.
1414  * @list: will point to an integer list
1415  *
1416  * Get a list of available key exchange methods in the priority
1417  * structure. 
1418  *
1419  * Returns: the number of curves, or an error code.
1420  * Since: 3.2.3
1421  **/
1422 int
1423 gnutls_priority_kx_list(gnutls_priority_t pcache,
1424                         const unsigned int **list)
1425 {
1426         if (pcache->kx.algorithms == 0)
1427                 return 0;
1428
1429         *list = pcache->kx.priority;
1430         return pcache->kx.algorithms;
1431 }
1432
1433 /**
1434  * gnutls_priority_cipher_list:
1435  * @pcache: is a #gnutls_prioritity_t structure.
1436  * @list: will point to an integer list
1437  *
1438  * Get a list of available ciphers in the priority
1439  * structure. 
1440  *
1441  * Returns: the number of curves, or an error code.
1442  * Since: 3.2.3
1443  **/
1444 int
1445 gnutls_priority_cipher_list(gnutls_priority_t pcache,
1446                             const unsigned int **list)
1447 {
1448         if (pcache->cipher.algorithms == 0)
1449                 return 0;
1450
1451         *list = pcache->cipher.priority;
1452         return pcache->cipher.algorithms;
1453 }
1454
1455 /**
1456  * gnutls_priority_mac_list:
1457  * @pcache: is a #gnutls_prioritity_t structure.
1458  * @list: will point to an integer list
1459  *
1460  * Get a list of available MAC algorithms in the priority
1461  * structure. 
1462  *
1463  * Returns: the number of curves, or an error code.
1464  * Since: 3.2.3
1465  **/
1466 int
1467 gnutls_priority_mac_list(gnutls_priority_t pcache,
1468                          const unsigned int **list)
1469 {
1470         if (pcache->mac.algorithms == 0)
1471                 return 0;
1472
1473         *list = pcache->mac.priority;
1474         return pcache->mac.algorithms;
1475 }
1476
1477 /**
1478  * gnutls_priority_compression_list:
1479  * @pcache: is a #gnutls_prioritity_t structure.
1480  * @list: will point to an integer list
1481  *
1482  * Get a list of available compression method in the priority
1483  * structure. 
1484  *
1485  * Returns: the number of methods, or an error code.
1486  * Since: 3.0
1487  **/
1488 int
1489 gnutls_priority_compression_list(gnutls_priority_t pcache,
1490                                  const unsigned int **list)
1491 {
1492         if (pcache->compression.algorithms == 0)
1493                 return 0;
1494
1495         *list = pcache->compression.priority;
1496         return pcache->compression.algorithms;
1497 }
1498
1499 /**
1500  * gnutls_priority_protocol_list:
1501  * @pcache: is a #gnutls_prioritity_t structure.
1502  * @list: will point to an integer list
1503  *
1504  * Get a list of available TLS version numbers in the priority
1505  * structure. 
1506  *
1507  * Returns: the number of protocols, or an error code.
1508  * Since: 3.0
1509  **/
1510 int
1511 gnutls_priority_protocol_list(gnutls_priority_t pcache,
1512                               const unsigned int **list)
1513 {
1514         if (pcache->protocol.algorithms == 0)
1515                 return 0;
1516
1517         *list = pcache->protocol.priority;
1518         return pcache->protocol.algorithms;
1519 }
1520
1521 /**
1522  * gnutls_priority_sign_list:
1523  * @pcache: is a #gnutls_prioritity_t structure.
1524  * @list: will point to an integer list
1525  *
1526  * Get a list of available signature algorithms in the priority
1527  * structure. 
1528  *
1529  * Returns: the number of algorithms, or an error code.
1530  * Since: 3.0
1531  **/
1532 int
1533 gnutls_priority_sign_list(gnutls_priority_t pcache,
1534                           const unsigned int **list)
1535 {
1536         if (pcache->sign_algo.algorithms == 0)
1537                 return 0;
1538
1539         *list = pcache->sign_algo.priority;
1540         return pcache->sign_algo.algorithms;
1541 }
1542
1543 /**
1544  * gnutls_priority_certificate_type_list:
1545  * @pcache: is a #gnutls_prioritity_t structure.
1546  * @list: will point to an integer list
1547  *
1548  * Get a list of available certificate types in the priority
1549  * structure. 
1550  *
1551  * Returns: the number of certificate types, or an error code.
1552  * Since: 3.0
1553  **/
1554 int
1555 gnutls_priority_certificate_type_list(gnutls_priority_t pcache,
1556                                       const unsigned int **list)
1557 {
1558         if (pcache->cert_type.algorithms == 0)
1559                 return 0;
1560
1561         *list = pcache->cert_type.priority;
1562         return pcache->cert_type.algorithms;
1563 }
1564
1565 /**
1566  * gnutls_priority_string_list:
1567  * @iter: an integer counter starting from zero
1568  * @flags: one of %GNUTLS_PRIORITY_LIST_INIT_KEYWORDS, %GNUTLS_PRIORITY_LIST_SPECIAL
1569  *
1570  * Can be used to iterate all available priority strings.
1571  * Due to internal implementation details, there are cases where this
1572  * function can return the empty string. In that case that string should be ignored.
1573  * When no strings are available it returns %NULL.
1574  *
1575  * Returns: a priority string
1576  * Since: 3.4.0
1577  **/
1578 const char *
1579 gnutls_priority_string_list(unsigned iter, unsigned int flags)
1580 {
1581         if (flags & GNUTLS_PRIORITY_LIST_INIT_KEYWORDS) {
1582                 if (iter >= (sizeof(pgroups)/sizeof(pgroups[0]))-1)
1583                         return NULL;
1584                 return pgroups[iter].name;
1585         } else if (flags & GNUTLS_PRIORITY_LIST_SPECIAL) {
1586                 if (iter >= (sizeof(wordlist)/sizeof(wordlist[0]))-1)
1587                         return NULL;
1588                 return wordlist[iter].name;
1589         }
1590         return NULL;
1591 }