Files
libmicrohttpd/src/daemon/https/tls/gnutls_priority.c
T
2008-08-24 22:20:59 +00:00

407 lines
13 KiB
C

/*
* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GNUTLS.
*
* The GNUTLS library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA
*
*/
/* Here lies the code of the gnutls_*_set_priority() functions.
*/
#include "gnutls_int.h"
#include "gnutls_algorithms.h"
#include "gnutls_errors.h"
#include <gnutls_num.h>
#define MAX_ELEMENTS 48
/**
* MHD_gnutls_cipher_set_priority - Sets the priority on the ciphers supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @list: is a 0 terminated list of enum MHD_GNUTLS_CipherAlgorithm elements.
*
* Sets the priority on the ciphers supported by gnutls.
* Priority is higher for elements specified before others.
* After specifying the ciphers you want, you must append a 0.
* Note that the priority is set on the client. The server does
* not use the algorithm's priority except for disabling
* algorithms that were not specified.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_cipher_set_priority (mhd_gtls_session_t session, const int *list)
{
int num = 0, i;
while (list[num] != 0)
num++;
if (num > MAX_ALGOS)
num = MAX_ALGOS;
session->internals.priorities.cipher.num_algorithms = num;
for (i = 0; i < num; i++)
{
session->internals.priorities.cipher.priority[i] = list[i];
}
return 0;
}
inline static int
_set_priority (mhd_gtls_priority_st * st, const int *list)
{
int num = 0, i;
while (list[num] != 0)
num++;
if (num > MAX_ALGOS)
num = MAX_ALGOS;
st->num_algorithms = num;
for (i = 0; i < num; i++)
{
st->priority[i] = list[i];
}
return 0;
}
/**
* MHD_gnutls_kx_set_priority - Sets the priority on the key exchange algorithms supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @list: is a 0 terminated list of enum MHD_GNUTLS_KeyExchangeAlgorithm elements.
*
* Sets the priority on the key exchange algorithms supported by gnutls.
* Priority is higher for elements specified before others.
* After specifying the algorithms you want, you must append a 0.
* Note that the priority is set on the client. The server does
* not use the algorithm's priority except for disabling
* algorithms that were not specified.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_kx_set_priority (mhd_gtls_session_t session, const int *list)
{
return _set_priority (&session->internals.priorities.kx, list);
}
/**
* MHD_gnutls_mac_set_priority - Sets the priority on the mac algorithms supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @list: is a 0 terminated list of enum MHD_GNUTLS_HashAlgorithm elements.
*
* Sets the priority on the mac algorithms supported by gnutls.
* Priority is higher for elements specified before others.
* After specifying the algorithms you want, you must append a 0.
* Note that the priority is set on the client. The server does
* not use the algorithm's priority except for disabling
* algorithms that were not specified.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_mac_set_priority (mhd_gtls_session_t session, const int *list)
{
return _set_priority (&session->internals.priorities.mac, list);
}
/**
* MHD_gnutls_compression_set_priority - Sets the priority on the compression algorithms supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @list: is a 0 terminated list of enum MHD_GNUTLS_CompressionMethod elements.
*
* Sets the priority on the compression algorithms supported by gnutls.
* Priority is higher for elements specified before others.
* After specifying the algorithms you want, you must append a 0.
* Note that the priority is set on the client. The server does
* not use the algorithm's priority except for disabling
* algorithms that were not specified.
*
* TLS 1.0 does not define any compression algorithms except
* NULL. Other compression algorithms are to be considered
* as gnutls extensions.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_compression_set_priority (mhd_gtls_session_t session,
const int *list)
{
return _set_priority (&session->internals.priorities.compression, list);
}
/**
* MHD_gnutls_protocol_set_priority - Sets the priority on the protocol versions supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @list: is a 0 terminated list of enum MHD_GNUTLS_Protocol elements.
*
* Sets the priority on the protocol versions supported by gnutls.
* This function actually enables or disables protocols. Newer protocol
* versions always have highest priority.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_protocol_set_priority (mhd_gtls_session_t session, const int *list)
{
int ret;
ret = _set_priority (&session->internals.priorities.protocol, list);
/* set the current version to the first in the chain.
* This will be overridden later.
*/
mhd_gtls_set_current_version (session, list[0]);
return ret;
}
/**
* MHD_gnutls_certificate_type_set_priority - Sets the priority on the certificate types supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @list: is a 0 terminated list of enum MHD_GNUTLS_CertificateType elements.
*
* Sets the priority on the certificate types supported by gnutls.
* Priority is higher for elements specified before others.
* After specifying the types you want, you must append a 0.
* Note that the certificate type priority is set on the client.
* The server does not use the cert type priority except for disabling
* types that were not specified.
*
* Returns 0 on success.
*
**/
int
MHD_gnutls_certificate_type_set_priority (mhd_gtls_session_t session,
const int *list)
{
#if ENABLE_OPENPGP
return _set_priority (&session->internals.priorities.cert_type, list);
#else
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
#endif
}
static const int mhd_gtls_protocol_priority[] = { MHD_GNUTLS_TLS1_1,
MHD_GNUTLS_TLS1_0,
MHD_GNUTLS_SSL3,
0
};
static const int mhd_gtls_cipher_priority_secure256[] =
{ MHD_GNUTLS_CIPHER_AES_256_CBC,
0
};
static const int mhd_gtls_kx_priority_secure[] = { MHD_GNUTLS_KX_RSA,
0
};
static const int mhd_gtls_mac_priority_secure[] = { MHD_GNUTLS_MAC_SHA1,
0
};
static int mhd_gtls_cert_type_priority[] = { MHD_GNUTLS_CRT_X509,
0
};
static const int mhd_gtls_comp_priority[] = { MHD_GNUTLS_COMP_NULL,
0
};
typedef void (rmadd_func) (mhd_gtls_priority_st * priority_list, int alg);
/**
* MHD_gnutls_priority_set - Sets priorities for the cipher suites supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @priority: is a #gnutls_priority_t structure.
*
* Sets the priorities to use on the ciphers, key exchange methods,
* macs and compression methods.
*
* On success 0 is returned.
*
**/
int
MHD_gnutls_priority_set (mhd_gtls_session_t session,
gnutls_priority_t priority)
{
if (priority == NULL)
{
gnutls_assert ();
return GNUTLS_E_NO_CIPHER_SUITES;
}
memcpy (&session->internals.priorities, priority,
sizeof (struct MHD_gtls_priority_st));
return 0;
}
/**
* MHD_tls_set_default_priority - Sets priorities for the cipher suites supported by gnutls.
* @priority_cache: is a #gnutls_prioritity_t structure.
* @priorities: is a string describing priorities
* @err_pos: In case of an error this will have the position in the string the error occured
*
* Sets priorities for the ciphers, key exchange methods, macs and
* compression methods. This is to avoid using the
* gnutls_*_priority() functions.
*
* The #priorities option allows you to specify a semi-colon
* separated list of the cipher priorities to enable.
*
* Unless the first keyword is "NONE" the defaults are:
* Protocols: TLS1.1, TLS1.0, and SSL3.0.
* Compression: NULL.
* Certificate types: X.509, OpenPGP.
*
* You can also use predefined sets of ciphersuites: "PERFORMANCE"
* all the "secure" ciphersuites are enabled, limited to 128 bit
* ciphers and sorted by terms of speed performance.
*
* "NORMAL" option enables all "secure" ciphersuites. The 256-bit ciphers
* are included as a fallback only. The ciphers are sorted by security margin.
*
* "SECURE128" flag enables all "secure" ciphersuites with ciphers up to
* 128 bits, sorted by security margin.
*
* "SECURE256" flag enables all "secure" ciphersuites including the 256 bit
* ciphers, sorted by security margin.
*
* "EXPORT" all the ciphersuites are enabled, including the
* low-security 40 bit ciphers.
*
* "NONE" nothing is enabled. This disables even protocols and
* compression methods.
*
* Special keywords:
* '!' or '-' appended with an algorithm will remove this algorithm.
* '+' appended with an algorithm will add this algorithm.
* '%COMPAT' will enable compatibility features for a server.
*
* To avoid collisions in order to specify a compression algorithm in
* this string you have to prefix it with "COMP-", protocol versions
* with "VERS-" and certificate types with "CTYPE-". All other
* algorithms don't need a prefix.
*
* For key exchange algorithms when in NORMAL or SECURE levels the
* perfect forward secrecy algorithms take precendence of the other
* protocols. In all cases all the supported key exchange algorithms
* are enabled (except for the RSA-EXPORT which is only enabled in
* EXPORT level).
*
* Note that although one can select very long key sizes (such as 256 bits)
* for symmetric algorithms, to actually increase security the public key
* algorithms have to use longer key sizes as well.
*
* Examples: "NORMAL:!AES-128-CBC",
* "EXPORT:!VERS-TLS1.0:+COMP-DEFLATE:+CTYPE-OPENPGP",
* "NONE:+VERS-TLS1.0:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL", "NORMAL",
* "NORMAL:%COMPAT".
*
* Returns: On syntax error GNUTLS_E_INVALID_REQUEST is returned and
* 0 on success.
**/
int
MHD_tls_set_default_priority (gnutls_priority_t * priority_cache,
const char *priorities, const char **err_pos)
{
*priority_cache = gnutls_calloc (1, sizeof (struct MHD_gtls_priority_st));
if (*priority_cache == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
}
/* set mode to "SECURE256" */
_set_priority (&(*priority_cache)->protocol, mhd_gtls_protocol_priority);
_set_priority (&(*priority_cache)->cipher,
mhd_gtls_cipher_priority_secure256);
_set_priority (&(*priority_cache)->kx, mhd_gtls_kx_priority_secure);
_set_priority (&(*priority_cache)->mac, mhd_gtls_mac_priority_secure);
_set_priority (&(*priority_cache)->cert_type, mhd_gtls_cert_type_priority);
_set_priority (&(*priority_cache)->compression, mhd_gtls_comp_priority);
(*priority_cache)->no_padding = 0;
return 0;
}
/**
* MHD_gnutls_priority_deinit - Deinitialize the priorities cache for the cipher suites supported by gnutls.
* @priority_cache: is a #gnutls_prioritity_t structure.
*
* Deinitializes the priority cache.
*
**/
void
MHD_gnutls_priority_deinit (gnutls_priority_t priority_cache)
{
gnutls_free (priority_cache);
}
/**
* MHD_gnutls_priority_set_direct - Sets priorities for the cipher suites supported by gnutls.
* @session: is a #mhd_gtls_session_t structure.
* @priorities: is a string describing priorities
* @err_pos: In case of an error this will have the position in the string the error occured
*
* Sets the priorities to use on the ciphers, key exchange methods,
* macs and compression methods. This function avoids keeping a
* priority cache and is used to directly set string priorities to a
* TLS session. For documentation check the MHD_tls_set_default_priority().
*
* On syntax error GNUTLS_E_INVALID_REQUEST is returned and 0 on success.
*
**/
int
MHD_gnutls_priority_set_direct (mhd_gtls_session_t session,
const char *priorities, const char **err_pos)
{
gnutls_priority_t prio;
int ret;
ret = MHD_tls_set_default_priority (&prio, priorities, err_pos);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
ret = MHD_gnutls_priority_set (session, prio);
if (ret < 0)
{
gnutls_assert ();
return ret;
}
MHD_gnutls_priority_deinit (prio);
return 0;
}