Blame lib/ext/ec_point_formats.c

Packit aea12f
/*
Packit aea12f
 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
Packit aea12f
 * Copyright (C) 2017 Red Hat, Inc.
Packit aea12f
 *
Packit aea12f
 * Author: Nikos Mavrogiannopoulos
Packit aea12f
 *
Packit aea12f
 * This file is part of GnuTLS.
Packit aea12f
 *
Packit aea12f
 * The GnuTLS is free software; you can redistribute it and/or
Packit aea12f
 * modify it under the terms of the GNU Lesser General Public License
Packit aea12f
 * as published by the Free Software Foundation; either version 2.1 of
Packit aea12f
 * the License, or (at your option) any later version.
Packit aea12f
 *
Packit aea12f
 * This library is distributed in the hope that it will be useful, but
Packit aea12f
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit aea12f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit aea12f
 * Lesser General Public License for more details.
Packit aea12f
 *
Packit aea12f
 * You should have received a copy of the GNU Lesser General Public License
Packit aea12f
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
Packit aea12f
 *
Packit aea12f
 */
Packit aea12f
Packit aea12f
/* This file contains the code for the Elliptic Curve Point Formats extension.
Packit aea12f
 */
Packit aea12f
Packit aea12f
#include "ext/ec_point_formats.h"
Packit aea12f
#include "str.h"
Packit aea12f
#include "state.h"
Packit aea12f
#include <gnutls/gnutls.h>
Packit aea12f
Packit aea12f
Packit aea12f
static int _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
Packit aea12f
						const uint8_t * data,
Packit aea12f
						size_t data_size);
Packit aea12f
static int _gnutls_supported_ec_point_formats_send_params(gnutls_session_t session,
Packit aea12f
						gnutls_buffer_st * extdata);
Packit aea12f
Packit aea12f
Packit aea12f
const hello_ext_entry_st ext_mod_supported_ec_point_formats = {
Packit aea12f
	.name = "Supported EC Point Formats",
Packit aea12f
	.tls_id = 11,
Packit aea12f
	.gid = GNUTLS_EXTENSION_SUPPORTED_EC_POINT_FORMATS,
Packit aea12f
	.parse_type = GNUTLS_EXT_TLS,
Packit aea12f
	.validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS |
Packit aea12f
		    GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
Packit aea12f
	.recv_func = _gnutls_supported_ec_point_formats_recv_params,
Packit aea12f
	.send_func = _gnutls_supported_ec_point_formats_send_params,
Packit aea12f
	.pack_func = NULL,
Packit aea12f
	.unpack_func = NULL,
Packit aea12f
	.deinit_func = NULL
Packit aea12f
};
Packit aea12f
Packit aea12f
Packit aea12f
/* Receive point formats
Packit aea12f
 */
Packit aea12f
static int
Packit aea12f
_gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session,
Packit aea12f
				     const uint8_t * data,
Packit 5407aa
				     size_t data_size)
Packit aea12f
{
Packit 5407aa
	size_t len, i;
Packit aea12f
	int uncompressed = 0;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
Packit aea12f
		if (data_size < 1)
Packit aea12f
			return
Packit aea12f
			    gnutls_assert_val
Packit aea12f
			    (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
Packit aea12f
Packit aea12f
		len = data[0];
Packit aea12f
		if (len < 1)
Packit aea12f
			return
Packit aea12f
			    gnutls_assert_val
Packit aea12f
			    (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
Packit aea12f
Packit aea12f
		DECR_LEN(data_size, len + 1);
Packit aea12f
Packit aea12f
		for (i = 1; i <= len; i++)
Packit aea12f
			if (data[i] == 0) {	/* uncompressed */
Packit aea12f
				uncompressed = 1;
Packit aea12f
				break;
Packit aea12f
			}
Packit aea12f
Packit aea12f
		if (uncompressed == 0)
Packit aea12f
			return
Packit aea12f
			    gnutls_assert_val
Packit aea12f
			    (GNUTLS_E_UNKNOWN_PK_ALGORITHM);
Packit aea12f
	} else {
Packit aea12f
		/* only sanity check here. We only support uncompressed points
Packit aea12f
		 * and a client must support it thus nothing to check.
Packit aea12f
		 */
Packit 5407aa
		if (data_size < 1)
Packit aea12f
			return
Packit aea12f
			    gnutls_assert_val
Packit aea12f
			    (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* returns data_size or a negative number on failure
Packit aea12f
 */
Packit aea12f
static int
Packit aea12f
_gnutls_supported_ec_point_formats_send_params(gnutls_session_t session,
Packit aea12f
				     gnutls_buffer_st * extdata)
Packit aea12f
{
Packit aea12f
	const uint8_t p[2] = { 0x01, 0x00 };	/* only support uncompressed point format */
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_SERVER
Packit aea12f
	    && !_gnutls_session_is_ecc(session))
Packit aea12f
		return 0;
Packit aea12f
Packit aea12f
	if (session->internals.priorities->groups.size > 0) {
Packit aea12f
		ret = _gnutls_buffer_append_data(extdata, p, 2);
Packit aea12f
		if (ret < 0)
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
		return 2;
Packit aea12f
	}
Packit aea12f
	return 0;
Packit aea12f
}