Blame lib/algorithms/kx.c

Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Author: Nikos Mavrogiannopoulos
Packit Service 4684c1
 *
Packit Service 4684c1
 * This file is part of GnuTLS.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The GnuTLS is free software; you can redistribute it and/or
Packit Service 4684c1
 * modify it under the terms of the GNU Lesser General Public License
Packit Service 4684c1
 * as published by the Free Software Foundation; either version 2.1 of
Packit Service 4684c1
 * the License, or (at your option) any later version.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This library is distributed in the hope that it will be useful, but
Packit Service 4684c1
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 4684c1
 * Lesser General Public License for more details.
Packit Service 4684c1
 *
Packit Service 4684c1
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 4684c1
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit Service 4684c1
 *
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#include "gnutls_int.h"
Packit Service 4684c1
#include <algorithms.h>
Packit Service 4684c1
#include "errors.h"
Packit Service 4684c1
#include <x509/common.h>
Packit Service 4684c1
#include "state.h"
Packit Service 4684c1
#include "c-strcase.h"
Packit Service 4684c1
Packit Service 4684c1
extern mod_auth_st rsa_auth_struct;
Packit Service 4684c1
extern mod_auth_st dhe_rsa_auth_struct;
Packit Service 4684c1
extern mod_auth_st ecdhe_rsa_auth_struct;
Packit Service 4684c1
extern mod_auth_st ecdhe_psk_auth_struct;
Packit Service 4684c1
extern mod_auth_st ecdhe_ecdsa_auth_struct;
Packit Service 4684c1
extern mod_auth_st dhe_dss_auth_struct;
Packit Service 4684c1
extern mod_auth_st anon_auth_struct;
Packit Service 4684c1
extern mod_auth_st anon_ecdh_auth_struct;
Packit Service 4684c1
extern mod_auth_st srp_auth_struct;
Packit Service 4684c1
extern mod_auth_st psk_auth_struct;
Packit Service 4684c1
extern mod_auth_st dhe_psk_auth_struct;
Packit Service 4684c1
extern mod_auth_st rsa_psk_auth_struct;
Packit Service 4684c1
extern mod_auth_st srp_rsa_auth_struct;
Packit Service 4684c1
extern mod_auth_st srp_dss_auth_struct;
Packit Service 4684c1
extern mod_auth_st vko_gost_auth_struct;
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* Cred type mappings to KX algorithms
Packit Service 4684c1
 * The mappings are not 1-1. Some KX such as SRP_RSA require
Packit Service 4684c1
 * more than one credentials type.
Packit Service 4684c1
 */
