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