|
Packit |
aea12f |
/*
|
|
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 the Key Share TLS 1.3 extension.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include "gnutls_int.h"
|
|
Packit |
aea12f |
#include "errors.h"
|
|
Packit |
aea12f |
#include "num.h"
|
|
Packit |
aea12f |
#include "ext/supported_groups.h"
|
|
Packit |
aea12f |
#include <state.h>
|
|
Packit |
aea12f |
#include <num.h>
|
|
Packit |
aea12f |
#include <algorithms.h>
|
|
Packit |
aea12f |
#include "auth/psk.h"
|
|
Packit |
aea12f |
#include "auth/cert.h"
|
|
Packit |
aea12f |
#include "handshake.h"
|
|
Packit |
aea12f |
#include "../ecc.h"
|
|
Packit |
aea12f |
#include "../algorithms.h"
|
|
Packit |
aea12f |
#include "pk.h"
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static int key_share_recv_params(gnutls_session_t session,
|
|
Packit |
aea12f |
const uint8_t * data,
|
|
Packit |
aea12f |
size_t data_size);
|
|
Packit |
aea12f |
static int key_share_send_params(gnutls_session_t session,
|
|
Packit |
aea12f |
gnutls_buffer_st * extdata);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
const hello_ext_entry_st ext_mod_key_share = {
|
|
Packit |
aea12f |
.name = "Key Share",
|
|
Packit |
aea12f |
.tls_id = 51,
|
|
Packit |
aea12f |
.gid = GNUTLS_EXTENSION_KEY_SHARE,
|
|
Packit |
aea12f |
.parse_type = _GNUTLS_EXT_TLS_POST_CS,
|
|
Packit |
aea12f |
.validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO |
|
|
Packit |
aea12f |
GNUTLS_EXT_FLAG_HRR,
|
|
Packit |
aea12f |
.recv_func = key_share_recv_params,
|
|
Packit |
aea12f |
.send_func = key_share_send_params,
|
|
Packit |
aea12f |
.pack_func = NULL,
|
|
Packit |
aea12f |
.unpack_func = NULL,
|
|
Packit |
aea12f |
.deinit_func = NULL,
|
|
Packit |
aea12f |
.cannot_be_overriden = 1
|
|
Packit |
aea12f |
};
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/*
|
|
Packit |
aea12f |
* Generates key exchange parameters, and stores them in
|
|
Packit |
aea12f |
* session->key.kshare_*_params.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* struct {
|
|
Packit |
aea12f |
* NamedGroup group;
|
|
Packit |
aea12f |
* opaque key_exchange<1..2^16-1>;
|
|
Packit |
aea12f |
* } KeyShareEntry;
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
static int client_gen_key_share(gnutls_session_t session, const gnutls_group_entry_st *group, gnutls_buffer_st *extdata)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_datum_t tmp = {NULL, 0};
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group->pk != GNUTLS_PK_EC && group->pk != GNUTLS_PK_ECDH_X25519 &&
|
|
Packit |
aea12f |
group->pk != GNUTLS_PK_DH) {
|
|
Packit |
aea12f |
_gnutls_debug_log("Cannot send key share for group %s!\n", group->name);
|
|
Packit |
aea12f |
return GNUTLS_E_INT_RET_0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_handshake_log("EXT[%p]: sending key share for %s\n", session, group->name);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_prefix(extdata, 16, group->tls_id);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group->pk == GNUTLS_PK_EC) {
|
|
Packit |
aea12f |
gnutls_pk_params_release(&session->key.kshare.ecdh_params);
|
|
Packit |
aea12f |
gnutls_pk_params_init(&session->key.kshare.ecdh_params);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_pk_generate_keys(group->pk, group->curve,
|
|
Packit |
aea12f |
&session->key.kshare.ecdh_params, 1);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_ecc_ansi_x962_export(group->curve,
|
|
Packit |
aea12f |
session->key.kshare.ecdh_params.params[ECC_X],
|
|
Packit |
aea12f |
session->key.kshare.ecdh_params.params[ECC_Y],
|
|
Packit |
aea12f |
&tmp);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_data_prefix(extdata, 16, tmp.data, tmp.size);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
goto cleanup;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
session->key.kshare.ecdh_params.algo = group->pk;
|
|
Packit |
aea12f |
session->key.kshare.ecdh_params.curve = group->curve;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_ECDH_X25519) {
|
|
Packit |
aea12f |
gnutls_pk_params_release(&session->key.kshare.ecdhx_params);
|
|
Packit |
aea12f |
gnutls_pk_params_init(&session->key.kshare.ecdhx_params);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_pk_generate_keys(group->pk, group->curve,
|
|
Packit |
aea12f |
&session->key.kshare.ecdhx_params, 1);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_data_prefix(extdata, 16,
|
|
Packit |
aea12f |
session->key.kshare.ecdhx_params.raw_pub.data,
|
|
Packit |
aea12f |
session->key.kshare.ecdhx_params.raw_pub.size);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
goto cleanup;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
session->key.kshare.ecdhx_params.algo = group->pk;
|
|
Packit |
aea12f |
session->key.kshare.ecdhx_params.curve = group->curve;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_DH) {
|
|
Packit |
aea12f |
/* we need to initialize the group parameters first */
|
|
Packit |
aea12f |
gnutls_pk_params_release(&session->key.kshare.dh_params);
|
|
Packit |
aea12f |
gnutls_pk_params_init(&session->key.kshare.dh_params);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_G],
|
|
Packit |
aea12f |
group->generator->data, group->generator->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_P],
|
|
Packit |
aea12f |
group->prime->data, group->prime->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_Q],
|
|
Packit |
aea12f |
group->q->data, group->q->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
session->key.kshare.dh_params.algo = group->pk;
|
|
Packit |
aea12f |
session->key.kshare.dh_params.dh_group = group->id; /* no curve in FFDH, we write the group */
|
|
Packit |
aea12f |
session->key.kshare.dh_params.qbits = *group->q_bits;
|
|
Packit |
aea12f |
session->key.kshare.dh_params.params_nr = 3;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_pk_generate_keys(group->pk, 0, &session->key.kshare.dh_params, 1);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_prefix(extdata, 16, group->prime->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_buffer_append_fixed_mpi(extdata, session->key.kshare.dh_params.params[DH_Y],
|
|
Packit |
aea12f |
group->prime->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
cleanup:
|
|
Packit |
aea12f |
gnutls_free(tmp.data);
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/*
|
|
Packit |
aea12f |
* Sends server key exchange parameters
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
static int server_gen_key_share(gnutls_session_t session, const gnutls_group_entry_st *group, gnutls_buffer_st *extdata)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_datum_t tmp = {NULL, 0};
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group->pk != GNUTLS_PK_EC && group->pk != GNUTLS_PK_ECDH_X25519 &&
|
|
Packit |
aea12f |
group->pk != GNUTLS_PK_DH) {
|
|
Packit |
aea12f |
_gnutls_debug_log("Cannot send key share for group %s!\n", group->name);
|
|
Packit |
aea12f |
return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_handshake_log("EXT[%p]: sending key share for %s\n", session, group->name);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_prefix(extdata, 16, group->tls_id);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group->pk == GNUTLS_PK_EC) {
|
|
Packit |
aea12f |
ret = _gnutls_ecc_ansi_x962_export(group->curve,
|
|
Packit |
aea12f |
session->key.kshare.ecdh_params.params[ECC_X],
|
|
Packit |
aea12f |
session->key.kshare.ecdh_params.params[ECC_Y],
|
|
Packit |
aea12f |
&tmp);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_data_prefix(extdata, 16, tmp.data, tmp.size);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
goto cleanup;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_ECDH_X25519) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_data_prefix(extdata, 16,
|
|
Packit |
aea12f |
session->key.kshare.ecdhx_params.raw_pub.data,
|
|
Packit |
aea12f |
session->key.kshare.ecdhx_params.raw_pub.size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_DH) {
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_prefix(extdata, 16, group->prime->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_buffer_append_fixed_mpi(extdata, session->key.kshare.dh_params.params[DH_Y],
|
|
Packit |
aea12f |
group->prime->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
cleanup:
|
|
Packit |
aea12f |
gnutls_free(tmp.data);
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Generates shared key and stores it in session->key.key
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
static int
|
|
Packit |
aea12f |
server_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *group,
|
|
Packit |
aea12f |
const uint8_t * data, size_t data_size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
const gnutls_ecc_curve_entry_st *curve;
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group->pk == GNUTLS_PK_EC) {
|
|
Packit |
aea12f |
gnutls_pk_params_st pub;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_pk_params_release(&session->key.kshare.ecdh_params);
|
|
Packit |
aea12f |
gnutls_pk_params_init(&session->key.kshare.ecdh_params);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
curve = _gnutls_ecc_curve_get_params(group->curve);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_pk_params_init(&pub;;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (curve->size*2+1 != data_size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate our key */
|
|
Packit |
aea12f |
ret = _gnutls_pk_generate_keys(curve->pk, curve->id, &session->key.kshare.ecdh_params, 1);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* read the public key */
|
|
Packit |
aea12f |
ret = _gnutls_ecc_ansi_x962_import(data, data_size,
|
|
Packit |
aea12f |
&pub.params[ECC_X],
|
|
Packit |
aea12f |
&pub.params[ECC_Y]);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.algo = group->pk;
|
|
Packit |
aea12f |
pub.curve = curve->id;
|
|
Packit |
aea12f |
pub.params_nr = 2;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate shared */
|
|
Packit |
aea12f |
ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdh_params, &pub;;
|
|
Packit |
aea12f |
gnutls_pk_params_release(&pub;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_ECDH_X25519) {
|
|
Packit |
aea12f |
gnutls_pk_params_st pub;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_pk_params_release(&session->key.kshare.ecdhx_params);
|
|
Packit |
aea12f |
gnutls_pk_params_init(&session->key.kshare.ecdhx_params);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
curve = _gnutls_ecc_curve_get_params(group->curve);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (curve->size != data_size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate our key */
|
|
Packit |
aea12f |
ret = _gnutls_pk_generate_keys(curve->pk, curve->id, &session->key.kshare.ecdhx_params, 1);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* read the public key and generate shared */
|
|
Packit |
aea12f |
gnutls_pk_params_init(&pub;;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.algo = group->pk;
|
|
Packit |
aea12f |
pub.curve = curve->id;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.raw_pub.data = (void*)data;
|
|
Packit |
aea12f |
pub.raw_pub.size = data_size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* We don't mask the MSB in the final byte as required
|
|
Packit |
aea12f |
* by RFC7748. This will be done internally by nettle 3.3 or later.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdhx_params, &pub;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_DH) {
|
|
Packit |
aea12f |
gnutls_pk_params_st pub;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* we need to initialize the group parameters first */
|
|
Packit |
aea12f |
gnutls_pk_params_release(&session->key.kshare.dh_params);
|
|
Packit |
aea12f |
gnutls_pk_params_init(&session->key.kshare.dh_params);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (data_size != group->prime->size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* set group params */
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_G],
|
|
Packit |
aea12f |
group->generator->data, group->generator->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_P],
|
|
Packit |
aea12f |
group->prime->data, group->prime->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_Q],
|
|
Packit |
aea12f |
group->q->data, group->q->size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
session->key.kshare.dh_params.algo = GNUTLS_PK_DH;
|
|
Packit |
aea12f |
session->key.kshare.dh_params.qbits = *group->q_bits;
|
|
Packit |
aea12f |
session->key.kshare.dh_params.params_nr = 3;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate our keys */
|
|
Packit |
aea12f |
ret = _gnutls_pk_generate_keys(group->pk, 0, &session->key.kshare.dh_params, 1);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* read the public key and generate shared */
|
|
Packit |
aea12f |
gnutls_pk_params_init(&pub;;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&pub.params[DH_Y],
|
|
Packit |
aea12f |
data, data_size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.algo = group->pk;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate shared key */
|
|
Packit |
aea12f |
ret = _gnutls_pk_derive_tls13(GNUTLS_PK_DH, &session->key.key, &session->key.kshare.dh_params, &pub;;
|
|
Packit |
aea12f |
_gnutls_mpi_release(&pub.params[DH_Y]);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_debug_log("EXT[%p]: server generated %s shared key\n", session, group->name);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Generates shared key and stores it in session->key.key
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
static int
|
|
Packit |
aea12f |
client_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *group,
|
|
Packit |
aea12f |
const uint8_t * data, size_t data_size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
const gnutls_ecc_curve_entry_st *curve;
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group->pk == GNUTLS_PK_EC) {
|
|
Packit |
aea12f |
gnutls_pk_params_st pub;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
curve = _gnutls_ecc_curve_get_params(group->curve);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_pk_params_init(&pub;;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (session->key.kshare.ecdh_params.algo != group->pk || session->key.kshare.ecdh_params.curve != curve->id)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (curve->size*2+1 != data_size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* read the server's public key */
|
|
Packit |
aea12f |
ret = _gnutls_ecc_ansi_x962_import(data, data_size,
|
|
Packit |
aea12f |
&pub.params[ECC_X],
|
|
Packit |
aea12f |
&pub.params[ECC_Y]);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.algo = group->pk;
|
|
Packit |
aea12f |
pub.curve = curve->id;
|
|
Packit |
aea12f |
pub.params_nr = 2;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate shared key */
|
|
Packit |
aea12f |
ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdh_params, &pub;;
|
|
Packit |
aea12f |
gnutls_pk_params_release(&pub;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_ECDH_X25519) {
|
|
Packit |
aea12f |
gnutls_pk_params_st pub;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
curve = _gnutls_ecc_curve_get_params(group->curve);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (session->key.kshare.ecdhx_params.algo != group->pk || session->key.kshare.ecdhx_params.curve != curve->id)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (curve->size != data_size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* read the public key and generate shared */
|
|
Packit |
aea12f |
gnutls_pk_params_init(&pub;;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.algo = group->pk;
|
|
Packit |
aea12f |
pub.curve = curve->id;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.raw_pub.data = (void*)data;
|
|
Packit |
aea12f |
pub.raw_pub.size = data_size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* We don't mask the MSB in the final byte as required
|
|
Packit |
aea12f |
* by RFC7748. This will be done internally by nettle 3.3 or later.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdhx_params, &pub;;
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else if (group->pk == GNUTLS_PK_DH) {
|
|
Packit |
aea12f |
gnutls_pk_params_st pub;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (session->key.kshare.dh_params.algo != group->pk || session->key.kshare.dh_params.dh_group != group->id)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (data_size != group->prime->size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* read the public key and generate shared */
|
|
Packit |
aea12f |
gnutls_pk_params_init(&pub;;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = _gnutls_mpi_init_scan_nz(&pub.params[DH_Y],
|
|
Packit |
aea12f |
data, data_size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
pub.algo = group->pk;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate shared key */
|
|
Packit |
aea12f |
ret = _gnutls_pk_derive_tls13(GNUTLS_PK_DH, &session->key.key, &session->key.kshare.dh_params, &pub;;
|
|
Packit |
aea12f |
_gnutls_mpi_release(&pub.params[DH_Y]);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_debug_log("EXT[%p]: client generated %s shared key\n", session, group->name);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static int
|
|
Packit |
aea12f |
key_share_recv_params(gnutls_session_t session,
|
|
Packit |
5407aa |
const uint8_t * data, size_t data_size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
5407aa |
size_t size;
|
|
Packit |
aea12f |
unsigned gid;
|
|
Packit |
aea12f |
const version_entry_st *ver;
|
|
Packit |
aea12f |
const gnutls_group_entry_st *group;
|
|
Packit |
aea12f |
unsigned used_share = 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (session->security_parameters.entity == GNUTLS_SERVER) {
|
|
Packit |
aea12f |
ver = get_version(session);
|
|
Packit |
aea12f |
if (ver == NULL || ver->key_shares == 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
DECR_LEN(data_size, 2);
|
|
Packit |
aea12f |
size = _gnutls_read_uint16(data);
|
|
Packit |
aea12f |
data += 2;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (data_size != size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* if we do PSK without DH ignore that share */
|
|
Packit |
aea12f |
if ((session->internals.hsk_flags & HSK_PSK_SELECTED) &&
|
|
Packit |
aea12f |
(session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK)) {
|
|
Packit |
aea12f |
reset_cand_groups(session);
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
while(data_size > 0) {
|
|
Packit |
aea12f |
DECR_LEN(data_size, 2);
|
|
Packit |
aea12f |
gid = _gnutls_read_uint16(data);
|
|
Packit |
aea12f |
data += 2;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
DECR_LEN(data_size, 2);
|
|
Packit |
aea12f |
size = _gnutls_read_uint16(data);
|
|
Packit |
aea12f |
data += 2;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
DECR_LEN(data_size, size);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* at this point we have already negotiated a group;
|
|
Packit |
aea12f |
* find the group's share. */
|
|
Packit |
aea12f |
group = _gnutls_tls_id_to_group(gid);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group != NULL)
|
|
Packit |
aea12f |
_gnutls_handshake_log("EXT[%p]: Received key share for %s\n", session, group->name);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group != NULL && group == session->internals.cand_group) {
|
|
Packit |
aea12f |
_gnutls_session_group_set(session, group);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = server_use_key_share(session, group, data, size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
used_share = 1;
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
data += size;
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* we utilize GNUTLS_E_NO_COMMON_KEY_SHARE for:
|
|
Packit |
aea12f |
* 1. signal for hello-retry-request in the handshake
|
|
Packit |
aea12f |
* layer during first client hello parsing (server side - here).
|
|
Packit |
aea12f |
* This does not result to error code being
|
|
Packit |
aea12f |
* propagated to app layer.
|
|
Packit |
aea12f |
* 2. Propagate to application error code that no
|
|
Packit |
aea12f |
* common key share was found after an HRR was
|
|
Packit |
aea12f |
* received (client side)
|
|
Packit |
aea12f |
* 3. Propagate to application error code that no
|
|
Packit |
aea12f |
* common key share was found after an HRR was
|
|
Packit |
aea12f |
* sent (server side).
|
|
Packit |
aea12f |
* In cases (2,3) the error is translated to illegal
|
|
Packit |
aea12f |
* parameter alert.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
if (used_share == 0) {
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
session->internals.hsk_flags |= HSK_KEY_SHARE_RECEIVED;
|
|
Packit |
aea12f |
} else { /* Client */
|
|
Packit |
aea12f |
ver = get_version(session);
|
|
Packit |
aea12f |
if (unlikely(ver == NULL || ver->key_shares == 0))
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) {
|
|
Packit |
aea12f |
if (unlikely(!(session->internals.hsk_flags & HSK_HRR_RECEIVED)))
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
DECR_LEN(data_size, 2);
|
|
Packit |
aea12f |
gid = _gnutls_read_uint16(data);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
group = _gnutls_tls_id_to_group(gid);
|
|
Packit |
aea12f |
if (group == NULL)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_handshake_log("EXT[%p]: HRR key share with %s\n", session, group->name);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* check if we support it */
|
|
Packit |
aea12f |
ret = _gnutls_session_supports_group(session, group->id);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
_gnutls_handshake_log("EXT[%p]: received share for %s which is disabled\n", session, group->name);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_session_group_set(session, group);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
/* else */
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
DECR_LEN(data_size, 2);
|
|
Packit |
aea12f |
gid = _gnutls_read_uint16(data);
|
|
Packit |
aea12f |
data += 2;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
DECR_LEN(data_size, 2);
|
|
Packit |
aea12f |
size = _gnutls_read_uint16(data);
|
|
Packit |
aea12f |
data+=2;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (data_size != size)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
group = _gnutls_tls_id_to_group(gid);
|
|
Packit |
aea12f |
if (group == NULL)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* check if we support it */
|
|
Packit |
aea12f |
ret = _gnutls_session_supports_group(session, group->id);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
_gnutls_handshake_log("EXT[%p]: received share for %s which is disabled\n", session, group->name);
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_session_group_set(session, group);
|
|
Packit |
aea12f |
session->internals.hsk_flags |= HSK_KEY_SHARE_RECEIVED;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = client_use_key_share(session, group, data, size);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
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 |
key_share_send_params(gnutls_session_t session,
|
|
Packit |
aea12f |
gnutls_buffer_st * extdata)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
unsigned i;
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
unsigned char *lengthp;
|
|
Packit |
aea12f |
unsigned int cur_length;
|
|
Packit |
aea12f |
unsigned int generated = 0;
|
|
Packit |
aea12f |
const gnutls_group_entry_st *group;
|
|
Packit |
aea12f |
const version_entry_st *ver;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* this extension is only being sent on client side */
|
|
Packit |
aea12f |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit |
aea12f |
ver = _gnutls_version_max(session);
|
|
Packit |
aea12f |
if (unlikely(ver == NULL || ver->key_shares == 0))
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (!have_creds_for_tls13(session))
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* write the total length later */
|
|
Packit |
aea12f |
lengthp = &extdata->data[extdata->length];
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_prefix(extdata, 16, 0);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
cur_length = extdata->length;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (session->internals.hsk_flags & HSK_HRR_RECEIVED) { /* we know the group */
|
|
Packit |
aea12f |
group = get_group(session);
|
|
Packit |
aea12f |
if (unlikely(group == NULL))
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = client_gen_key_share(session, group, extdata);
|
|
Packit |
aea12f |
if (ret == GNUTLS_E_INT_RET_0)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
gnutls_pk_algorithm_t selected_groups[3];
|
|
Packit |
aea12f |
unsigned max_groups = 2; /* GNUTLS_KEY_SHARE_TOP2 */
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (session->internals.flags & GNUTLS_KEY_SHARE_TOP)
|
|
Packit |
aea12f |
max_groups = 1;
|
|
Packit |
aea12f |
else if (session->internals.flags & GNUTLS_KEY_SHARE_TOP3)
|
|
Packit |
aea12f |
max_groups = 3;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
assert(max_groups <= sizeof(selected_groups)/sizeof(selected_groups[0]));
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate key shares for out top-(max_groups) groups
|
|
Packit |
aea12f |
* if they are of different PK type. */
|
|
Packit |
aea12f |
for (i = 0; i < session->internals.priorities->groups.size; i++) {
|
|
Packit |
aea12f |
group = session->internals.priorities->groups.entry[i];
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (generated == 1 && group->pk == selected_groups[0])
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
else if (generated == 2 && (group->pk == selected_groups[1] || group->pk == selected_groups[0]))
|
|
Packit |
aea12f |
continue;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
selected_groups[generated] = group->pk;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = client_gen_key_share(session, group, extdata);
|
|
Packit |
aea12f |
if (ret == GNUTLS_E_INT_RET_0)
|
|
Packit |
aea12f |
continue; /* no key share for this algorithm */
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
generated++;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (generated >= max_groups)
|
|
Packit |
aea12f |
break;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* copy actual length */
|
|
Packit |
aea12f |
_gnutls_write_uint16(extdata->length - cur_length, lengthp);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
} else { /* server */
|
|
Packit |
aea12f |
ver = get_version(session);
|
|
Packit |
aea12f |
if (unlikely(ver == NULL || ver->key_shares == 0))
|
|
Packit |
aea12f |
return gnutls_assert_val(0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) {
|
|
Packit |
aea12f |
group = session->internals.cand_group;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (group == NULL)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_session_group_set(session, group);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
_gnutls_handshake_log("EXT[%p]: requesting retry with group %s\n", session, group->name);
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_buffer_append_prefix(extdata, 16, group->tls_id);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
/* if we are negotiating PSK without DH, do not send a key share */
|
|
Packit |
aea12f |
if ((session->internals.hsk_flags & HSK_PSK_SELECTED) &&
|
|
Packit |
aea12f |
(session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK))
|
|
Packit |
aea12f |
return gnutls_assert_val(0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
group = get_group(session);
|
|
Packit |
aea12f |
if (unlikely(group == NULL))
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = server_gen_key_share(session, group, extdata);
|
|
Packit |
aea12f |
if (ret < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(ret);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
session->internals.hsk_flags |= HSK_KEY_SHARE_SENT;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|