Documented gnutls_certificate_verification_status_print().
[gnutls.git] / lib / gnutls_priority.c
blobb6649ca6705cf113b84444fbffa527259c4a7ad4
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 = 0, i, j, init;
94 init = i = st->algorithms;
96 while (list[num] != 0)
98 if (i+1 > MAX_ALGOS)
100 return;
103 for (j=0;j<init;j++)
105 if (st->priority[j] == (unsigned)list[num])
107 num++;
108 continue;
112 st->priority[i++] = list[num];
113 st->algorithms++;
114 num++;
117 return;
120 static void
121 _clear_priorities (priority_st * st, const int *list)
123 memset(st, 0, sizeof(*st));
127 * gnutls_kx_set_priority:
128 * @session: is a #gnutls_session_t structure.
129 * @list: is a 0 terminated list of gnutls_kx_algorithm_t elements.
131 * Sets the priority on the key exchange algorithms supported by
132 * gnutls. Priority is higher for elements specified before others.
133 * After specifying the algorithms you want, you must append a 0.
134 * Note that the priority is set on the client. The server does not
135 * use the algorithm's priority except for disabling algorithms that
136 * were not specified.
138 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
141 gnutls_kx_set_priority (gnutls_session_t session, const int *list)
143 _set_priority (&session->internals.priorities.kx, list);
144 return 0;
148 * gnutls_mac_set_priority:
149 * @session: is a #gnutls_session_t structure.
150 * @list: is a 0 terminated list of gnutls_mac_algorithm_t elements.
152 * Sets the priority on the mac algorithms supported by gnutls.
153 * Priority is higher for elements specified before others. After
154 * specifying the algorithms you want, you must append a 0. Note
155 * that the priority is set on the client. The server does not use
156 * the algorithm's priority except for disabling algorithms that were
157 * not specified.
159 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
162 gnutls_mac_set_priority (gnutls_session_t session, const int *list)
164 _set_priority (&session->internals.priorities.mac, list);
165 return 0;
169 * gnutls_compression_set_priority:
170 * @session: is a #gnutls_session_t structure.
171 * @list: is a 0 terminated list of gnutls_compression_method_t elements.
173 * Sets the priority on the compression algorithms supported by
174 * gnutls. Priority is higher for elements specified before others.
175 * After specifying the algorithms you want, you must append a 0.
176 * Note that the priority is set on the client. The server does not
177 * use the algorithm's priority except for disabling algorithms that
178 * were not specified.
180 * TLS 1.0 does not define any compression algorithms except
181 * NULL. Other compression algorithms are to be considered as gnutls
182 * extensions.
184 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
187 gnutls_compression_set_priority (gnutls_session_t session, const int *list)
189 _set_priority (&session->internals.priorities.compression, list);
190 return 0;
194 * gnutls_protocol_set_priority:
195 * @session: is a #gnutls_session_t structure.
196 * @list: is a 0 terminated list of gnutls_protocol_t elements.
198 * Sets the priority on the protocol versions supported by gnutls.
199 * This function actually enables or disables protocols. Newer protocol
200 * versions always have highest priority.
202 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
205 gnutls_protocol_set_priority (gnutls_session_t session, const int *list)
207 _set_priority (&session->internals.priorities.protocol, list);
209 /* set the current version to the first in the chain.
210 * This will be overridden later.
212 if (list)
213 _gnutls_set_current_version (session, list[0]);
215 return 0;
219 * gnutls_certificate_type_set_priority:
220 * @session: is a #gnutls_session_t structure.
221 * @list: is a 0 terminated list of gnutls_certificate_type_t elements.
223 * Sets the priority on the certificate types supported by gnutls.
224 * Priority is higher for elements specified before others.
225 * After specifying the types you want, you must append a 0.
226 * Note that the certificate type priority is set on the client.
227 * The server does not use the cert type priority except for disabling
228 * types that were not specified.
230 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
233 gnutls_certificate_type_set_priority (gnutls_session_t session,
234 const int *list)
236 #ifdef ENABLE_OPENPGP
237 _set_priority (&session->internals.priorities.cert_type, list);
238 return 0;
239 #else
241 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
243 #endif
246 static const int supported_ecc_normal[] = {
247 GNUTLS_ECC_CURVE_SECP192R1,
248 GNUTLS_ECC_CURVE_SECP224R1,
249 GNUTLS_ECC_CURVE_SECP256R1,
250 GNUTLS_ECC_CURVE_SECP384R1,
251 GNUTLS_ECC_CURVE_SECP521R1,
255 static const int supported_ecc_secure128[] = {
256 GNUTLS_ECC_CURVE_SECP256R1,
257 GNUTLS_ECC_CURVE_SECP384R1,
258 GNUTLS_ECC_CURVE_SECP521R1,
262 static const int supported_ecc_suiteb128[] = {
263 GNUTLS_ECC_CURVE_SECP256R1,
264 GNUTLS_ECC_CURVE_SECP384R1,
268 static const int supported_ecc_suiteb192[] = {
269 GNUTLS_ECC_CURVE_SECP384R1,
273 static const int supported_ecc_secure192[] = {
274 GNUTLS_ECC_CURVE_SECP384R1,
275 GNUTLS_ECC_CURVE_SECP521R1,
279 static const int protocol_priority[] = {
280 GNUTLS_TLS1_2,
281 GNUTLS_TLS1_1,
282 GNUTLS_TLS1_0,
283 GNUTLS_SSL3,
284 GNUTLS_DTLS1_0,
288 static const int protocol_priority_suiteb[] = {
289 GNUTLS_TLS1_2,
293 static const int kx_priority_performance[] = {
294 GNUTLS_KX_RSA,
295 GNUTLS_KX_ECDHE_ECDSA,
296 GNUTLS_KX_ECDHE_RSA,
297 GNUTLS_KX_DHE_RSA,
298 GNUTLS_KX_DHE_DSS,
302 static const int kx_priority_suiteb[] = {
303 GNUTLS_KX_ECDHE_ECDSA,
307 static const int kx_priority_export[] = {
308 GNUTLS_KX_RSA,
309 GNUTLS_KX_ECDHE_ECDSA,
310 GNUTLS_KX_ECDHE_RSA,
311 GNUTLS_KX_DHE_RSA,
312 GNUTLS_KX_DHE_DSS,
313 GNUTLS_KX_RSA_EXPORT,
317 static const int kx_priority_secure[] = {
318 /* The ciphersuites that offer forward secrecy take
319 * precedence
321 GNUTLS_KX_ECDHE_ECDSA,
322 GNUTLS_KX_ECDHE_RSA,
323 GNUTLS_KX_DHE_RSA,
324 GNUTLS_KX_DHE_DSS,
325 GNUTLS_KX_RSA,
326 /* GNUTLS_KX_ANON_DH: Man-in-the-middle prone, don't add!
327 * GNUTLS_KX_RSA_EXPORT: Deprecated, don't add!
332 static const int cipher_priority_performance_sw[] = {
333 GNUTLS_CIPHER_ARCFOUR_128,
334 GNUTLS_CIPHER_AES_128_CBC,
335 GNUTLS_CIPHER_CAMELLIA_128_CBC,
336 GNUTLS_CIPHER_AES_256_CBC,
337 GNUTLS_CIPHER_CAMELLIA_256_CBC,
338 GNUTLS_CIPHER_3DES_CBC,
339 GNUTLS_CIPHER_AES_128_GCM,
340 GNUTLS_CIPHER_AES_256_GCM,
344 /* If GCM and AES acceleration is available then prefer
345 * them over anything else.
347 static const int cipher_priority_performance_hw_aes[] = {
348 GNUTLS_CIPHER_AES_128_GCM,
349 GNUTLS_CIPHER_AES_128_CBC,
350 GNUTLS_CIPHER_AES_256_GCM,
351 GNUTLS_CIPHER_AES_256_CBC,
352 GNUTLS_CIPHER_ARCFOUR_128,
353 GNUTLS_CIPHER_CAMELLIA_128_CBC,
354 GNUTLS_CIPHER_CAMELLIA_256_CBC,
355 GNUTLS_CIPHER_3DES_CBC,
359 static const int cipher_priority_normal_sw[] = {
360 GNUTLS_CIPHER_AES_128_CBC,
361 GNUTLS_CIPHER_CAMELLIA_128_CBC,
362 GNUTLS_CIPHER_AES_128_GCM,
363 GNUTLS_CIPHER_AES_256_CBC,
364 GNUTLS_CIPHER_CAMELLIA_256_CBC,
365 GNUTLS_CIPHER_AES_256_GCM,
366 GNUTLS_CIPHER_3DES_CBC,
367 GNUTLS_CIPHER_ARCFOUR_128,
371 static const int cipher_priority_normal_hw_aes[] = {
372 GNUTLS_CIPHER_AES_128_GCM,
373 GNUTLS_CIPHER_AES_128_CBC,
374 GNUTLS_CIPHER_AES_256_GCM,
375 GNUTLS_CIPHER_AES_256_CBC,
376 GNUTLS_CIPHER_CAMELLIA_128_CBC,
377 GNUTLS_CIPHER_CAMELLIA_256_CBC,
378 GNUTLS_CIPHER_3DES_CBC,
379 GNUTLS_CIPHER_ARCFOUR_128,
383 static const int *cipher_priority_performance = cipher_priority_performance_sw;
384 static const int *cipher_priority_normal = cipher_priority_normal_sw;
387 static const int cipher_priority_suiteb128[] = {
388 GNUTLS_CIPHER_AES_128_GCM,
389 GNUTLS_CIPHER_AES_256_GCM,
393 static const int cipher_priority_suiteb192[] = {
394 GNUTLS_CIPHER_AES_256_GCM,
399 static const int cipher_priority_secure128[] = {
400 GNUTLS_CIPHER_AES_128_CBC,
401 GNUTLS_CIPHER_CAMELLIA_128_CBC,
402 GNUTLS_CIPHER_AES_128_GCM,
403 GNUTLS_CIPHER_AES_256_CBC,
404 GNUTLS_CIPHER_CAMELLIA_256_CBC,
405 GNUTLS_CIPHER_AES_256_GCM,
410 static const int cipher_priority_secure192[] = {
411 GNUTLS_CIPHER_AES_256_CBC,
412 GNUTLS_CIPHER_CAMELLIA_256_CBC,
413 GNUTLS_CIPHER_AES_256_GCM,
417 /* The same as cipher_priority_security_normal + arcfour-40. */
418 static const int cipher_priority_export[] = {
419 GNUTLS_CIPHER_AES_128_CBC,
420 GNUTLS_CIPHER_AES_256_CBC,
421 GNUTLS_CIPHER_CAMELLIA_128_CBC,
422 GNUTLS_CIPHER_CAMELLIA_256_CBC,
423 GNUTLS_CIPHER_AES_128_GCM,
424 GNUTLS_CIPHER_3DES_CBC,
425 GNUTLS_CIPHER_ARCFOUR_128,
426 GNUTLS_CIPHER_ARCFOUR_40,
430 static const int comp_priority[] = {
431 /* compression should be explicitly requested to be enabled */
432 GNUTLS_COMP_NULL,
436 static const int sign_priority_default[] = {
437 GNUTLS_SIGN_RSA_SHA256,
438 GNUTLS_SIGN_DSA_SHA256,
439 GNUTLS_SIGN_ECDSA_SHA256,
441 GNUTLS_SIGN_RSA_SHA384,
442 GNUTLS_SIGN_ECDSA_SHA384,
444 GNUTLS_SIGN_RSA_SHA512,
445 GNUTLS_SIGN_ECDSA_SHA512,
447 GNUTLS_SIGN_RSA_SHA224,
448 GNUTLS_SIGN_DSA_SHA224,
449 GNUTLS_SIGN_ECDSA_SHA224,
451 GNUTLS_SIGN_RSA_SHA1,
452 GNUTLS_SIGN_DSA_SHA1,
453 GNUTLS_SIGN_ECDSA_SHA1,
457 static const int sign_priority_suiteb128[] = {
458 GNUTLS_SIGN_ECDSA_SHA256,
459 GNUTLS_SIGN_ECDSA_SHA384,
463 static const int sign_priority_suiteb192[] = {
464 GNUTLS_SIGN_ECDSA_SHA384,
468 static const int sign_priority_secure128[] = {
469 GNUTLS_SIGN_RSA_SHA256,
470 GNUTLS_SIGN_DSA_SHA256,
471 GNUTLS_SIGN_ECDSA_SHA256,
472 GNUTLS_SIGN_RSA_SHA384,
473 GNUTLS_SIGN_ECDSA_SHA384,
474 GNUTLS_SIGN_RSA_SHA512,
475 GNUTLS_SIGN_ECDSA_SHA512,
479 static const int sign_priority_secure192[] = {
480 GNUTLS_SIGN_RSA_SHA384,
481 GNUTLS_SIGN_ECDSA_SHA384,
482 GNUTLS_SIGN_RSA_SHA512,
483 GNUTLS_SIGN_ECDSA_SHA512,
487 static const int mac_priority_normal[] = {
488 GNUTLS_MAC_SHA1,
489 GNUTLS_MAC_SHA256,
490 GNUTLS_MAC_SHA384,
491 GNUTLS_MAC_AEAD,
492 GNUTLS_MAC_MD5,
496 static const int mac_priority_suiteb128[] = {
497 GNUTLS_MAC_AEAD,
501 static const int mac_priority_suiteb192[] = {
502 GNUTLS_MAC_AEAD,
506 static const int mac_priority_secure128[] = {
507 GNUTLS_MAC_SHA1,
508 GNUTLS_MAC_SHA256,
509 GNUTLS_MAC_SHA384,
510 GNUTLS_MAC_AEAD,
514 static const int mac_priority_secure192[] = {
515 GNUTLS_MAC_SHA256,
516 GNUTLS_MAC_SHA384,
517 GNUTLS_MAC_AEAD,
521 static const int cert_type_priority_default[] = {
522 GNUTLS_CRT_X509,
526 static const int cert_type_priority_all[] = {
527 GNUTLS_CRT_X509,
528 GNUTLS_CRT_OPENPGP,
532 typedef void (rmadd_func) (priority_st * priority_list, unsigned int alg);
534 static void
535 prio_remove (priority_st * priority_list, unsigned int algo)
537 int i = 0;
538 int pos = -1; /* the position of the cipher to remove */
540 while (priority_list->priority[i] != 0)
542 if (priority_list->priority[i] == algo)
543 pos = i;
544 i++;
547 if (pos >= 0)
549 priority_list->priority[pos] = priority_list->priority[i - 1];
550 priority_list->priority[i - 1] = 0;
551 priority_list->algorithms--;
554 return;
557 static void
558 prio_add (priority_st * priority_list, unsigned int algo)
560 register int i = 0;
561 while (priority_list->priority[i] != 0)
563 if (algo == priority_list->priority[i])
564 return; /* if it exists */
565 i++;
568 if (i < MAX_ALGOS)
570 priority_list->priority[i] = algo;
571 priority_list->algorithms++;
574 return;
579 * gnutls_priority_set:
580 * @session: is a #gnutls_session_t structure.
581 * @priority: is a #gnutls_priority_t structure.
583 * Sets the priorities to use on the ciphers, key exchange methods,
584 * macs and compression methods.
586 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
589 gnutls_priority_set (gnutls_session_t session, gnutls_priority_t priority)
591 if (priority == NULL)
593 gnutls_assert ();
594 return GNUTLS_E_NO_CIPHER_SUITES;
597 memcpy (&session->internals.priorities, priority,
598 sizeof (struct gnutls_priority_st));
600 /* set the current version to the first in the chain.
601 * This will be overridden later.
603 if (session->internals.priorities.protocol.algorithms > 0)
604 _gnutls_set_current_version (session,
605 session->internals.priorities.protocol.
606 priority[0]);
608 if (session->internals.priorities.protocol.algorithms == 0 ||
609 session->internals.priorities.cipher.algorithms == 0 ||
610 session->internals.priorities.mac.algorithms == 0 ||
611 session->internals.priorities.kx.algorithms == 0 ||
612 session->internals.priorities.compression.algorithms == 0)
613 return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
615 return 0;
619 #define MAX_ELEMENTS 48
621 #define LEVEL_NONE "NONE"
622 #define LEVEL_NORMAL "NORMAL"
623 #define LEVEL_PERFORMANCE "PERFORMANCE"
624 #define LEVEL_SECURE128 "SECURE128"
625 #define LEVEL_SECURE192 "SECURE192"
626 #define LEVEL_SECURE256 "SECURE256"
627 #define LEVEL_SUITEB128 "SUITEB128"
628 #define LEVEL_SUITEB192 "SUITEB192"
629 #define LEVEL_EXPORT "EXPORT"
631 static
632 int check_level(const char* level, gnutls_priority_t priority_cache, int add)
634 bulk_rmadd_func *func;
636 if (add) func = _add_priority;
637 else func = _set_priority;
639 if (strcasecmp (level, LEVEL_PERFORMANCE) == 0)
641 func (&priority_cache->cipher,
642 cipher_priority_performance);
643 func (&priority_cache->kx, kx_priority_performance);
644 func (&priority_cache->mac, mac_priority_normal);
645 func (&priority_cache->sign_algo,
646 sign_priority_default);
647 func (&priority_cache->supported_ecc, supported_ecc_normal);
648 return 1;
650 else if (strcasecmp (level, LEVEL_NORMAL) == 0)
652 func (&priority_cache->cipher, cipher_priority_normal);
653 func (&priority_cache->kx, kx_priority_secure);
654 func (&priority_cache->mac, mac_priority_normal);
655 func (&priority_cache->sign_algo,
656 sign_priority_default);
657 func (&priority_cache->supported_ecc, supported_ecc_normal);
658 return 1;
660 else if (strcasecmp (level, LEVEL_SECURE256) == 0
661 || strcasecmp (level, LEVEL_SECURE192) == 0)
663 func (&priority_cache->cipher,
664 cipher_priority_secure192);
665 func (&priority_cache->kx, kx_priority_secure);
666 func (&priority_cache->mac, mac_priority_secure192);
667 func (&priority_cache->sign_algo,
668 sign_priority_secure192);
669 func (&priority_cache->supported_ecc, supported_ecc_secure192);
670 return 1;
672 else if (strcasecmp (level, LEVEL_SECURE128) == 0
673 || strcasecmp (level, "SECURE") == 0)
675 func (&priority_cache->cipher,
676 cipher_priority_secure128);
677 func (&priority_cache->kx, kx_priority_secure);
678 func (&priority_cache->mac, mac_priority_secure128);
679 func (&priority_cache->sign_algo,
680 sign_priority_secure128);
681 func (&priority_cache->supported_ecc, supported_ecc_secure128);
682 return 1;
684 else if (strcasecmp (level, LEVEL_SUITEB128) == 0)
686 func (&priority_cache->protocol, protocol_priority_suiteb);
687 func (&priority_cache->cipher,
688 cipher_priority_suiteb128);
689 func (&priority_cache->kx, kx_priority_suiteb);
690 func (&priority_cache->mac, mac_priority_suiteb128);
691 func (&priority_cache->sign_algo,
692 sign_priority_suiteb128);
693 func (&priority_cache->supported_ecc, supported_ecc_suiteb128);
694 return 1;
696 else if (strcasecmp (level, LEVEL_SUITEB192) == 0)
698 func (&priority_cache->protocol, protocol_priority_suiteb);
699 func (&priority_cache->cipher,
700 cipher_priority_suiteb192);
701 func (&priority_cache->kx, kx_priority_suiteb);
702 func (&priority_cache->mac, mac_priority_suiteb192);
703 func (&priority_cache->sign_algo,
704 sign_priority_suiteb192);
705 func (&priority_cache->supported_ecc, supported_ecc_suiteb192);
706 return 1;
708 else if (strcasecmp (level, LEVEL_EXPORT) == 0)
710 func (&priority_cache->cipher, cipher_priority_export);
711 func (&priority_cache->kx, kx_priority_export);
712 func (&priority_cache->mac, mac_priority_secure128);
713 func (&priority_cache->sign_algo,
714 sign_priority_default);
715 func (&priority_cache->supported_ecc, supported_ecc_normal);
716 return 1;
718 return 0;
722 * gnutls_priority_init:
723 * @priority_cache: is a #gnutls_prioritity_t structure.
724 * @priorities: is a string describing priorities
725 * @err_pos: In case of an error this will have the position in the string the error occured
727 * Sets priorities for the ciphers, key exchange methods, macs and
728 * compression methods.
730 * The #priorities option allows you to specify a colon
731 * separated list of the cipher priorities to enable.
732 * Some keywords are defined to provide quick access
733 * to common preferences.
735 * "PERFORMANCE" means all the "secure" ciphersuites are enabled,
736 * limited to 128 bit ciphers and sorted by terms of speed
737 * performance.
739 * "NORMAL" means all "secure" ciphersuites. The 256-bit ciphers are
740 * included as a fallback only. The ciphers are sorted by security
741 * margin.
743 * "SECURE128" means all "secure" ciphersuites of security level 128-bit
744 * or more.
746 * "SECURE192" means all "secure" ciphersuites of security level 192-bit
747 * or more.
749 * "SUITEB128" means all the NSA SuiteB ciphersuites with security level
750 * of 128.
752 * "SUITEB192" means all the NSA SuiteB ciphersuites with security level
753 * of 192.
755 * "EXPORT" means all ciphersuites are enabled, including the
756 * low-security 40 bit ciphers.
758 * "NONE" means nothing is enabled. This disables even protocols and
759 * compression methods.
761 * Special keywords are "!", "-" and "+".
762 * "!" or "-" appended with an algorithm will remove this algorithm.
763 * "+" appended with an algorithm will add this algorithm.
765 * Check the GnuTLS manual section "Priority strings" for detailed
766 * information.
768 * Examples:
770 * "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL"
772 * "NORMAL:-ARCFOUR-128" means normal ciphers except for ARCFOUR-128.
774 * "SECURE:-VERS-SSL3.0:+COMP-DEFLATE" means that only secure ciphers are
775 * enabled, SSL3.0 is disabled, and libz compression enabled.
777 * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1",
779 * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+ECDHE-RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1:+CURVE-SECP256R1",
781 * "SECURE256:+SECURE128",
783 * Note that "NORMAL:%COMPAT" is the most compatible mode.
785 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
786 * %GNUTLS_E_SUCCESS on success, or an error code.
789 gnutls_priority_init (gnutls_priority_t * priority_cache,
790 const char *priorities, const char **err_pos)
792 char *broken_list[MAX_ELEMENTS];
793 int broken_list_size = 0, i = 0, j;
794 char *darg = NULL;
795 int algo;
796 rmadd_func *fn;
797 bulk_rmadd_func *bulk_fn;
799 *priority_cache = gnutls_calloc (1, sizeof (struct gnutls_priority_st));
800 if (*priority_cache == NULL)
802 gnutls_assert ();
803 return GNUTLS_E_MEMORY_ERROR;
806 /* for now unsafe renegotiation is default on everyone. To be removed
807 * when we make it the default.
809 (*priority_cache)->sr = SR_PARTIAL;
810 (*priority_cache)->ssl3_record_version = 1;
812 if (priorities == NULL)
813 priorities = LEVEL_NORMAL;
815 darg = gnutls_strdup (priorities);
816 if (darg == NULL)
818 gnutls_assert ();
819 goto error;
822 break_comma_list (darg, broken_list, &broken_list_size, MAX_ELEMENTS, ':');
823 /* This is our default set of protocol version, certificate types and
824 * compression methods.
826 if (strcasecmp (broken_list[0], LEVEL_NONE) != 0)
828 _set_priority (&(*priority_cache)->protocol, protocol_priority);
829 _set_priority (&(*priority_cache)->compression, comp_priority);
830 _set_priority (&(*priority_cache)->cert_type, cert_type_priority_default);
831 _set_priority (&(*priority_cache)->sign_algo, sign_priority_default);
832 _set_priority (&(*priority_cache)->supported_ecc, supported_ecc_normal);
833 i = 0;
835 else
837 i = 1;
840 for (; i < broken_list_size; i++)
842 if (check_level(broken_list[i], *priority_cache, 0) != 0)
844 continue;
846 else if (broken_list[i][0] == '!' || broken_list[i][0] == '+'
847 || broken_list[i][0] == '-')
849 if (broken_list[i][0] == '+')
851 fn = prio_add;
852 bulk_fn = _set_priority;
854 else
856 fn = prio_remove;
857 bulk_fn = _clear_priorities;
860 if (broken_list[i][0] == '+' && check_level(&broken_list[i][1], *priority_cache, 1) != 0)
862 continue;
864 else if ((algo =
865 gnutls_mac_get_id (&broken_list[i][1])) != GNUTLS_MAC_UNKNOWN)
866 fn (&(*priority_cache)->mac, algo);
867 else if ((algo = gnutls_cipher_get_id (&broken_list[i][1])) !=
868 GNUTLS_CIPHER_UNKNOWN)
869 fn (&(*priority_cache)->cipher, algo);
870 else if ((algo = gnutls_kx_get_id (&broken_list[i][1])) !=
871 GNUTLS_KX_UNKNOWN)
872 fn (&(*priority_cache)->kx, algo);
873 else if (strncasecmp (&broken_list[i][1], "VERS-", 5) == 0)
875 if (strncasecmp (&broken_list[i][1], "VERS-TLS-ALL", 12) == 0)
877 bulk_fn (&(*priority_cache)->protocol,
878 protocol_priority);
880 else
882 if ((algo =
883 gnutls_protocol_get_id (&broken_list[i][6])) !=
884 GNUTLS_VERSION_UNKNOWN)
885 fn (&(*priority_cache)->protocol, algo);
886 else
887 goto error;
890 } /* now check if the element is something like -ALGO */
891 else if (strncasecmp (&broken_list[i][1], "COMP-", 5) == 0)
893 if (strncasecmp (&broken_list[i][1], "COMP-ALL", 8) == 0)
895 bulk_fn (&(*priority_cache)->compression,
896 comp_priority);
898 else
900 if ((algo =
901 gnutls_compression_get_id (&broken_list[i][6])) !=
902 GNUTLS_COMP_UNKNOWN)
903 fn (&(*priority_cache)->compression, algo);
904 else
905 goto error;
907 } /* now check if the element is something like -ALGO */
908 else if (strncasecmp (&broken_list[i][1], "CURVE-", 6) == 0)
910 if (strncasecmp (&broken_list[i][1], "CURVE-ALL", 9) == 0)
912 bulk_fn (&(*priority_cache)->supported_ecc,
913 supported_ecc_normal);
915 else
917 if ((algo =
918 _gnutls_ecc_curve_get_id (&broken_list[i][7])) !=
919 GNUTLS_ECC_CURVE_INVALID)
920 fn (&(*priority_cache)->supported_ecc, algo);
921 else
922 goto error;
924 } /* now check if the element is something like -ALGO */
925 else if (strncasecmp (&broken_list[i][1], "CTYPE-", 6) == 0)
927 if (strncasecmp (&broken_list[i][1], "CTYPE-ALL", 9) == 0)
929 bulk_fn (&(*priority_cache)->cert_type,
930 cert_type_priority_all);
932 else
934 if ((algo =
935 gnutls_certificate_type_get_id (&broken_list[i][7])) !=
936 GNUTLS_CRT_UNKNOWN)
937 fn (&(*priority_cache)->cert_type, algo);
938 else
939 goto error;
941 } /* now check if the element is something like -ALGO */
942 else if (strncasecmp (&broken_list[i][1], "SIGN-", 5) == 0)
944 if (strncasecmp (&broken_list[i][1], "SIGN-ALL", 8) == 0)
946 bulk_fn (&(*priority_cache)->sign_algo,
947 sign_priority_default);
949 else
951 if ((algo =
952 gnutls_sign_get_id (&broken_list[i][6])) !=
953 GNUTLS_SIGN_UNKNOWN)
954 fn (&(*priority_cache)->sign_algo, algo);
955 else
956 goto error;
959 else if (strncasecmp (&broken_list[i][1], "MAC-ALL", 7) == 0)
961 bulk_fn (&(*priority_cache)->mac,
962 mac_priority_normal);
964 else if (strncasecmp (&broken_list[i][1], "CIPHER-ALL", 10) == 0)
966 bulk_fn (&(*priority_cache)->cipher,
967 cipher_priority_normal);
969 else if (strncasecmp (&broken_list[i][1], "KX-ALL", 6) == 0)
971 bulk_fn (&(*priority_cache)->kx,
972 kx_priority_secure);
974 else
975 goto error;
977 else if (broken_list[i][0] == '%')
979 if (strcasecmp (&broken_list[i][1], "COMPAT") == 0)
981 ENABLE_COMPAT((*priority_cache));
983 else if (strcasecmp (&broken_list[i][1], "NO_EXTENSIONS") == 0)
985 (*priority_cache)->no_extensions = 1;
987 else if (strcasecmp (&broken_list[i][1], "STATELESS_COMPRESSION") == 0)
989 (*priority_cache)->stateless_compression = 1;
991 else if (strcasecmp (&broken_list[i][1],
992 "VERIFY_ALLOW_SIGN_RSA_MD5") == 0)
994 prio_add (&(*priority_cache)->sign_algo, GNUTLS_SIGN_RSA_MD5);
995 (*priority_cache)->additional_verify_flags |=
996 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5;
998 else if (strcasecmp (&broken_list[i][1],
999 "VERIFY_DISABLE_CRL_CHECKS") == 0)
1001 (*priority_cache)->additional_verify_flags |=
1002 GNUTLS_VERIFY_DISABLE_CRL_CHECKS;
1004 else if (strcasecmp (&broken_list[i][1],
1005 "SSL3_RECORD_VERSION") == 0)
1006 (*priority_cache)->ssl3_record_version = 1;
1007 else if (strcasecmp (&broken_list[i][1],
1008 "LATEST_RECORD_VERSION") == 0)
1009 (*priority_cache)->ssl3_record_version = 0;
1010 else if (strcasecmp (&broken_list[i][1],
1011 "VERIFY_ALLOW_X509_V1_CA_CRT") == 0)
1012 (*priority_cache)->additional_verify_flags |=
1013 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
1014 else if (strcasecmp (&broken_list[i][1],
1015 "UNSAFE_RENEGOTIATION") == 0)
1017 (*priority_cache)->sr = SR_UNSAFE;
1019 else if (strcasecmp (&broken_list[i][1], "SAFE_RENEGOTIATION") == 0)
1021 (*priority_cache)->sr = SR_SAFE;
1023 else if (strcasecmp (&broken_list[i][1],
1024 "PARTIAL_RENEGOTIATION") == 0)
1026 (*priority_cache)->sr = SR_PARTIAL;
1028 else if (strcasecmp (&broken_list[i][1],
1029 "DISABLE_SAFE_RENEGOTIATION") == 0)
1031 (*priority_cache)->sr = SR_DISABLED;
1033 else if (strcasecmp (&broken_list[i][1],
1034 "SERVER_PRECEDENCE") == 0)
1036 (*priority_cache)->server_precedence = 1;
1038 else
1039 goto error;
1041 else
1042 goto error;
1045 gnutls_free (darg);
1046 return 0;
1048 error:
1049 if (err_pos != NULL && i < broken_list_size)
1051 *err_pos = priorities;
1052 for (j = 0; j < i; j++)
1054 (*err_pos) += strlen (broken_list[j]) + 1;
1057 gnutls_free (darg);
1058 gnutls_free (*priority_cache);
1060 return GNUTLS_E_INVALID_REQUEST;
1065 * gnutls_priority_deinit:
1066 * @priority_cache: is a #gnutls_prioritity_t structure.
1068 * Deinitializes the priority cache.
1070 void
1071 gnutls_priority_deinit (gnutls_priority_t priority_cache)
1073 gnutls_free (priority_cache);
1078 * gnutls_priority_set_direct:
1079 * @session: is a #gnutls_session_t structure.
1080 * @priorities: is a string describing priorities
1081 * @err_pos: In case of an error this will have the position in the string the error occured
1083 * Sets the priorities to use on the ciphers, key exchange methods,
1084 * macs and compression methods. This function avoids keeping a
1085 * priority cache and is used to directly set string priorities to a
1086 * TLS session. For documentation check the gnutls_priority_init().
1088 * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned,
1089 * %GNUTLS_E_SUCCESS on success, or an error code.
1092 gnutls_priority_set_direct (gnutls_session_t session,
1093 const char *priorities, const char **err_pos)
1095 gnutls_priority_t prio;
1096 int ret;
1098 ret = gnutls_priority_init (&prio, priorities, err_pos);
1099 if (ret < 0)
1101 gnutls_assert ();
1102 return ret;
1105 ret = gnutls_priority_set (session, prio);
1106 if (ret < 0)
1108 gnutls_assert ();
1109 return ret;
1112 gnutls_priority_deinit (prio);
1114 return 0;
1117 /* Breaks a list of "xxx", "yyy", to a character array, of
1118 * MAX_COMMA_SEP_ELEMENTS size; Note that the given string is modified.
1120 static void
1121 break_comma_list (char *etag,
1122 char **broken_etag, int *elements, int max_elements,
1123 char sep)
1125 char *p = etag;
1126 if (sep == 0)
1127 sep = ',';
1129 *elements = 0;
1133 broken_etag[*elements] = p;
1135 (*elements)++;
1137 p = strchr (p, sep);
1138 if (p)
1140 *p = 0;
1141 p++; /* move to next entry and skip white
1142 * space.
1144 while (*p == ' ')
1145 p++;
1148 while (p != NULL && *elements < max_elements);
1152 * gnutls_set_default_priority:
1153 * @session: is a #gnutls_session_t structure.
1155 * Sets some default priority on the ciphers, key exchange methods,
1156 * macs and compression methods.
1158 * This is the same as calling:
1160 * gnutls_priority_set_direct (session, "NORMAL", NULL);
1162 * This function is kept around for backwards compatibility, but
1163 * because of its wide use it is still fully supported. If you wish
1164 * to allow users to provide a string that specify which ciphers to
1165 * use (which is recommended), you should use
1166 * gnutls_priority_set_direct() or gnutls_priority_set() instead.
1168 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
1171 gnutls_set_default_priority (gnutls_session_t session)
1173 return gnutls_priority_set_direct (session, "NORMAL", NULL);
1177 * gnutls_set_default_export_priority:
1178 * @session: is a #gnutls_session_t structure.
1180 * Sets some default priority on the ciphers, key exchange methods, macs
1181 * and compression methods. This function also includes weak algorithms.
1183 * This is the same as calling:
1185 * gnutls_priority_set_direct (session, "EXPORT", NULL);
1187 * This function is kept around for backwards compatibility, but
1188 * because of its wide use it is still fully supported. If you wish
1189 * to allow users to provide a string that specify which ciphers to
1190 * use (which is recommended), you should use
1191 * gnutls_priority_set_direct() or gnutls_priority_set() instead.
1193 * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
1196 gnutls_set_default_export_priority (gnutls_session_t session)
1198 return gnutls_priority_set_direct (session, "EXPORT", NULL);
1201 /* Increases the priority of AES-GCM as it is much faster
1202 * than anything else if hardware support is there.
1204 void _gnutls_priority_prefer_aes_gcm(void)
1206 cipher_priority_performance = cipher_priority_performance_hw_aes;
1207 cipher_priority_normal = cipher_priority_normal_hw_aes;
1211 * gnutls_priority_ecc_curve_list:
1212 * @pcache: is a #gnutls_prioritity_t structure.
1213 * @list: will point to an integer list
1215 * Get a list of available elliptic curves in the priority
1216 * structure.
1218 * Returns: the number of curves, or an error code.
1219 * Since: 3.0
1222 gnutls_priority_ecc_curve_list (gnutls_priority_t pcache, const unsigned int** list)
1224 if (pcache->supported_ecc.algorithms == 0)
1225 return 0;
1227 *list = pcache->supported_ecc.priority;
1228 return pcache->supported_ecc.algorithms;
1232 * gnutls_priority_compression_list:
1233 * @pcache: is a #gnutls_prioritity_t structure.
1234 * @list: will point to an integer list
1236 * Get a list of available compression method in the priority
1237 * structure.
1239 * Returns: the number of methods, or an error code.
1240 * Since: 3.0
1243 gnutls_priority_compression_list (gnutls_priority_t pcache, const unsigned int** list)
1245 if (pcache->compression.algorithms == 0)
1246 return 0;
1248 *list = pcache->compression.priority;
1249 return pcache->compression.algorithms;
1253 * gnutls_priority_protocol_list:
1254 * @pcache: is a #gnutls_prioritity_t structure.
1255 * @list: will point to an integer list
1257 * Get a list of available TLS version numbers in the priority
1258 * structure.
1260 * Returns: the number of protocols, or an error code.
1261 * Since: 3.0
1264 gnutls_priority_protocol_list (gnutls_priority_t pcache, const unsigned int** list)
1266 if (pcache->protocol.algorithms == 0)
1267 return 0;
1269 *list = pcache->protocol.priority;
1270 return pcache->protocol.algorithms;
1274 * gnutls_priority_sign_list:
1275 * @pcache: is a #gnutls_prioritity_t structure.
1276 * @list: will point to an integer list
1278 * Get a list of available signature algorithms in the priority
1279 * structure.
1281 * Returns: the number of algorithms, or an error code.
1282 * Since: 3.0
1285 gnutls_priority_sign_list (gnutls_priority_t pcache, const unsigned int** list)
1287 if (pcache->sign_algo.algorithms == 0)
1288 return 0;
1290 *list = pcache->sign_algo.priority;
1291 return pcache->sign_algo.algorithms;
1295 * gnutls_priority_certificate_type_list:
1296 * @pcache: is a #gnutls_prioritity_t structure.
1297 * @list: will point to an integer list
1299 * Get a list of available certificate types in the priority
1300 * structure.
1302 * Returns: the number of certificate types, or an error code.
1303 * Since: 3.0
1306 gnutls_priority_certificate_type_list (gnutls_priority_t pcache, const unsigned int** list)
1308 if (pcache->cert_type.algorithms == 0)
1309 return 0;
1311 *list = pcache->cert_type.priority;
1312 return pcache->cert_type.algorithms;