Blame lib/dh-session.c

Packit Service 4684c1
/*
Packit Service 4684c1
 * Copyright (C) 2001-2015 Free Software Foundation, Inc.
Packit Service 4684c1
 * Copyright (C) 2015 Nikos Mavrogiannopoulos
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
/* This file contains certificate authentication functions to be exported in the
Packit Service 4684c1
 * API which did not fit elsewhere.
Packit Service 4684c1
 */
Packit Service 4684c1
Packit Service 4684c1
#include "gnutls_int.h"
Packit Service 4684c1
#include <auth/srp_kx.h>
Packit Service 4684c1
#include <auth/anon.h>
Packit Service 4684c1
#include <auth/cert.h>
Packit Service 4684c1
#include <auth/psk.h>
Packit Service 4684c1
#include "errors.h"
Packit Service 4684c1
#include <auth.h>
Packit Service 4684c1
#include <state.h>
Packit Service 4684c1
#include <datum.h>
Packit Service 4684c1
#include <algorithms.h>
Packit Service 4684c1
Packit Service 4684c1
/* ANON & DHE */
Packit Service 4684c1
Packit Service 4684c1
#if defined(ENABLE_DHE) || defined(ENABLE_ANON)
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_dh_set_prime_bits:
Packit Service 4684c1
 * @session: is a #gnutls_session_t type.
Packit Service 4684c1
 * @bits: is the number of bits
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function sets the number of bits, for use in a Diffie-Hellman
Packit Service 4684c1
 * key exchange.  This is used both in DH ephemeral and DH anonymous
Packit Service 4684c1
 * cipher suites.  This will set the minimum size of the prime that
Packit Service 4684c1
 * will be used for the handshake.
Packit Service 4684c1
 *
Packit Service 4684c1
 * In the client side it sets the minimum accepted number of bits.  If
Packit Service 4684c1
 * a server sends a prime with less bits than that
Packit Service 4684c1
 * %GNUTLS_E_DH_PRIME_UNACCEPTABLE will be returned by the handshake.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Note that this function will warn via the audit log for value that
Packit Service 4684c1
 * are believed to be weak.
Packit Service 4684c1
 *
Packit Service 4684c1
 * The function has no effect in server side.
Packit Service 4684c1
 * 
Packit Service 4684c1
 * Note that since 3.1.7 this function is deprecated. The minimum
Packit Service 4684c1
 * number of bits is set by the priority string level.
Packit Service 4684c1
 * Also this function must be called after gnutls_priority_set_direct()
Packit Service 4684c1
 * or the set value may be overridden by the selected priority options.
Packit Service 4684c1
 *
Packit Service 4684c1
 *
Packit Service 4684c1
 **/
Packit Service 4684c1
void gnutls_dh_set_prime_bits(gnutls_session_t session, unsigned int bits)
Packit Service 4684c1
{
Packit Service 4684c1
	if (bits < gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_WEAK)
Packit Service 4684c1
		&& bits != 0)
Packit Service 4684c1
		_gnutls_audit_log(session,
Packit Service 4684c1
				  "Note that the security level of the Diffie-Hellman key exchange has been lowered to %u bits and this may allow decryption of the session data\n",
Packit Service 4684c1
				  bits);
Packit Service 4684c1
	session->internals.dh_prime_bits = bits;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_dh_get_group:
Packit Service 4684c1
 * @session: is a gnutls session
Packit Service 4684c1
 * @raw_gen: will hold the generator.
Packit Service 4684c1
 * @raw_prime: will hold the prime.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will return the group parameters used in the last
Packit Service 4684c1
 * Diffie-Hellman key exchange with the peer.  These are the prime and
Packit Service 4684c1
 * the generator used.  This function should be used for both
Packit Service 4684c1
 * anonymous and ephemeral Diffie-Hellman.  The output parameters must
Packit Service 4684c1
 * be freed with gnutls_free().
Packit Service 4684c1
 *
Packit Service 4684c1
 * Note, that the prime and generator are exported as non-negative
Packit Service 4684c1
 * integers and may include a leading zero byte.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
Packit Service 4684c1
 *   an error code is returned.
Packit Service 4684c1
 **/
Packit Service 4684c1
int
Packit Service 4684c1
gnutls_dh_get_group(gnutls_session_t session,
Packit Service 4684c1
		    gnutls_datum_t * raw_gen, gnutls_datum_t * raw_prime)