Packit Service 4684c1
typedef struct {
Packit Service 4684c1
	gnutls_kx_algorithm_t algorithm;
Packit Service 4684c1
	gnutls_credentials_type_t client_type;
Packit Service 4684c1
	gnutls_credentials_type_t server_type;	/* The type of credentials a server
Packit Service 4684c1
						 * needs to set */
Packit Service 4684c1
} gnutls_cred_map;
Packit Service 4684c1
Packit Service 4684c1
static const gnutls_cred_map cred_mappings[] = {
Packit Service 4684c1
	{GNUTLS_KX_ECDHE_RSA, GNUTLS_CRD_CERTIFICATE,
Packit Service 4684c1
	 GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_ECDHE_ECDSA, GNUTLS_CRD_CERTIFICATE,
Packit Service 4684c1
	 GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE,
Packit Service 4684c1
	 GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE,
Packit Service 4684c1
	 GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_ECDHE_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
Packit Service 4684c1
	{GNUTLS_KX_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
Packit Service 4684c1
	{GNUTLS_KX_DHE_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
Packit Service 4684c1
	{GNUTLS_KX_RSA_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_SRP, GNUTLS_CRD_SRP, GNUTLS_CRD_SRP},
Packit Service 4684c1
	{GNUTLS_KX_SRP_RSA, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_SRP_DSS, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{GNUTLS_KX_ANON_DH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
Packit Service 4684c1
	{GNUTLS_KX_ANON_ECDH, GNUTLS_CRD_ANON, GNUTLS_CRD_ANON},
Packit Service 4684c1
	{GNUTLS_KX_VKO_GOST_12, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
Packit Service 4684c1
	{0, 0, 0}
Packit Service 4684c1
};
Packit Service 4684c1
Packit Service 4684c1
#define GNUTLS_KX_MAP_LOOP(b) \
Packit Service 4684c1
	const gnutls_cred_map *p; \
Packit Service 4684c1
		for(p = cred_mappings; p->algorithm != 0; p++) { b ; }
Packit Service 4684c1
Packit Service 4684c1
struct gnutls_kx_algo_entry {
Packit Service 4684c1
	const char *name;
Packit Service 4684c1
	gnutls_kx_algorithm_t algorithm;
Packit Service 4684c1
	mod_auth_st *auth_struct;
Packit Service 4684c1
	bool needs_dh_params;
Packit Service 4684c1
	bool false_start;
Packit Service 4684c1
};
Packit Service 4684c1
typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry;
Packit Service 4684c1
Packit Service 4684c1
static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = {
Packit Service 4684c1
#ifdef ENABLE_ECDHE
Packit Service 4684c1
	{"ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, &ecdhe_rsa_auth_struct, 0, 1},
Packit Service 4684c1
	{"ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, &ecdhe_ecdsa_auth_struct,
Packit Service 4684c1
	 0, 1},
Packit Service 4684c1
#endif
Packit Service 4684c1
	{"RSA", GNUTLS_KX_RSA, &rsa_auth_struct, 0, 0},
Packit Service 4684c1
#ifdef ENABLE_DHE
Packit Service 4684c1
	{"DHE-RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1, 1},
Packit Service 4684c1
	{"DHE-DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, 1},
Packit Service 4684c1
#endif
Packit Service 4684c1
#ifdef ENABLE_PSK
Packit Service 4684c1
	{"PSK", GNUTLS_KX_PSK, &psk_auth_struct, 0, 0},
Packit Service 4684c1
	{"RSA-PSK", GNUTLS_KX_RSA_PSK, &rsa_psk_auth_struct, 0, 0},
Packit Service 4684c1
#ifdef ENABLE_DHE
Packit Service 4684c1
	{"DHE-PSK", GNUTLS_KX_DHE_PSK, &dhe_psk_auth_struct,
Packit Service 4684c1
	 1 /* needs DHE params */, 0},
Packit Service 4684c1
#endif
Packit Service 4684c1
#ifdef ENABLE_ECDHE
Packit Service 4684c1
	{"ECDHE-PSK", GNUTLS_KX_ECDHE_PSK, &ecdhe_psk_auth_struct, 0, 0},
Packit Service 4684c1
#endif
Packit Service 4684c1
#endif
Packit Service 4684c1
#ifdef ENABLE_SRP
Packit Service 4684c1
	{"SRP-DSS", GNUTLS_KX_SRP_DSS, &srp_dss_auth_struct, 0, 0},
Packit Service 4684c1
	{"SRP-RSA", GNUTLS_KX_SRP_RSA, &srp_rsa_auth_struct, 0, 0},
Packit Service 4684c1
	{"SRP", GNUTLS_KX_SRP, &srp_auth_struct, 0, 0},
Packit Service 4684c1
#endif
Packit Service 4684c1
#if defined(ENABLE_ANON) && defined(ENABLE_DHE)
Packit Service 4684c1
	{"ANON-DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1, 0},
Packit Service 4684c1
#endif
Packit Service 4684c1
#if defined(ENABLE_ANON) && defined(ENABLE_ECDHE)
Packit Service 4684c1
	{"ANON-ECDH", GNUTLS_KX_ANON_ECDH, &anon_ecdh_auth_struct, 0, 0},
Packit Service 4684c1
#endif
Packit Service 4684c1
#ifdef ENABLE_GOST
Packit Service 4684c1
	{"VKO-GOST-12", GNUTLS_KX_VKO_GOST_12, &vko_gost_auth_struct, 0, 0},
Packit Service 4684c1
#endif
Packit Service 4684c1
	/* for deprecated and legacy algorithms no longer supported, use
Packit Service 4684c1
	 * GNUTLS_KX_INVALID as an entry. This will make them available
Packit Service 4684c1
	 * as priority strings, but they will be a no-op.
Packit Service 4684c1
	 */
Packit Service 4684c1
	{"RSA-EXPORT", GNUTLS_KX_INVALID, NULL, 0, 0},
Packit Service 4684c1
	{0, 0, 0, 0, 0}
Packit Service 4684c1
};
Packit Service 4684c1
Packit Service 4684c1
#define GNUTLS_KX_LOOP(b) \
Packit Service 4684c1
	const gnutls_kx_algo_entry *p; \
Packit Service 4684c1
		for(p = _gnutls_kx_algorithms; p->name != NULL; p++) { b ; }
Packit Service 4684c1
Packit Service 4684c1
#define GNUTLS_KX_ALG_LOOP(a) \
Packit Service 4684c1
			GNUTLS_KX_LOOP( if(p->algorithm == algorithm) { a; break; } )
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/* Key EXCHANGE functions */
Packit Service 4684c1
mod_auth_st *_gnutls_kx_auth_struct(gnutls_kx_algorithm_t algorithm)
Packit Service 4684c1
{
Packit Service 4684c1
	mod_auth_st *ret = NULL;
Packit Service 4684c1
	GNUTLS_KX_ALG_LOOP(ret = p->auth_struct);
Packit Service 4684c1
	return ret;
Packit Service 4684c1
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_kx_get_name:
Packit Service 4684c1
 * @algorithm: is a key exchange algorithm
Packit Service 4684c1
 *
Packit Service 4684c1
 * Convert a #gnutls_kx_algorithm_t value to a string.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: a pointer to a string that contains the name of the
Packit Service 4684c1
 *   specified key exchange algorithm, or %NULL.
Packit Service 4684c1
 **/
Packit Service 4684c1
const char *gnutls_kx_get_name(gnutls_kx_algorithm_t algorithm)
Packit Service 4684c1
{
Packit Service 4684c1
	const char *ret = NULL;
Packit Service 4684c1
Packit Service 4684c1
	/* avoid prefix */
Packit Service 4684c1
	GNUTLS_KX_ALG_LOOP(ret = p->name);
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_kx_get_id:
Packit Service 4684c1
 * @name: is a KX name
Packit Service 4684c1
 *
Packit Service 4684c1
 * Convert a string to a #gnutls_kx_algorithm_t value.  The names are
Packit Service 4684c1
 * compared in a case insensitive way.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: an id of the specified KX algorithm, or %GNUTLS_KX_UNKNOWN
Packit Service 4684c1
 *   on error.
Packit Service 4684c1
 **/
Packit Service 4684c1
gnutls_kx_algorithm_t gnutls_kx_get_id(const char *name)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_kx_algorithm_t ret = GNUTLS_KX_UNKNOWN;
Packit Service 4684c1
Packit Service 4684c1
	GNUTLS_KX_LOOP(
Packit Service 4684c1
		if (c_strcasecmp(p->name, name) == 0 && (int)p->algorithm != GNUTLS_KX_INVALID) {
Packit Service 4684c1
			ret = p->algorithm;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	);
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* As with gnutls_kx_get_id(), but it returns all known
Packit Service 4684c1
 * key exchange algorithms (even legacy), with GNUTLS_KX_INVALID
Packit Service 4684c1
 * value.
Packit Service 4684c1
 */
Packit Service 4684c1
int _gnutls_kx_get_id(const char *name)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_kx_algorithm_t ret = GNUTLS_KX_UNKNOWN;
Packit Service 4684c1
Packit Service 4684c1
	GNUTLS_KX_LOOP(
Packit Service 4684c1
		if (c_strcasecmp(p->name, name) == 0) {
Packit Service 4684c1
			ret = p->algorithm;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	);
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_kx_list:
Packit Service 4684c1
 *
Packit Service 4684c1
 * Get a list of supported key exchange algorithms.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function is not thread safe.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: a (0)-terminated list of #gnutls_kx_algorithm_t integers
Packit Service 4684c1
 * indicating the available key exchange algorithms.
Packit Service 4684c1
 **/
Packit Service 4684c1
const gnutls_kx_algorithm_t *gnutls_kx_list(void)
Packit Service 4684c1
{
Packit Service 4684c1
	static gnutls_kx_algorithm_t supported_kxs[MAX_ALGOS] = { 0 };
Packit Service 4684c1
Packit Service 4684c1
	if (supported_kxs[0] == 0) {
Packit Service 4684c1
		int i = 0;
Packit Service 4684c1
Packit Service 4684c1
		GNUTLS_KX_LOOP(supported_kxs[i++] = p->algorithm);
Packit Service 4684c1
		supported_kxs[i++] = 0;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return supported_kxs;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
int _gnutls_kx_is_ok(gnutls_kx_algorithm_t algorithm)
Packit Service 4684c1
{
Packit Service 4684c1
	ssize_t ret = -1;
Packit Service 4684c1
	GNUTLS_KX_ALG_LOOP(ret = p->algorithm);
Packit Service 4684c1
	if (ret >= 0)
Packit Service 4684c1
		ret = 0;
Packit Service 4684c1
	else
Packit Service 4684c1
		ret = 1;
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
bool _gnutls_kx_allows_false_start(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	unsigned algorithm = session->security_parameters.cs->kx_algorithm;
Packit Service 4684c1
	bool needs_dh = 0;
Packit Service 4684c1
	int bits;
Packit Service 4684c1
Packit Service 4684c1
	ssize_t ret = 0;
Packit Service 4684c1
	GNUTLS_KX_ALG_LOOP(ret = p->false_start; needs_dh = p->needs_dh_params);
Packit Service 4684c1
Packit Service 4684c1
	if (ret != 0) {
Packit Service 4684c1
		const gnutls_group_entry_st *e;
Packit Service 4684c1
Packit Service 4684c1
		e = get_group(session);
Packit Service 4684c1
Packit Service 4684c1
#if defined(ENABLE_DHE) || defined(ENABLE_ANON)
Packit Service 4684c1
		if (needs_dh != 0) {
Packit Service 4684c1
			bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_HIGH);
Packit Service 4684c1
			/* check whether sizes are sufficient */
Packit Service 4684c1
			if (e && e->prime) {
Packit Service 4684c1
				if (e->prime->size*8 < (unsigned)bits)
Packit Service 4684c1
					ret = 0;
Packit Service 4684c1
			} else if (gnutls_dh_get_prime_bits(session) < bits)
Packit Service 4684c1
				ret = 0;
Packit Service 4684c1
		} else
Packit Service 4684c1
#endif
Packit Service 4684c1
		if (algorithm == GNUTLS_KX_ECDHE_RSA || algorithm == GNUTLS_KX_ECDHE_ECDSA) {
Packit Service 4684c1
			bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_EC, GNUTLS_SEC_PARAM_HIGH);
Packit Service 4684c1
Packit Service 4684c1
			if (e != NULL && gnutls_ecc_curve_get_size(e->curve) * 8 < bits)
Packit Service 4684c1
				ret = 0;
Packit Service 4684c1
		}
Packit Service 4684c1
	}
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
bool _gnutls_kx_needs_dh_params(gnutls_kx_algorithm_t algorithm)
Packit Service 4684c1
{
Packit Service 4684c1
	ssize_t ret = 0;
Packit Service 4684c1
	GNUTLS_KX_ALG_LOOP(ret = p->needs_dh_params);
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Returns the credentials type required for this
Packit Service 4684c1
 * Key exchange method.
Packit Service 4684c1
 */
Packit Service 4684c1
gnutls_credentials_type_t
Packit Service 4684c1
_gnutls_map_kx_get_cred(gnutls_kx_algorithm_t algorithm, int server)
Packit Service 4684c1
{
Packit Service 4684c1
	gnutls_credentials_type_t ret = -1;
Packit Service 4684c1
	if (server) {
Packit Service 4684c1
		GNUTLS_KX_MAP_LOOP(if (p->algorithm == algorithm) ret =
Packit Service 4684c1
				   p->server_type);
Packit Service 4684c1
	} else {
Packit Service 4684c1
		GNUTLS_KX_MAP_LOOP(if (p->algorithm == algorithm) ret =
Packit Service 4684c1
				   p->client_type);
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return ret;
Packit Service 4684c1
}