corrected copyright notices
[gnutls.git] / lib / gnutls_priority.c
blob03ef83bf3cac79b07cad71308d05fddd430ca5f8
1 /*
2 * Copyright (C) 2004-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
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 3 of
11 * the License, or (at your option) any later version.
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.
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/>
23 /* Here lies the code of the gnutls_*_set_priority() functions.
26 #include "gnutls_int.h"
27 #include "algorithms.h"
28 #include "gnutls_errors.h"
29 #include <gnutls_num.h>
31 static void
32 break_comma_list (char *etag,
33 char **broken_etag, int *elements, int max_elements,
34 char sep);
36 /**
37 * gnutls_cipher_set_priority:
38 * @session: is a #gnutls_session_t structure.
39 * @list: is a 0 terminated list of gnutls_cipher_algorithm_t elements.
41 * Sets the priority on the ciphers supported by gnutls. Priority is
42 * higher for elements specified before others. After specifying the
43 * ciphers you want, you must append a 0. Note that the priority is
44 * set on the client. The server does not use the algorithm's
45 * priority except for disabling algorithms that were not specified.
47 * Returns: %GNUTLS_E_SUCCESS (0) on success, or a negative error code.
48 **/
49 int
50 gnutls_cipher_set_priority (gnutls_session_t session, const int *list)
52 int num = 0, i;
54 while (list[num] != 0)
55 num++;
56 if (num > MAX_ALGOS)
57 num = MAX_ALGOS;
58 session->internals.priorities.cipher.algorithms = num;
60 for (i = 0; i < num; i++)
62 session->internals.priorities.cipher.priority[i] = list[i];
65 return 0;
68 typedef void (bulk_rmadd_func) (priority_st * priority_list, const int *);
70 inline static void
71 _set_priority (priority_st * st, const int *list)
73 int num = 0, i;
75 while (list[num] != 0)
76 num++;
77 if (num > MAX_ALGOS)
78 num = MAX_ALGOS;
79 st->algorithms = num;
81 for (i = 0; i < num; i++)
83 st->priority[i] = list[i];
86 return;
89 inline static void
90 _add_priority (priority_st * st, const int *list)
92 int num, i, j, init;
94 init = i = st->algorithms;
96 for (num=0;list[num]!=0;++num)
98 if (i+1 > MAX_ALGOS)
100 return;
103 for (j=0;j<init;j++)
105 if (st->priority[j] == (unsigned)list[num])
107 break;
111 if (j == init)
113 st->priority[i++] = list[num];
114 st->algorithms++;
118 return;
121 static void
122 _clear_priorities (priority_st * st, const int *list)
124 memset(st, 0, sizeof(*st));
128 * gnutls_kx_set_priority:
129 * @session: is a #gnutls_session_t structure.
130 * @list: is a 0 terminated list of gnutls_kx_algorithm_t elements.
132 * Sets the priority on the key exchange algorithms supported by
133 * gnutls. Priority is higher for elements specified before others.
134 * After specifying the algorithms you want, you must append a 0.
135 * Note that the priority is set on the client. The server does not
136 * use the algorithm's priority except for disabling algorithms that
137 * were not specified.
139 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
142 gnutls_kx_set_priority (gnutls_session_t session, const int *list)
144 _set_priority (&session->internals.priorities.kx, list);
145 return 0;
149 * gnutls_mac_set_priority:
150 * @session: is a #gnutls_session_t structure.
151 * @list: is a 0 terminated list of gnutls_mac_algorithm_t elements.
153 * Sets the priority on the mac algorithms supported by gnutls.
154 * Priority is higher for elements specified before others. After
155 * specifying the algorithms you want, you must append a 0. Note
156 * that the priority is set on the client. The server does not use
157 * the algorithm's priority except for disabling algorithms that were
158 * not specified.
160 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
163 gnutls_mac_set_priority (gnutls_session_t session, const int *list)
165 _set_priority (&session->internals.priorities.mac, list);
166 return 0;
170 * gnutls_compression_set_priority:
171 * @session: is a #gnutls_session_t structure.
172 * @list: is a 0 terminated list of gnutls_compression_method_t elements.
174 * Sets the priority on the compression algorithms supported by
175 * gnutls. Priority is higher for elements specified before others.
176 * After specifying the algorithms you want, you must append a 0.
177 * Note that the priority is set on the client. The server does not
178 * use the algorithm's priority except for disabling algorithms that
179 * were not specified.
181 * TLS 1.0 does not define any compression algorithms except
182 * NULL. Other compression algorithms are to be considered as gnutls
183 * extensions.
185 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
188 gnutls_compression_set_priority (gnutls_session_t session, const int *list)
190 _set_priority (&session->internals.priorities.compression, list);
191 return 0;
195 * gnutls_protocol_set_priority:
196 * @session: is a #gnutls_session_t structure.
197 * @list: is a 0 terminated list of gnutls_protocol_t elements.
199 * Sets the priority on the protocol versions supported by gnutls.
200 * This function actually enables or disables protocols. Newer protocol
201 * versions always have highest priority.
203 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
206 gnutls_protocol_set_priority (gnutls_session_t session, const int *list)
208 _set_priority (&session->internals.priorities.protocol, list);
210 /* set the current version to the first in the chain.
211 * This will be overridden later.
213 if (list)
214 _gnutls_set_current_version (session, list[0]);
216 return 0;
220 * gnutls_certificate_type_set_priority:
221 * @session: is a #gnutls_session_t structure.
222 * @list: is a 0 terminated list of gnutls_certificate_type_t elements.
224 * Sets the priority on the certificate types supported by gnutls.
225 * Priority is higher for elements specified before others.
226 * After specifying the types you want, you must append a 0.
227 * Note that the certificate type priority is set on the client.
228 * The server does not use the cert type priority except for disabling
229 * types that were not specified.
231 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
234 gnutls_certificate_type_set_priority (gnutls_session_t session,
235 const int *list)
237 #ifdef ENABLE_OPENPGP
238 _set_priority (&session->internals.priorities.cert_type, list);
239 return 0;
240 #else
242 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
244 #endif
247 static const int supported_ecc_normal[] = {
248 GNUTLS_ECC_CURVE_SECP192R1,
249 GNUTLS_ECC_CURVE_SECP224R1,
250 GNUTLS_ECC_CURVE_SECP256R1,
251 GNUTLS_ECC_CURVE_SECP384R1,
252 GNUTLS_ECC_CURVE_SECP521R1,
256 static const int supported_ecc_secure128[] = {
257 GNUTLS_ECC_CURVE_SECP256R1,
258 GNUTLS_ECC_CURVE_SECP384R1,
259 GNUTLS_ECC_CURVE_SECP521R1,
263 static const int supported_ecc_suiteb128[] = {
264 GNUTLS_ECC_CURVE_SECP256R1,
265 GNUTLS_ECC_CURVE_SECP384R1,
269 static const int supported_ecc_suiteb192[] = {
270 GNUTLS_ECC_CURVE_SECP384R1,
274 static const int supported_ecc_secure192[] = {
275 GNUTLS_ECC_CURVE_SECP384R1,
276 GNUTLS_ECC_CURVE_SECP521R1,
280 static const int protocol_priority[] = {
281 GNUTLS_TLS1_2,
282 GNUTLS_TLS1_1,
283 GNUTLS_TLS1_0,
284 GNUTLS_SSL3,
285 GNUTLS_DTLS1_0,
289 static const int protocol_priority_suiteb[] = {
290 GNUTLS_TLS1_2,
294 static const int kx_priority_performance[] = {
295 GNUTLS_KX_RSA,
296 GNUTLS_KX_ECDHE_ECDSA,
297 GNUTLS_KX_ECDHE_RSA,
298 GNUTLS_KX_DHE_RSA,
299 GNUTLS_KX_DHE_DSS,
303 static const int kx_priority_suiteb[] = {
304 GNUTLS_KX_ECDHE_ECDSA,
308 static const int kx_priority_export[] = {
309 GNUTLS_KX_RSA,
310 GNUTLS_KX_ECDHE_ECDSA,
311 GNUTLS_KX_ECDHE_RSA,
312 GNUTLS_KX_DHE_RSA,
313 GNUTLS_KX_DHE_DSS,
314 GNUTLS_KX_RSA_EXPORT,
318 static const int kx_priority_secure[] = {
319 /* The ciphersuites that offer forward secrecy take
320 * precedence
322 GNUTLS_KX_ECDHE_ECDSA,
323 GNUTLS_KX_ECDHE_RSA,
324 GNUTLS_KX_DHE_RSA,
325 GNUTLS_KX_DHE_DSS,
326 GNUTLS_KX_RSA,
327 /* GNUTLS_KX_ANON_DH: Man-in-the-middle prone, don't add!
328 * GNUTLS_KX_RSA_EXPORT: Deprecated, don't add!
333 static const int cipher_priority_performance_sw[] = {
334 GNUTLS_CIPHER_ARCFOUR_128,
335 GNUTLS_CIPHER_AES_128_CBC,
336 GNUTLS_CIPHER_CAMELLIA_128_CBC,
337 GNUTLS_CIPHER_AES_256_CBC,
338 GNUTLS_CIPHER_CAMELLIA_256_CBC,
339 GNUTLS_CIPHER_3DES_CBC,
340 GNUTLS_CIPHER_AES_128_GCM,
341 GNUTLS_CIPHER_AES_256_GCM,
345 /* If GCM and AES acceleration is available then prefer
346 * them over anything else.
348 static const int cipher_priority_performance_hw_aes[] = {
349 GNUTLS_CIPHER_AES_128_GCM,
350 GNUTLS_CIPHER_AES_128_CBC,
351 GNUTLS_CIPHER_AES_256_GCM,
352 GNUTLS_CIPHER_AES_256_CBC,
353 GNUTLS_CIPHER_ARCFOUR_128,
354 GNUTLS_CIPHER_CAMELLIA_128_CBC,
355 GNUTLS_CIPHER_CAMELLIA_256_CBC,
356 GNUTLS_CIPHER_3DES_CBC,
360 static const int cipher_priority_normal_sw[] = {
361 GNUTLS_CIPHER_AES_128_CBC,
362 GNUTLS_CIPHER_CAMELLIA_128_CBC,
363 GNUTLS_CIPHER_AES_128_GCM,
364 GNUTLS_CIPHER_AES_256_CBC,
365 GNUTLS_CIPHER_CAMELLIA_256_CBC,
366 GNUTLS_CIPHER_AES_256_GCM,
367 GNUTLS_CIPHER_3DES_CBC,
368 GNUTLS_CIPHER_ARCFOUR_128,
372 static const int cipher_priority_normal_hw_aes[] = {
373 GNUTLS_CIPHER_AES_128_GCM,
374 GNUTLS_CIPHER_AES_128_CBC,
375 GNUTLS_CIPHER_AES_256_GCM,
376 GNUTLS_CIPHER_AES_256_CBC,
377 GNUTLS_CIPHER_CAMELLIA_128_CBC,
378 GNUTLS_CIPHER_CAMELLIA_256_CBC,
379 GNUTLS_CIPHER_3DES_CBC,
380 GNUTLS_CIPHER_ARCFOUR_128,
384 static const int *cipher_priority_performance = cipher_priority_performance_sw;
385 static const int *cipher_priority_normal = cipher_priority_normal_sw;
388 static const int cipher_priority_suiteb128[] = {
389 GNUTLS_CIPHER_AES_128_GCM,
390 GNUTLS_CIPHER_AES_256_GCM,
394 static const int cipher_priority_suiteb192[] = {
395 GNUTLS_CIPHER_AES_256_GCM,
400 static const int cipher_priority_secure128[] = {
401 GNUTLS_CIPHER_AES_128_CBC,
402 GNUTLS_CIPHER_CAMELLIA_128_CBC,
403 GNUTLS_CIPHER_AES_128_GCM,
404 GNUTLS_CIPHER_AES_256_CBC,
405 GNUTLS_CIPHER_CAMELLIA_256_CBC,
406 GNUTLS_CIPHER_AES_256_GCM,
411 static const int cipher_priority_secure192[] = {
412 GNUTLS_CIPHER_AES_256_CBC,
413 GNUTLS_CIPHER_CAMELLIA_256_CBC,
414 GNUTLS_CIPHER_AES_256_GCM,
418 /* The same as cipher_priority_security_normal + arcfour-40. */
419 static const int cipher_priority_export[] = {
420 GNUTLS_CIPHER_AES_128_CBC,
421 GNUTLS_CIPHER_AES_256_CBC,
422 GNUTLS_CIPHER_CAMELLIA_128_CBC,
423 GNUTLS_CIPHER_CAMELLIA_256_CBC,
424 GNUTLS_CIPHER_AES_128_GCM,
425 GNUTLS_CIPHER_3DES_CBC,
426 GNUTLS_CIPHER_ARCFOUR_128,
427 GNUTLS_CIPHER_ARCFOUR_40,
431 static const int comp_priority[] = {
432 /* compression should be explicitly requested to be enabled */
433 GNUTLS_COMP_NULL,
437 static const int sign_priority_default[] = {
438 GNUTLS_SIGN_RSA_SHA256,
439 GNUTLS_SIGN_DSA_SHA256,
440 GNUTLS_SIGN_ECDSA_SHA256,
442 GNUTLS_SIGN_RSA_SHA384,
443 GNUTLS_SIGN_ECDSA_SHA384,
445 GNUTLS_SIGN_RSA_SHA512,
446 GNUTLS_SIGN_ECDSA_SHA512,
448 GNUTLS_SIGN_RSA_SHA224,
449 GNUTLS_SIGN_DSA_SHA224,
450 GNUTLS_SIGN_ECDSA_SHA224,
452 GNUTLS_SIGN_RSA_SHA1,
453 GNUTLS_SIGN_DSA_SHA1,
454 GNUTLS_SIGN_ECDSA_SHA1,
458 static const int sign_priority_suiteb128[] = {
459 GNUTLS_SIGN_ECDSA_SHA256,
460 GNUTLS_SIGN_ECDSA_SHA384,
464 static const int sign_priority_suiteb192[] = {
465 GNUTLS_SIGN_ECDSA_SHA384,
469 static const int sign_priority_secure128[] = {
470 GNUTLS_SIGN_RSA_SHA256,
471 GNUTLS_SIGN_DSA_SHA256,
472 GNUTLS_SIGN_ECDSA_SHA256,
473 GNUTLS_SIGN_RSA_SHA384,
474 GNUTLS_SIGN_ECDSA_SHA384,
475 GNUTLS_SIGN_RSA_SHA512,
476 GNUTLS_SIGN_ECDSA_SHA512,
480 static const int sign_priority_secure192[] = {
481 GNUTLS_SIGN_RSA_SHA384,
482 GNUTLS_SIGN_ECDSA_SHA384,
483 GNUTLS_SIGN_RSA_SHA512,
484 GNUTLS_SIGN_ECDSA_SHA512,
488 static const int mac_priority_normal[] = {
489 GNUTLS_MAC_SHA1,
490 GNUTLS_MAC_SHA256,
491 GNUTLS_MAC_SHA384,
492 GNUTLS_MAC_AEAD,
493 GNUTLS_MAC_MD5,
497 static const int mac_priority_suiteb128[] = {
498 GNUTLS_MAC_AEAD,
502 static const int mac_priority_suiteb192[] = {
503 GNUTLS_MAC_AEAD,
507 static const int mac_priority_secure128[] = {
508 GNUTLS_MAC_SHA1,
509 GNUTLS_MAC_SHA256,
510 GNUTLS_MAC_SHA384,
511 GNUTLS_MAC_AEAD,
515 static const int mac_priority_secure192[] = {
516 GNUTLS_MAC_SHA256,
517 GNUTLS_MAC_SHA384,
518 GNUTLS_MAC_AEAD,
522 static const int cert_type_priority_default[] = {
523 GNUTLS_CRT_X509,
527 static const int cert_type_priority_all[] = {
528 GNUTLS_CRT_X509,
529 GNUTLS_CRT_OPENPGP,
533 typedef void (rmadd_func) (priority_st * priority_list, unsigned int alg);
535 static void
536 prio_remove (priority_st * priority_list, unsigned int algo)
538 int i = 0;
539 int pos = -1; /* the position of the cipher to remove */
541 while (priority_list->priority[i] != 0)
543 if (priority_list->priority[i] == algo)
544 pos = i;
545 i++;
548 if (pos >= 0)
550 priority_list->priority[pos] = priority_list->priority[i - 1];
551 priority_list->priority[i - 1] = 0;
552 priority_list->algorithms--;
555 return;
558 static void
559 prio_add (priority_st * priority_list, unsigned int algo)
561 register int i = 0;
562 while (priority_list->priority[i] != 0)
564 if (algo == priority_list->priority[i])
565 return; /* if it exists */
566 i++;
569 if (i < MAX_ALGOS)
571 priority_list->priority[i] = algo;
572 priority_list->algorithms++;
575 return;
580 * gnutls_priority_set:
581 * @session: is a #gnutls_session_t structure.
582 * @priority: is a #gnutls_priority_t structure.
584 * Sets the priorities to use on the ciphers, key exchange methods,
585 * macs and compression methods.
587 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
590 gnutls_priority_set (gnutls_session_t session, gnutls_priority_t priority)
592 if (priority == NULL)
594 gnutls_assert ();
595 return GNUTLS_E_NO_CIPHER_SUITES;
598 memcpy (&session->internals.priorities, priority,
599 sizeof (struct gnutls_priority_st));
601 /* set the current version to the first in the chain.
602 * This will be overridden later.
604 if (session->internals.priorities.protocol.algorithms > 0)
605 _gnutls_set_current_version (session,
606 session->internals.priorities.protocol.
607 priority[0]);
609 if (session->internals.priorities.protocol.algorithms == 0 ||
610 session->internals.priorities.cipher.algorithms == 0 ||
611 session->internals.priorities.mac.algorithms == 0 ||
612 session->internals.priorities.kx.algorithms == 0 ||
613 session->internals.priorities.compression.algorithms == 0)
614 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
616 return 0;
620 #define MAX_ELEMENTS 48
622 #define LEVEL_NONE "NONE"
623 #define LEVEL_NORMAL "NORMAL"
624 #define LEVEL_PERFORMANCE "PERFORMANCE"
625 #define LEVEL_SECURE128 "SECURE128"
626 #define LEVEL_SECURE192 "SECURE192"
627 #define LEVEL_SECURE256 "SECURE256"
628 #define LEVEL_SUITEB128 "SUITEB128"
629 #define LEVEL_SUITEB192 "SUITEB192"
630 #define LEVEL_EXPORT "EXPORT"
632 static
633 int check_level(const char* level, gnutls_priority_t priority_cache, int add)
635 bulk_rmadd_func *func;
637 if (add) func = _add_priority;
638 else func = _set_priority;
640 if (strcasecmp (level, LEVEL_PERFORMANCE) == 0)
642 func (&priority_cache->cipher,
643 cipher_priority_performance);
644 func (&priority_cache->kx, kx_priority_performance);
645 func (&priority_cache->mac, mac_priority_normal);
646 func (&priority_cache->sign_algo,
647 sign_priority_default);
648 func (&priority_cache->supported_ecc, supported_ecc_normal);
649 return 1;
651 else if (strcasecmp (level, LEVEL_NORMAL) == 0)
653 func (&priority_cache->cipher, cipher_priority_normal);
654 func (&priority_cache->kx, kx_priority_secure);
655 func (&priority_cache->mac, mac_priority_normal);
656 func (&priority_cache->sign_algo,
657 sign_priority_default);
658 func (&priority_cache->supported_ecc, supported_ecc_normal);
659 return 1;
661 else if (strcasecmp (level, LEVEL_SECURE256) == 0
662 || strcasecmp (level, LEVEL_SECURE192) == 0)
664 func (&priority_cache->cipher,
665 cipher_priority_secure192);
666 func (&priority_cache->kx, kx_priority_secure);
667 func (&priority_cache->mac, mac_priority_secure192);
668 func (&priority_cache->sign_algo,
669 sign_priority_secure192);
670 func (&priority_cache->supported_ecc, supported_ecc_secure192);
671 return 1;
673 else if (strcasecmp (level, LEVEL_SECURE128) == 0
674 || strcasecmp (level, "SECURE") == 0)
676 func (&priority_cache->cipher,
677 cipher_priority_secure128);
678 func (&priority_cache->kx, kx_priority_secure);
679 func (&priority_cache->mac, mac_priority_secure128);
680 func (&priority_cache->sign_algo,
681 sign_priority_secure128);
682 func (&priority_cache->supported_ecc, supported_ecc_secure128);
683 return 1;
685 else if (strcasecmp (level, LEVEL_SUITEB128) == 0)
687 func (&priority_cache->protocol, protocol_priority_suiteb);
688 func (&priority_cache->cipher,
689 cipher_priority_suiteb128);
690 func (&priority_cache->kx, kx_priority_suiteb);
691 func (&priority_cache->mac, mac_priority_suiteb128);
692 func (&priority_cache->sign_algo,
693 sign_priority_suiteb128);
694 func (&priority_cache->supported_ecc, supported_ecc_suiteb128);
695 return 1;
697 else if (strcasecmp (level, LEVEL_SUITEB192) == 0)
699 func (&priority_cache->protocol, protocol_priority_suiteb);
700 func (&priority_cache->cipher,
701 cipher_priority_suiteb192);
702 func (&priority_cache->kx, kx_priority_suiteb);
703 func (&priority_cache->mac, mac_priority_suiteb192);
704 func (&priority_cache->sign_algo,
705 sign_priority_suiteb192);
706 func (&priority_cache->supported_ecc, supported_ecc_suiteb192);
707 return 1;
709 else if (strcasecmp (level, LEVEL_EXPORT) == 0)
711 func (&priority_cache->cipher, cipher_priority_export);
712 func (&priority_cache->kx, kx_priority_export);
713 func (&priority_cache->mac, mac_priority_secure128);
714 func (&priority_cache->sign_algo,
715 sign_priority_default);
716 func (&priority_cache->supported_ecc, supported_ecc_normal);
717 return 1;
719 return 0;
723 * gnutls_priority_init:
724 * @priority_cache: is a #gnutls_prioritity_t structure.
725 * @priorities: is a string describing priorities
726 * @err_pos: In case of an error this will have the position in the string the error occured
728 * Sets priorities for the ciphers, key exchange methods, macs and
729 * compression methods.
731 * The #priorities option allows you to specify a colon
732 * separated list of the cipher priorities to enable.
733 * Some keywords are defined to provide quick access
734 * to common preferences.
736 * "PERFORMANCE" means all the "secure" ciphersuites are enabled,
737 * limited to 128 bit ciphers and sorted by terms of speed
738 * performance.
740 * "NORMAL" means all "secure" ciphersuites. The 256-bit ciphers are
741 * included as a fallback only. The ciphers are sorted by security
742 * margin.
744 * "SECURE128" means all "secure" ciphersuites of security level 128-bit
745 * or more.
747 * "SECURE192" means all "secure" ciphersuites of security level 192-bit
748 * or more.
750 * "SUITEB128" means all the NSA SuiteB ciphersuites with security level
751 * of 128.
753 * "SUITEB192" means all the NSA SuiteB ciphersuites with security level
754 * of 192.
756 * "EXPORT" means all ciphersuites are enabled, including the
757 * low-security 40 bit ciphers.
759 * "NONE" means nothing is enabled. This disables even protocols and
760 * compression methods.
762 * Special keywords are "!", "-" and "+".
763 * "!" or "-" appended with an algorithm will remove this algorithm.
764 * "+" appended with an algorithm will add this algorithm.
766 * Check the GnuTLS manual section "Priority strings" for detailed
767 * information.
769 * Examples:
771 * "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"
773 * "NORMAL:-ARCFOUR-128" means normal ciphers except for ARCFOUR-128.
775 * "SECURE:-VERS-SSL3.0:+COMP-DEFLATE" means that only secure ciphers are
776 * enabled, SSL3.0 is disabled, and libz compression enabled.
778 * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1",
780 * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+ECDHE-RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1:+CURVE-SECP256R1",
782 * "SECURE256:+SECURE128",
784 * Note that "NORMAL:%COMPAT" is the most compatible mode.
786 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
787 * %GNUTLS_E_SUCCESS on success, or an error code.
790 gnutls_priority_init (gnutls_priority_t * priority_cache,
791 const char *priorities, const char **err_pos)
793 char *broken_list[MAX_ELEMENTS];
794 int broken_list_size = 0, i = 0, j;
795 char *darg = NULL;
796 int algo;
797 rmadd_func *fn;
798 bulk_rmadd_func *bulk_fn;
800 *priority_cache = gnutls_calloc (1, sizeof (struct gnutls_priority_st));
801 if (*priority_cache == NULL)
803 gnutls_assert ();
804 return GNUTLS_E_MEMORY_ERROR;
807 /* for now unsafe renegotiation is default on everyone. To be removed
808 * when we make it the default.
810 (*priority_cache)->sr = SR_PARTIAL;
811 (*priority_cache)->ssl3_record_version = 1;
813 if (priorities == NULL)
814 priorities = LEVEL_NORMAL;
816 darg = gnutls_strdup (priorities);
817 if (darg == NULL)
819 gnutls_assert ();
820 goto error;
823 break_comma_list (darg, broken_list, &broken_list_size, MAX_ELEMENTS, ':');
824 /* This is our default set of protocol version, certificate types and
825 * compression methods.
827 if (strcasecmp (broken_list[0], LEVEL_NONE) != 0)
829 _set_priority (&(*priority_cache)->protocol, protocol_priority);
830 _set_priority (&(*priority_cache)->compression, comp_priority);
831 _set_priority (&(*priority_cache)->cert_type, cert_type_priority_default);
832 _set_priority (&(*priority_cache)->sign_algo, sign_priority_default);
833 _set_priority (&(*priority_cache)->supported_ecc, supported_ecc_normal);
834 i = 0;
836 else
838 i = 1;
841 for (; i < broken_list_size; i++)
843 if (check_level(broken_list[i], *priority_cache, 0) != 0)
845 continue;
847 else if (broken_list[i][0] == '!' || broken_list[i][0] == '+'
848 || broken_list[i][0] == '-')
850 if (broken_list[i][0] == '+')
852 fn = prio_add;
853 bulk_fn = _set_priority;
855 else
857 fn = prio_remove;
858 bulk_fn = _clear_priorities;
861 if (broken_list[i][0] == '+' && check_level(&broken_list[i][1], *priority_cache, 1) != 0)
863 continue;
865 else if ((algo =
866 gnutls_mac_get_id (&broken_list[i][1])) != GNUTLS_MAC_UNKNOWN)
867 fn (&(*priority_cache)->mac, algo);
868 else if ((algo = gnutls_cipher_get_id (&broken_list[i][1])) !=
869 GNUTLS_CIPHER_UNKNOWN)
870 fn (&(*priority_cache)->cipher, algo);
871 else if ((algo = gnutls_kx_get_id (&broken_list[i][1])) !=
872 GNUTLS_KX_UNKNOWN)
873 fn (&(*priority_cache)->kx, algo);
874 else if (strncasecmp (&broken_list[i][1], "VERS-", 5) == 0)
876 if (strncasecmp (&broken_list[i][1], "VERS-TLS-ALL", 12) == 0)
878 bulk_fn (&(*priority_cache)->protocol,
879 protocol_priority);
881 else
883 if ((algo =
884 gnutls_protocol_get_id (&broken_list[i][6])) !=
885 GNUTLS_VERSION_UNKNOWN)
886 fn (&(*priority_cache)->protocol, algo);
887 else
888 goto error;
891 } /* now check if the element is something like -ALGO */
892 else if (strncasecmp (&broken_list[i][1], "COMP-", 5) == 0)
894 if (strncasecmp (&broken_list[i][1], "COMP-ALL", 8) == 0)
896 bulk_fn (&(*priority_cache)->compression,
897 comp_priority);
899 else
901 if ((algo =
902 gnutls_compression_get_id (&broken_list[i][6])) !=
903 GNUTLS_COMP_UNKNOWN)
904 fn (&(*priority_cache)->compression, algo);
905 else
906 goto error;
908 } /* now check if the element is something like -ALGO */
909 else if (strncasecmp (&broken_list[i][1], "CURVE-", 6) == 0)
911 if (strncasecmp (&broken_list[i][1], "CURVE-ALL", 9) == 0)
913 bulk_fn (&(*priority_cache)->supported_ecc,
914 supported_ecc_normal);
916 else
918 if ((algo =
919 _gnutls_ecc_curve_get_id (&broken_list[i][7])) !=
920 GNUTLS_ECC_CURVE_INVALID)
921 fn (&(*priority_cache)->supported_ecc, algo);
922 else
923 goto error;
925 } /* now check if the element is something like -ALGO */
926 else if (strncasecmp (&broken_list[i][1], "CTYPE-", 6) == 0)
928 if (strncasecmp (&broken_list[i][1], "CTYPE-ALL", 9) == 0)
930 bulk_fn (&(*priority_cache)->cert_type,
931 cert_type_priority_all);
933 else
935 if ((algo =
936 gnutls_certificate_type_get_id (&broken_list[i][7])) !=
937 GNUTLS_CRT_UNKNOWN)
938 fn (&(*priority_cache)->cert_type, algo);
939 else
940 goto error;
942 } /* now check if the element is something like -ALGO */
943 else if (strncasecmp (&broken_list[i][1], "SIGN-", 5) == 0)
945 if (strncasecmp (&broken_list[i][1], "SIGN-ALL", 8) == 0)
947 bulk_fn (&(*priority_cache)->sign_algo,
948 sign_priority_default);
950 else
952 if ((algo =
953 gnutls_sign_get_id (&broken_list[i][6])) !=
954 GNUTLS_SIGN_UNKNOWN)
955 fn (&(*priority_cache)->sign_algo, algo);
956 else
957 goto error;
960 else if (strncasecmp (&broken_list[i][1], "MAC-ALL", 7) == 0)
962 bulk_fn (&(*priority_cache)->mac,
963 mac_priority_normal);
965 else if (strncasecmp (&broken_list[i][1], "CIPHER-ALL", 10) == 0)
967 bulk_fn (&(*priority_cache)->cipher,
968 cipher_priority_normal);
970 else if (strncasecmp (&broken_list[i][1], "KX-ALL", 6) == 0)
972 bulk_fn (&(*priority_cache)->kx,
973 kx_priority_secure);
975 else
976 goto error;
978 else if (broken_list[i][0] == '%')
980 if (strcasecmp (&broken_list[i][1], "COMPAT") == 0)
982 ENABLE_COMPAT((*priority_cache));
984 else if (strcasecmp (&broken_list[i][1], "NO_EXTENSIONS") == 0)
986 (*priority_cache)->no_extensions = 1;
988 else if (strcasecmp (&broken_list[i][1], "STATELESS_COMPRESSION") == 0)
990 (*priority_cache)->stateless_compression = 1;
992 else if (strcasecmp (&broken_list[i][1],
993 "VERIFY_ALLOW_SIGN_RSA_MD5") == 0)
995 prio_add (&(*priority_cache)->sign_algo, GNUTLS_SIGN_RSA_MD5);
996 (*priority_cache)->additional_verify_flags |=
997 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5;
999 else if (strcasecmp (&broken_list[i][1],
1000 "VERIFY_DISABLE_CRL_CHECKS") == 0)
1002 (*priority_cache)->additional_verify_flags |=
1003 GNUTLS_VERIFY_DISABLE_CRL_CHECKS;
1005 else if (strcasecmp (&broken_list[i][1],
1006 "SSL3_RECORD_VERSION") == 0)
1007 (*priority_cache)->ssl3_record_version = 1;
1008 else if (strcasecmp (&broken_list[i][1],
1009 "LATEST_RECORD_VERSION") == 0)
1010 (*priority_cache)->ssl3_record_version = 0;
1011 else if (strcasecmp (&broken_list[i][1],
1012 "VERIFY_ALLOW_X509_V1_CA_CRT") == 0)
1013 (*priority_cache)->additional_verify_flags |=
1014 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
1015 else if (strcasecmp (&broken_list[i][1],
1016 "UNSAFE_RENEGOTIATION") == 0)
1018 (*priority_cache)->sr = SR_UNSAFE;
1020 else if (strcasecmp (&broken_list[i][1], "SAFE_RENEGOTIATION") == 0)
1022 (*priority_cache)->sr = SR_SAFE;
1024 else if (strcasecmp (&broken_list[i][1],
1025 "PARTIAL_RENEGOTIATION") == 0)
1027 (*priority_cache)->sr = SR_PARTIAL;
1029 else if (strcasecmp (&broken_list[i][1],
1030 "DISABLE_SAFE_RENEGOTIATION") == 0)
1032 (*priority_cache)->sr = SR_DISABLED;
1034 else if (strcasecmp (&broken_list[i][1],
1035 "SERVER_PRECEDENCE") == 0)
1037 (*priority_cache)->server_precedence = 1;
1039 else
1040 goto error;
1042 else
1043 goto error;
1046 gnutls_free (darg);
1047 return 0;
1049 error:
1050 if (err_pos != NULL && i < broken_list_size)
1052 *err_pos = priorities;
1053 for (j = 0; j < i; j++)
1055 (*err_pos) += strlen (broken_list[j]) + 1;
1058 gnutls_free (darg);
1059 gnutls_free (*priority_cache);
1061 return GNUTLS_E_INVALID_REQUEST;
1066 * gnutls_priority_deinit:
1067 * @priority_cache: is a #gnutls_prioritity_t structure.
1069 * Deinitializes the priority cache.
1071 void
1072 gnutls_priority_deinit (gnutls_priority_t priority_cache)
1074 gnutls_free (priority_cache);
1079 * gnutls_priority_set_direct:
1080 * @session: is a #gnutls_session_t structure.
1081 * @priorities: is a string describing priorities
1082 * @err_pos: In case of an error this will have the position in the string the error occured
1084 * Sets the priorities to use on the ciphers, key exchange methods,
1085 * macs and compression methods. This function avoids keeping a
1086 * priority cache and is used to directly set string priorities to a
1087 * TLS session. For documentation check the gnutls_priority_init().
1089 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
1090 * %GNUTLS_E_SUCCESS on success, or an error code.
1093 gnutls_priority_set_direct (gnutls_session_t session,
1094 const char *priorities, const char **err_pos)
1096 gnutls_priority_t prio;
1097 int ret;
1099 ret = gnutls_priority_init (&prio, priorities, err_pos);
1100 if (ret < 0)
1102 gnutls_assert ();
1103 return ret;
1106 ret = gnutls_priority_set (session, prio);
1107 if (ret < 0)
1109 gnutls_assert ();
1110 return ret;
1113 gnutls_priority_deinit (prio);
1115 return 0;
1118 /* Breaks a list of "xxx", "yyy", to a character array, of
1119 * MAX_COMMA_SEP_ELEMENTS size; Note that the given string is modified.
1121 static void
1122 break_comma_list (char *etag,
1123 char **broken_etag, int *elements, int max_elements,
1124 char sep)
1126 char *p = etag;
1127 if (sep == 0)
1128 sep = ',';
1130 *elements = 0;
1134 broken_etag[*elements] = p;
1136 (*elements)++;
1138 p = strchr (p, sep);
1139 if (p)
1141 *p = 0;
1142 p++; /* move to next entry and skip white
1143 * space.
1145 while (*p == ' ')
1146 p++;
1149 while (p != NULL && *elements < max_elements);
1153 * gnutls_set_default_priority:
1154 * @session: is a #gnutls_session_t structure.
1156 * Sets some default priority on the ciphers, key exchange methods,
1157 * macs and compression methods.
1159 * This is the same as calling:
1161 * gnutls_priority_set_direct (session, "NORMAL", NULL);
1163 * This function is kept around for backwards compatibility, but
1164 * because of its wide use it is still fully supported. If you wish
1165 * to allow users to provide a string that specify which ciphers to
1166 * use (which is recommended), you should use
1167 * gnutls_priority_set_direct() or gnutls_priority_set() instead.
1169 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
1172 gnutls_set_default_priority (gnutls_session_t session)
1174 return gnutls_priority_set_direct (session, "NORMAL", NULL);
1178 * gnutls_set_default_export_priority:
1179 * @session: is a #gnutls_session_t structure.
1181 * Sets some default priority on the ciphers, key exchange methods, macs
1182 * and compression methods. This function also includes weak algorithms.
1184 * This is the same as calling:
1186 * gnutls_priority_set_direct (session, "EXPORT", NULL);
1188 * This function is kept around for backwards compatibility, but
1189 * because of its wide use it is still fully supported. If you wish
1190 * to allow users to provide a string that specify which ciphers to
1191 * use (which is recommended), you should use
1192 * gnutls_priority_set_direct() or gnutls_priority_set() instead.
1194 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
1197 gnutls_set_default_export_priority (gnutls_session_t session)
1199 return gnutls_priority_set_direct (session, "EXPORT", NULL);
1202 /* Increases the priority of AES-GCM as it is much faster
1203 * than anything else if hardware support is there.
1205 void _gnutls_priority_prefer_aes_gcm(void)
1207 cipher_priority_performance = cipher_priority_performance_hw_aes;
1208 cipher_priority_normal = cipher_priority_normal_hw_aes;
1212 * gnutls_priority_ecc_curve_list:
1213 * @pcache: is a #gnutls_prioritity_t structure.
1214 * @list: will point to an integer list
1216 * Get a list of available elliptic curves in the priority
1217 * structure.
1219 * Returns: the number of curves, or an error code.
1220 * Since: 3.0
1223 gnutls_priority_ecc_curve_list (gnutls_priority_t pcache, const unsigned int** list)
1225 if (pcache->supported_ecc.algorithms == 0)
1226 return 0;
1228 *list = pcache->supported_ecc.priority;
1229 return pcache->supported_ecc.algorithms;
1233 * gnutls_priority_compression_list:
1234 * @pcache: is a #gnutls_prioritity_t structure.
1235 * @list: will point to an integer list
1237 * Get a list of available compression method in the priority
1238 * structure.
1240 * Returns: the number of methods, or an error code.
1241 * Since: 3.0
1244 gnutls_priority_compression_list (gnutls_priority_t pcache, const unsigned int** list)
1246 if (pcache->compression.algorithms == 0)
1247 return 0;
1249 *list = pcache->compression.priority;
1250 return pcache->compression.algorithms;
1254 * gnutls_priority_protocol_list:
1255 * @pcache: is a #gnutls_prioritity_t structure.
1256 * @list: will point to an integer list
1258 * Get a list of available TLS version numbers in the priority
1259 * structure.
1261 * Returns: the number of protocols, or an error code.
1262 * Since: 3.0
1265 gnutls_priority_protocol_list (gnutls_priority_t pcache, const unsigned int** list)
1267 if (pcache->protocol.algorithms == 0)
1268 return 0;
1270 *list = pcache->protocol.priority;
1271 return pcache->protocol.algorithms;
1275 * gnutls_priority_sign_list:
1276 * @pcache: is a #gnutls_prioritity_t structure.
1277 * @list: will point to an integer list
1279 * Get a list of available signature algorithms in the priority
1280 * structure.
1282 * Returns: the number of algorithms, or an error code.
1283 * Since: 3.0
1286 gnutls_priority_sign_list (gnutls_priority_t pcache, const unsigned int** list)
1288 if (pcache->sign_algo.algorithms == 0)
1289 return 0;
1291 *list = pcache->sign_algo.priority;
1292 return pcache->sign_algo.algorithms;
1296 * gnutls_priority_certificate_type_list:
1297 * @pcache: is a #gnutls_prioritity_t structure.
1298 * @list: will point to an integer list
1300 * Get a list of available certificate types in the priority
1301 * structure.
1303 * Returns: the number of certificate types, or an error code.
1304 * Since: 3.0
1307 gnutls_priority_certificate_type_list (gnutls_priority_t pcache, const unsigned int** list)
1309 if (pcache->cert_type.algorithms == 0)
1310 return 0;
1312 *list = pcache->cert_type.priority;
1313 return pcache->cert_type.algorithms;