Packit Service 4684c1
{
Packit Service 4684c1
	dh_info_st *dh;
Packit Service 4684c1
	int ret;
Packit Service 4684c1
	anon_auth_info_t anon_info;
Packit Service 4684c1
	cert_auth_info_t cert_info;
Packit Service 4684c1
	psk_auth_info_t psk_info;
Packit Service 4684c1
Packit Service 4684c1
	switch (gnutls_auth_get_type(session)) {
Packit Service 4684c1
	case GNUTLS_CRD_ANON:
Packit Service 4684c1
		anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
Packit Service 4684c1
		if (anon_info == NULL)
Packit Service 4684c1
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
		dh = &anon_info->dh;
Packit Service 4684c1
		break;
Packit Service 4684c1
	case GNUTLS_CRD_PSK:
Packit Service 4684c1
		psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
Packit Service 4684c1
		if (psk_info == NULL)
Packit Service 4684c1
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
		dh = &psk_info->dh;
Packit Service 4684c1
		break;
Packit Service 4684c1
	case GNUTLS_CRD_CERTIFICATE:
Packit Service 4684c1
		cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
Packit Service 4684c1
		if (cert_info == NULL)
Packit Service 4684c1
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
		dh = &cert_info->dh;
Packit Service 4684c1
		break;
Packit Service 4684c1
	default:
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_INVALID_REQUEST;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret = _gnutls_set_datum(raw_prime, dh->prime.data, dh->prime.size);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return ret;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	ret =
Packit Service 4684c1
	    _gnutls_set_datum(raw_gen, dh->generator.data,
Packit Service 4684c1
			      dh->generator.size);
Packit Service 4684c1
	if (ret < 0) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		_gnutls_free_datum(raw_prime);
Packit Service 4684c1
		return ret;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return 0;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_dh_get_pubkey:
Packit Service 4684c1
 * @session: is a gnutls session
Packit Service 4684c1
 * @raw_key: will hold the public key.
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will return the peer's public key used in the last
Packit Service 4684c1
 * Diffie-Hellman key exchange.  This function should be used for both
Packit Service 4684c1
 * anonymous and ephemeral Diffie-Hellman.  The output parameters must
Packit Service 4684c1
 * be freed with gnutls_free().
Packit Service 4684c1
 *
Packit Service 4684c1
 * Note, that public key is exported as non-negative
Packit Service 4684c1
 * integer and may include a leading zero byte.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
Packit Service 4684c1
 *   an error code is returned.
Packit Service 4684c1
 **/
Packit Service 4684c1
int
Packit Service 4684c1
gnutls_dh_get_pubkey(gnutls_session_t session, gnutls_datum_t * raw_key)
Packit Service 4684c1
{
Packit Service 4684c1
	dh_info_st *dh;
Packit Service 4684c1
	anon_auth_info_t anon_info;
Packit Service 4684c1
	cert_auth_info_t cert_info;
Packit Service 4684c1
	psk_auth_info_t psk_info;
Packit Service 4684c1
Packit Service 4684c1
	switch (gnutls_auth_get_type(session)) {
Packit Service 4684c1
	case GNUTLS_CRD_ANON:
Packit Service 4684c1
		{
Packit Service 4684c1
			anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
Packit Service 4684c1
			if (anon_info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
			dh = &anon_info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_PSK:
Packit Service 4684c1
		{
Packit Service 4684c1
			psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
Packit Service 4684c1
			if (psk_info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
			dh = &psk_info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_CERTIFICATE:
Packit Service 4684c1
		{
Packit Service 4684c1
Packit Service 4684c1
			cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
Packit Service 4684c1
			if (cert_info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
			dh = &cert_info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	default:
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_INVALID_REQUEST;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return _gnutls_set_datum(raw_key, dh->public_key.data,
Packit Service 4684c1
				 dh->public_key.size);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_dh_get_secret_bits:
Packit Service 4684c1
 * @session: is a gnutls session
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will return the bits used in the last Diffie-Hellman
Packit Service 4684c1
 * key exchange with the peer.  Should be used for both anonymous and
Packit Service 4684c1
 * ephemeral Diffie-Hellman.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
Packit Service 4684c1
 *   an error code is returned.
Packit Service 4684c1
 **/
Packit Service 4684c1
int gnutls_dh_get_secret_bits(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	switch (gnutls_auth_get_type(session)) {
Packit Service 4684c1
	case GNUTLS_CRD_ANON:
Packit Service 4684c1
		{
Packit Service 4684c1
			anon_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
			return info->dh.secret_bits;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_PSK:
Packit Service 4684c1
		{
Packit Service 4684c1
			psk_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
			return info->dh.secret_bits;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_CERTIFICATE:
Packit Service 4684c1
		{
Packit Service 4684c1
			cert_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
Packit Service 4684c1
			return info->dh.secret_bits;
Packit Service 4684c1
		}
Packit Service 4684c1
	default:
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_INVALID_REQUEST;
Packit Service 4684c1
	}
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
static int mpi_buf2bits(gnutls_datum_t * mpi_buf)
Packit Service 4684c1
{
Packit Service 4684c1
	bigint_t mpi;
Packit Service 4684c1
	int rc;
Packit Service 4684c1
Packit Service 4684c1
	rc = _gnutls_mpi_init_scan_nz(&mpi, mpi_buf->data, mpi_buf->size);
Packit Service 4684c1
	if (rc) {
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return rc;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	rc = _gnutls_mpi_get_nbits(mpi);
Packit Service 4684c1
	_gnutls_mpi_release(&mpi;;
Packit Service 4684c1
Packit Service 4684c1
	return rc;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_dh_get_prime_bits:
Packit Service 4684c1
 * @session: is a gnutls session
Packit Service 4684c1
 *
Packit Service 4684c1
 * This function will return the bits of the prime used in the last
Packit Service 4684c1
 * Diffie-Hellman key exchange with the peer.  Should be used for both
Packit Service 4684c1
 * anonymous and ephemeral Diffie-Hellman.  Note that some ciphers,
Packit Service 4684c1
 * like RSA and DSA without DHE, do not use a Diffie-Hellman key
Packit Service 4684c1
 * exchange, and then this function will return 0.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: The Diffie-Hellman bit strength is returned, or 0 if no
Packit Service 4684c1
 *   Diffie-Hellman key exchange was done, or a negative error code on
Packit Service 4684c1
 *   failure.
Packit Service 4684c1
 **/
Packit Service 4684c1
int gnutls_dh_get_prime_bits(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	dh_info_st *dh;
Packit Service 4684c1
Packit Service 4684c1
	switch (gnutls_auth_get_type(session)) {
Packit Service 4684c1
	case GNUTLS_CRD_ANON:
Packit Service 4684c1
		{
Packit Service 4684c1
			anon_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
			dh = &info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_PSK:
Packit Service 4684c1
		{
Packit Service 4684c1
			psk_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
			dh = &info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_CERTIFICATE:
Packit Service 4684c1
		{
Packit Service 4684c1
			cert_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
Packit Service 4684c1
			dh = &info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	default:
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_INVALID_REQUEST;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	if(dh->prime.size == 0)
Packit Service 4684c1
		return 0;
Packit Service 4684c1
Packit Service 4684c1
	return mpi_buf2bits(&dh->prime);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
Packit Service 4684c1
/**
Packit Service 4684c1
 * gnutls_dh_get_peers_public_bits:
Packit Service 4684c1
 * @session: is a gnutls session
Packit Service 4684c1
 *
Packit Service 4684c1
 * Get the Diffie-Hellman public key bit size.  Can be used for both
Packit Service 4684c1
 * anonymous and ephemeral Diffie-Hellman.
Packit Service 4684c1
 *
Packit Service 4684c1
 * Returns: The public key bit size used in the last Diffie-Hellman
Packit Service 4684c1
 *   key exchange with the peer, or a negative error code in case of error.
Packit Service 4684c1
 **/
Packit Service 4684c1
int gnutls_dh_get_peers_public_bits(gnutls_session_t session)
Packit Service 4684c1
{
Packit Service 4684c1
	dh_info_st *dh;
Packit Service 4684c1
Packit Service 4684c1
	switch (gnutls_auth_get_type(session)) {
Packit Service 4684c1
	case GNUTLS_CRD_ANON:
Packit Service 4684c1
		{
Packit Service 4684c1
			anon_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
Packit Service 4684c1
			dh = &info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_PSK:
Packit Service 4684c1
		{
Packit Service 4684c1
			psk_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
Packit Service 4684c1
			dh = &info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	case GNUTLS_CRD_CERTIFICATE:
Packit Service 4684c1
		{
Packit Service 4684c1
			cert_auth_info_t info;
Packit Service 4684c1
Packit Service 4684c1
			info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
Packit Service 4684c1
			if (info == NULL)
Packit Service 4684c1
				return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit Service 4684c1
Packit Service 4684c1
			dh = &info->dh;
Packit Service 4684c1
			break;
Packit Service 4684c1
		}
Packit Service 4684c1
	default:
Packit Service 4684c1
		gnutls_assert();
Packit Service 4684c1
		return GNUTLS_E_INVALID_REQUEST;
Packit Service 4684c1
	}
Packit Service 4684c1
Packit Service 4684c1
	return mpi_buf2bits(&dh->public_key);
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#endif				/* DH */
Packit Service 4684c1