Blame lib/ext/pre_shared_key.c

Packit aea12f
/*
Packit aea12f
 * Copyright (C) 2017-2018 Free Software Foundation, Inc.
Packit aea12f
 * Copyright (C) 2018 Red Hat, Inc.
Packit aea12f
 *
Packit aea12f
 * Author: Ander Juaristi, 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
#include "gnutls_int.h"
Packit aea12f
#include "auth/psk.h"
Packit aea12f
#include "handshake.h"
Packit aea12f
#include "kx.h"
Packit aea12f
#include "secrets.h"
Packit aea12f
#include "tls13/anti_replay.h"
Packit aea12f
#include "tls13/psk_ext_parser.h"
Packit aea12f
#include "tls13/finished.h"
Packit aea12f
#include "tls13/session_ticket.h"
Packit aea12f
#include "auth/psk_passwd.h"
Packit aea12f
#include <ext/session_ticket.h>
Packit aea12f
#include <ext/pre_shared_key.h>
Packit aea12f
#include <assert.h>
Packit aea12f
Packit aea12f
static int
Packit aea12f
compute_psk_from_ticket(const tls13_ticket_st *ticket, gnutls_datum_t *key)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (unlikely(ticket->prf == NULL || ticket->prf->output_size == 0))
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
Packit aea12f
	key->data = gnutls_malloc(ticket->prf->output_size);
Packit aea12f
	if (!key->data) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		return GNUTLS_E_MEMORY_ERROR;
Packit aea12f
	}
Packit aea12f
	key->size = ticket->prf->output_size;
Packit aea12f
Packit aea12f
	ret = _tls13_expand_secret2(ticket->prf,
Packit aea12f
				    RESUMPTION_LABEL, sizeof(RESUMPTION_LABEL)-1,
Packit aea12f
				    ticket->nonce, ticket->nonce_size,
Packit aea12f
				    ticket->resumption_master_secret,
Packit aea12f
				    key->size,
Packit aea12f
				    key->data);
Packit aea12f
	if (ret < 0)
Packit aea12f
		gnutls_assert();
Packit aea12f
Packit aea12f
	return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
static int
Packit aea12f
compute_binder_key(const mac_entry_st *prf,
Packit aea12f
		   const uint8_t *key, size_t keylen,
Packit aea12f
		   bool resuming,
Packit aea12f
		   void *out)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
	const char ext_label[] = EXT_BINDER_LABEL;
Packit aea12f
	const size_t ext_label_len = sizeof(ext_label) - 1;
Packit aea12f
	const char res_label[] = RES_BINDER_LABEL;
Packit aea12f
	const size_t res_label_len = sizeof(res_label) - 1;
Packit aea12f
	const char *label = resuming ? res_label : ext_label;
Packit aea12f
	size_t label_len = resuming ? res_label_len : ext_label_len;
Packit aea12f
	uint8_t tmp_key[MAX_HASH_SIZE];
Packit aea12f
Packit aea12f
	/* Compute HKDF-Extract(0, psk) */
Packit aea12f
	ret = _tls13_init_secret2(prf, key, keylen, tmp_key);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return ret;
Packit aea12f
Packit aea12f
	/* Compute Derive-Secret(secret, label, transcript_hash) */
Packit aea12f
	ret = _tls13_derive_secret2(prf, label, label_len,
Packit aea12f
				    NULL, 0, tmp_key, out);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return ret;
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
static int
Packit aea12f
compute_psk_binder(gnutls_session_t session,
Packit aea12f
		   const mac_entry_st *prf, unsigned binders_length,
Packit aea12f
		   int exts_length, int ext_offset,
Packit aea12f
		   const gnutls_datum_t *psk, const gnutls_datum_t *client_hello,
Packit aea12f
		   bool resuming, void *out)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
	unsigned client_hello_pos, extensions_len_pos;
Packit aea12f
	gnutls_buffer_st handshake_buf;
Packit aea12f
	uint8_t binder_key[MAX_HASH_SIZE];
Packit aea12f
Packit aea12f
	_gnutls_buffer_init(&handshake_buf);
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
Packit aea12f
		if (session->internals.hsk_flags & HSK_HRR_RECEIVED) {
Packit aea12f
			ret = gnutls_buffer_append_data(&handshake_buf,
Packit aea12f
							(const void *) session->internals.handshake_hash_buffer.data,
Packit aea12f
							session->internals.handshake_hash_buffer.length);
Packit aea12f
			if (ret < 0) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				goto error;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
Packit aea12f
		client_hello_pos = handshake_buf.length;
Packit aea12f
		ret = gnutls_buffer_append_data(&handshake_buf, client_hello->data,
Packit aea12f
						client_hello->size);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto error;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* This is a ClientHello message */
Packit aea12f
		handshake_buf.data[client_hello_pos] = GNUTLS_HANDSHAKE_CLIENT_HELLO;
Packit aea12f
Packit aea12f
		/* At this point we have not yet added the binders to the ClientHello,
Packit aea12f
		 * but we have to overwrite the size field, pretending as if binders
Packit aea12f
		 * of the correct length were present.
Packit aea12f
		 */
Packit aea12f
		_gnutls_write_uint24(handshake_buf.length - client_hello_pos + binders_length - 2, &handshake_buf.data[client_hello_pos + 1]);
Packit aea12f
		_gnutls_write_uint16(handshake_buf.length - client_hello_pos + binders_length - ext_offset,
Packit aea12f
				     &handshake_buf.data[client_hello_pos + ext_offset]);
Packit aea12f
		extensions_len_pos = handshake_buf.length - client_hello_pos - exts_length - 2;
Packit aea12f
		_gnutls_write_uint16(exts_length + binders_length + 2,
Packit aea12f
				     &handshake_buf.data[client_hello_pos + extensions_len_pos]);
Packit aea12f
	} else {
Packit aea12f
		if (session->internals.hsk_flags & HSK_HRR_SENT) {
Packit aea12f
			if (unlikely(session->internals.handshake_hash_buffer.length <= client_hello->size)) {
Packit aea12f
				ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
Packit aea12f
				goto error;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			ret = gnutls_buffer_append_data(&handshake_buf,
Packit aea12f
							session->internals.handshake_hash_buffer.data,
Packit aea12f
							session->internals.handshake_hash_buffer.length - client_hello->size);
Packit aea12f
			if (ret < 0) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				goto error;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
Packit aea12f
		if (unlikely(client_hello->size <= binders_length)) {
Packit aea12f
			ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
Packit aea12f
			goto error;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		ret = gnutls_buffer_append_data(&handshake_buf,
Packit aea12f
						(const void *) client_hello->data,
Packit aea12f
						client_hello->size - binders_length);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto error;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	ret = compute_binder_key(prf,
Packit aea12f
				 psk->data, psk->size, resuming,
Packit aea12f
				 binder_key);
Packit aea12f
	if (ret < 0) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		goto error;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	ret = _gnutls13_compute_finished(prf, binder_key,
Packit aea12f
					 &handshake_buf,
Packit aea12f
					 out);
Packit aea12f
	if (ret < 0) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		goto error;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	ret = 0;
Packit aea12f
error:
Packit aea12f
	_gnutls_buffer_clear(&handshake_buf);
Packit aea12f
	return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
static int
Packit aea12f
generate_early_secrets(gnutls_session_t session,
Packit aea12f
		       const mac_entry_st *prf)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	ret = _tls13_derive_secret2(prf, EARLY_TRAFFIC_LABEL, sizeof(EARLY_TRAFFIC_LABEL)-1,
Packit aea12f
				    session->internals.handshake_hash_buffer.data,
Packit aea12f
				    session->internals.handshake_hash_buffer_client_hello_len,
Packit aea12f
				    session->key.proto.tls13.temp_secret,
Packit aea12f
				    session->key.proto.tls13.e_ckey);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit Service 991b93
	ret = _gnutls_call_keylog_func(session, "CLIENT_EARLY_TRAFFIC_SECRET",
Packit Service 991b93
				       session->key.proto.tls13.e_ckey,
Packit Service 991b93
				       prf->output_size);
Packit Service 991b93
	if (ret < 0)
Packit Service 991b93
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	ret = _tls13_derive_secret2(prf, EARLY_EXPORTER_MASTER_LABEL, sizeof(EARLY_EXPORTER_MASTER_LABEL)-1,
Packit aea12f
				    session->internals.handshake_hash_buffer.data,
Packit aea12f
				    session->internals.handshake_hash_buffer_client_hello_len,
Packit aea12f
				    session->key.proto.tls13.temp_secret,
Packit aea12f
				    session->key.proto.tls13.ap_expkey);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit Service 991b93
	ret = _gnutls_call_keylog_func(session, "EARLY_EXPORTER_SECRET",
Packit Service 991b93
				       session->key.proto.tls13.ap_expkey,
Packit Service 991b93
				       prf->output_size);
Packit Service 991b93
	if (ret < 0)
Packit Service 991b93
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* Calculate TLS 1.3 Early Secret and the derived secrets from the
Packit aea12f
 * selected PSK. */
Packit aea12f
int
Packit aea12f
_gnutls_generate_early_secrets_for_psk(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	const uint8_t *psk;
Packit aea12f
	size_t psk_size;
Packit aea12f
	const mac_entry_st *prf;
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	psk = session->key.binders[0].psk.data;
Packit aea12f
	psk_size = session->key.binders[0].psk.size;
Packit aea12f
	prf = session->key.binders[0].prf;
Packit aea12f
Packit aea12f
	if (unlikely(psk_size == 0))
Packit aea12f
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
Packit aea12f
Packit aea12f
	ret = _tls13_init_secret2(prf, psk, psk_size,
Packit aea12f
				  session->key.proto.tls13.temp_secret);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	session->key.proto.tls13.temp_secret_size = prf->output_size;
Packit aea12f
Packit aea12f
	ret = generate_early_secrets(session, session->key.binders[0].prf);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
}
Packit aea12f
Packit aea12f
static int
Packit aea12f
client_send_params(gnutls_session_t session,
Packit aea12f
		   gnutls_buffer_t extdata,
Packit aea12f
		   const gnutls_psk_client_credentials_t cred)
Packit aea12f
{
Packit aea12f
	int ret, ext_offset = 0;
Packit aea12f
	uint8_t binder_value[MAX_HASH_SIZE];
Packit aea12f
	size_t spos;
Packit aea12f
	gnutls_datum_t username = {NULL, 0};
Packit aea12f
	gnutls_datum_t user_key = {NULL, 0}, rkey = {NULL, 0};
Packit aea12f
	gnutls_datum_t client_hello;
Packit aea12f
	unsigned next_idx;
Packit aea12f
	const mac_entry_st *prf_res = NULL;
Packit aea12f
	const mac_entry_st *prf_psk = NULL;
Packit aea12f
	struct timespec cur_time;
Packit aea12f
	uint32_t ticket_age, ob_ticket_age;
Packit aea12f
	int free_username = 0;
Packit aea12f
	psk_auth_info_t info = NULL;
Packit aea12f
	unsigned psk_id_len = 0;
Packit aea12f
	unsigned binders_len, binders_pos;
Packit aea12f
Packit aea12f
	if (((session->internals.flags & GNUTLS_NO_TICKETS) ||
Packit aea12f
	    session->internals.tls13_ticket.ticket.data == NULL) &&
Packit aea12f
	    (!cred || !_gnutls_have_psk_credentials(cred, session))) {
Packit aea12f
Packit aea12f
		return 0;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	binders_len = 0;
Packit aea12f
Packit aea12f
	/* placeholder to be filled later */
Packit aea12f
	spos = extdata->length;
Packit aea12f
	ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	/* First, let's see if we have a session ticket to send */
Packit aea12f
	if (!(session->internals.flags & GNUTLS_NO_TICKETS) &&
Packit aea12f
	    session->internals.tls13_ticket.ticket.data != NULL) {
Packit aea12f
		/* We found a session ticket */
Packit aea12f
		if (unlikely(session->internals.tls13_ticket.prf == NULL)) {
Packit aea12f
			_gnutls13_session_ticket_unset(session);
Packit aea12f
			ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		prf_res = session->internals.tls13_ticket.prf;
Packit aea12f
Packit aea12f
		gnutls_gettime(&cur_time);
Packit aea12f
		if (unlikely(_gnutls_timespec_cmp(&cur_time,
Packit aea12f
						  &session->internals.
Packit aea12f
						  tls13_ticket.
Packit aea12f
						  arrival_time) < 0)) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			_gnutls13_session_ticket_unset(session);
Packit aea12f
			goto ignore_ticket;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* Check whether the ticket is stale */
Packit aea12f
		ticket_age = timespec_sub_ms(&cur_time,
Packit aea12f
					     &session->internals.tls13_ticket.
Packit aea12f
					     arrival_time);
Packit aea12f
		if (ticket_age / 1000 > session->internals.tls13_ticket.lifetime) {
Packit aea12f
			_gnutls13_session_ticket_unset(session);
Packit aea12f
			goto ignore_ticket;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		ret = compute_psk_from_ticket(&session->internals.tls13_ticket, &rkey);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			_gnutls13_session_ticket_unset(session);
Packit aea12f
			goto ignore_ticket;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */
Packit aea12f
		ob_ticket_age = ticket_age + session->internals.tls13_ticket.age_add;
Packit aea12f
Packit aea12f
		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
Packit aea12f
							     session->internals.tls13_ticket.ticket.data,
Packit aea12f
							     session->internals.tls13_ticket.ticket.size)) < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* Now append the obfuscated ticket age */
Packit aea12f
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, ob_ticket_age)) < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		psk_id_len += 6 + session->internals.tls13_ticket.ticket.size;
Packit aea12f
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_res);
Packit aea12f
	}
Packit aea12f
Packit aea12f
 ignore_ticket:
Packit aea12f
	if (cred && _gnutls_have_psk_credentials(cred, session)) {
Packit aea12f
		gnutls_datum_t tkey;
Packit aea12f
Packit aea12f
		if (cred->binder_algo == NULL) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		prf_psk = cred->binder_algo;
Packit aea12f
Packit aea12f
		ret = _gnutls_find_psk_key(session, cred, &username, &tkey, &free_username);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		if (username.size == 0 || username.size > UINT16_MAX) {
Packit aea12f
			ret = gnutls_assert_val(GNUTLS_E_INVALID_PASSWORD);
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		if (!free_username) {
Packit aea12f
			/* we need to copy the key */
Packit aea12f
			ret = _gnutls_set_datum(&user_key, tkey.data, tkey.size);
Packit aea12f
			if (ret < 0) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				goto cleanup;
Packit aea12f
			}
Packit aea12f
		} else {
Packit aea12f
			user_key.data = tkey.data;
Packit aea12f
			user_key.size = tkey.size;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
Packit aea12f
		assert(info != NULL);
Packit aea12f
Packit Service 991b93
		_gnutls_copy_psk_username(info, &username);
Packit aea12f
Packit aea12f
		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
Packit aea12f
							     username.data,
Packit aea12f
							     username.size)) < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* Now append the obfuscated ticket age */
Packit aea12f
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, 0)) < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		psk_id_len += 6 + username.size;
Packit aea12f
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_psk);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* if no tickets or identities to be sent */
Packit aea12f
	if (psk_id_len == 0) {
Packit aea12f
		/* reset extensions buffer */
Packit aea12f
		extdata->length = spos;
Packit aea12f
		return 0;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	_gnutls_write_uint16(psk_id_len, &extdata->data[spos]);
Packit aea12f
Packit aea12f
	binders_pos = extdata->length-spos;
Packit aea12f
	ext_offset = _gnutls_ext_get_extensions_offset(session);
Packit aea12f
Packit aea12f
	/* Compute the binders. extdata->data points to the start
Packit aea12f
	 * of this client hello. */
Packit aea12f
	assert(extdata->length >= sizeof(mbuffer_st));
Packit aea12f
	assert(ext_offset >= (ssize_t)sizeof(mbuffer_st));
Packit aea12f
	ext_offset -= sizeof(mbuffer_st);
Packit aea12f
	client_hello.data = extdata->data+sizeof(mbuffer_st);
Packit aea12f
	client_hello.size = extdata->length-sizeof(mbuffer_st);
Packit aea12f
Packit aea12f
	next_idx = 0;
Packit aea12f
Packit aea12f
	ret = _gnutls_buffer_append_prefix(extdata, 16, binders_len);
Packit aea12f
	if (ret < 0) {
Packit aea12f
		gnutls_assert_val(ret);
Packit aea12f
		goto cleanup;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (prf_res && rkey.size > 0) {
Packit aea12f
		ret = compute_psk_binder(session, prf_res,
Packit aea12f
					 binders_len, binders_pos,
Packit aea12f
					 ext_offset, &rkey, &client_hello, 1,
Packit aea12f
					 binder_value);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* Associate the selected pre-shared key with the session */
Packit aea12f
		gnutls_free(session->key.binders[next_idx].psk.data);
Packit aea12f
		session->key.binders[next_idx].psk.data = rkey.data;
Packit aea12f
		session->key.binders[next_idx].psk.size = rkey.size;
Packit aea12f
		rkey.data = NULL;
Packit aea12f
Packit aea12f
		session->key.binders[next_idx].prf = prf_res;
Packit aea12f
		session->key.binders[next_idx].resumption = 1;
Packit aea12f
		session->key.binders[next_idx].idx = next_idx;
Packit aea12f
Packit aea12f
		_gnutls_handshake_log("EXT[%p]: sent PSK resumption identity (%d)\n", session, next_idx);
Packit aea12f
Packit aea12f
		next_idx++;
Packit aea12f
Packit aea12f
		/* Add the binder */
Packit aea12f
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_res->output_size);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (prf_psk && user_key.size > 0 && info) {
Packit aea12f
		ret = compute_psk_binder(session, prf_psk,
Packit aea12f
					 binders_len, binders_pos,
Packit aea12f
					 ext_offset, &user_key, &client_hello, 0,
Packit aea12f
					 binder_value);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* Associate the selected pre-shared key with the session */
Packit aea12f
		gnutls_free(session->key.binders[next_idx].psk.data);
Packit aea12f
		session->key.binders[next_idx].psk.data = user_key.data;
Packit aea12f
		session->key.binders[next_idx].psk.size = user_key.size;
Packit aea12f
		user_key.data = NULL;
Packit aea12f
Packit aea12f
		session->key.binders[next_idx].prf = prf_psk;
Packit aea12f
		session->key.binders[next_idx].resumption = 0;
Packit aea12f
		session->key.binders[next_idx].idx = next_idx;
Packit aea12f
Packit aea12f
		_gnutls_handshake_log("EXT[%p]: sent PSK identity '%s' (%d)\n", session, info->username, next_idx);
Packit aea12f
Packit aea12f
		next_idx++;
Packit aea12f
Packit aea12f
		/* Add the binder */
Packit aea12f
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_psk->output_size);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto cleanup;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	ret = 0;
Packit aea12f
Packit aea12f
cleanup:
Packit aea12f
	if (free_username)
Packit aea12f
		_gnutls_free_datum(&username);
Packit aea12f
Packit aea12f
	_gnutls_free_temp_key_datum(&user_key);
Packit aea12f
	_gnutls_free_temp_key_datum(&rkey);
Packit aea12f
Packit aea12f
	return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
static int
Packit aea12f
server_send_params(gnutls_session_t session, gnutls_buffer_t extdata)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (!(session->internals.hsk_flags & HSK_PSK_SELECTED))
Packit aea12f
		return 0;
Packit aea12f
Packit aea12f
	ret = _gnutls_buffer_append_prefix(extdata, 16,
Packit aea12f
					   session->key.binders[0].idx);
Packit aea12f
	if (ret < 0)
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
	return 2;
Packit aea12f
}
Packit aea12f
Packit aea12f
static int server_recv_params(gnutls_session_t session,
Packit aea12f
			      const unsigned char *data, size_t len,
Packit aea12f
			      const gnutls_psk_server_credentials_t pskcred)
Packit aea12f
{
Packit aea12f
	int ret;
Packit aea12f
	const mac_entry_st *prf;
Packit aea12f
	gnutls_datum_t full_client_hello;
Packit aea12f
	uint8_t binder_value[MAX_HASH_SIZE];
Packit aea12f
	uint16_t psk_index, i;
Packit aea12f
	gnutls_datum_t binder_recvd = { NULL, 0 };
Packit aea12f
	gnutls_datum_t key = {NULL, 0};
Packit aea12f
	psk_ext_parser_st psk_parser;
Packit aea12f
	psk_ext_iter_st psk_iter;
Packit aea12f
	struct psk_st psk;
Packit aea12f
	psk_auth_info_t info;
Packit aea12f
	tls13_ticket_st ticket_data;
Packit aea12f
	/* These values should be set properly when session ticket is accepted. */
Packit aea12f
	uint32_t ticket_age = UINT32_MAX;
Packit aea12f
	struct timespec ticket_creation_time = { 0, 0 };
Packit aea12f
	bool resuming;
Packit aea12f
Packit aea12f
	ret = _gnutls13_psk_ext_parser_init(&psk_parser, data, len);
Packit aea12f
	if (ret < 0) {
Packit aea12f
		/* No PSKs advertised by client */
Packit aea12f
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
Packit aea12f
			return 0;
Packit aea12f
		return gnutls_assert_val(ret);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	_gnutls13_psk_ext_iter_init(&psk_iter, &psk_parser);
Packit aea12f
	for (psk_index = 0; ; psk_index++) {
Packit aea12f
		ret = _gnutls13_psk_ext_iter_next_identity(&psk_iter, &psk;;
Packit aea12f
		if (ret < 0) {
Packit aea12f
			/* We couldn't find any usable PSK */
Packit aea12f
			if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
Packit aea12f
				return 0;
Packit aea12f
			return gnutls_assert_val(ret);
Packit aea12f
		}
Packit aea12f
Packit aea12f
		/* This will unpack the session ticket if it is well
Packit aea12f
		 * formed and has the expected name */
Packit aea12f
		if (!(session->internals.flags & GNUTLS_NO_TICKETS) &&
Packit aea12f
		    (ret = _gnutls13_unpack_session_ticket(session, &psk.identity, &ticket_data)) == 0) {
Packit aea12f
			prf = ticket_data.prf;
Packit aea12f
Packit aea12f
			session->internals.resumption_requested = 1;
Packit aea12f
Packit aea12f
			/* Check whether ticket is stale or not */
Packit aea12f
			ticket_age = psk.ob_ticket_age - ticket_data.age_add;
Packit aea12f
			if (ticket_age / 1000 > ticket_data.lifetime) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				tls13_ticket_deinit(&ticket_data);
Packit aea12f
				continue;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			ret = compute_psk_from_ticket(&ticket_data, &key);
Packit aea12f
			if (ret < 0) {
Packit aea12f
				gnutls_assert();
Packit aea12f
				tls13_ticket_deinit(&ticket_data);
Packit aea12f
				continue;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			memcpy(&ticket_creation_time,
Packit aea12f
			       &ticket_data.creation_time,
Packit aea12f
			       sizeof(struct timespec));
Packit aea12f
Packit aea12f
			tls13_ticket_deinit(&ticket_data);
Packit aea12f
Packit aea12f
			resuming = 1;
Packit aea12f
			break;
Packit aea12f
		} else if (pskcred &&
Packit aea12f
			   psk.ob_ticket_age == 0 &&
Packit aea12f
			   psk.identity.size > 0 && psk.identity.size <= MAX_USERNAME_SIZE) {
Packit aea12f
			prf = pskcred->binder_algo;
Packit aea12f
Packit aea12f
			/* this fails only on configuration errors; as such we always
Packit aea12f
			 * return its error code in that case */
Packit Service 991b93
			ret = _gnutls_psk_pwd_find_entry(session, (char *) psk.identity.data, psk.identity.size, &key);
Packit aea12f
			if (ret < 0)
Packit aea12f
				return gnutls_assert_val(ret);
Packit aea12f
Packit aea12f
			resuming = 0;
Packit aea12f
			break;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	_gnutls13_psk_ext_iter_init(&psk_iter, &psk_parser);
Packit aea12f
	for (i = 0; i <= psk_index; i++) {
Packit aea12f
		ret = _gnutls13_psk_ext_iter_next_binder(&psk_iter, &binder_recvd);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			/* We couldn't extract binder */
Packit aea12f
			if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
Packit aea12f
				ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
Packit aea12f
			goto fail;
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* Get full ClientHello */
Packit aea12f
	if (!_gnutls_ext_get_full_client_hello(session, &full_client_hello)) {
Packit aea12f
		ret = GNUTLS_E_INTERNAL_ERROR;
Packit aea12f
		gnutls_assert();
Packit aea12f
		goto fail;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* Compute the binder value for this PSK */
Packit aea12f
	ret = compute_psk_binder(session, prf, psk_parser.binders_len+2, 0, 0,
Packit aea12f
				 &key, &full_client_hello, resuming,
Packit aea12f
				 binder_value);
Packit aea12f
	if (ret < 0) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		goto fail;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (_gnutls_mac_get_algo_len(prf) != binder_recvd.size ||
Packit Service 6bac9f
	    gnutls_memcmp(binder_value, binder_recvd.data, binder_recvd.size)) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
Packit aea12f
		goto fail;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	if (session->internals.hsk_flags & HSK_PSK_KE_MODE_DHE_PSK)
Packit aea12f
		_gnutls_handshake_log("EXT[%p]: selected DHE-PSK mode\n", session);
Packit aea12f
	else {
Packit aea12f
		reset_cand_groups(session);
Packit aea12f
		_gnutls_handshake_log("EXT[%p]: selected PSK mode\n", session);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	/* save the username in psk_auth_info to make it available
Packit aea12f
	 * using gnutls_psk_server_get_username() */
Packit aea12f
	if (!resuming) {
Packit aea12f
		assert(psk.identity.size < sizeof(info->username));
Packit aea12f
Packit aea12f
		ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
Packit aea12f
		if (ret < 0) {
Packit aea12f
			gnutls_assert();
Packit aea12f
			goto fail;
Packit aea12f
		}
Packit aea12f
Packit aea12f
		info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
Packit aea12f
		assert(info != NULL);
Packit aea12f
Packit Service 991b93
		_gnutls_copy_psk_username(info, &psk.identity);
Packit aea12f
		_gnutls_handshake_log("EXT[%p]: selected PSK identity: %s (%d)\n", session, info->username, psk_index);
Packit aea12f
	} else {
Packit aea12f
		if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
Packit aea12f
			if (session->internals.anti_replay) {
Packit aea12f
				ret = _gnutls_anti_replay_check(session->internals.anti_replay,
Packit aea12f
								ticket_age,
Packit aea12f
								&ticket_creation_time,
Packit aea12f
								&binder_recvd);
Packit aea12f
				if (ret < 0) {
Packit aea12f
					session->internals.hsk_flags &= ~HSK_EARLY_DATA_ACCEPTED;
Packit aea12f
					_gnutls_handshake_log("EXT[%p]: replay detected; rejecting early data\n",
Packit aea12f
						      session);
Packit aea12f
				}
Packit aea12f
			} else {
Packit aea12f
				_gnutls_handshake_log("EXT[%p]: anti-replay is not enabled; rejecting early data\n",
Packit aea12f
						      session);
Packit aea12f
				session->internals.hsk_flags &= ~HSK_EARLY_DATA_ACCEPTED;
Packit aea12f
			}
Packit aea12f
		}
Packit aea12f
Packit aea12f
		session->internals.resumed = RESUME_TRUE;
Packit aea12f
		_gnutls_handshake_log("EXT[%p]: selected resumption PSK identity (%d)\n", session, psk_index);
Packit aea12f
	}
Packit aea12f
Packit aea12f
	session->internals.hsk_flags |= HSK_PSK_SELECTED;
Packit aea12f
Packit aea12f
	/* Reference the selected pre-shared key */
Packit aea12f
	session->key.binders[0].psk.data = key.data;
Packit aea12f
	session->key.binders[0].psk.size = key.size;
Packit aea12f
Packit aea12f
	session->key.binders[0].idx = psk_index;
Packit aea12f
	session->key.binders[0].prf = prf;
Packit aea12f
	session->key.binders[0].resumption = resuming;
Packit aea12f
Packit aea12f
	ret = _gnutls_generate_early_secrets_for_psk(session);
Packit aea12f
	if (ret < 0) {
Packit aea12f
		gnutls_assert();
Packit aea12f
		goto fail;
Packit aea12f
	}
Packit aea12f
Packit aea12f
	return 0;
Packit aea12f
Packit aea12f
 fail:
Packit aea12f
	gnutls_free(key.data);
Packit aea12f
	return ret;
Packit aea12f
}
Packit aea12f
Packit aea12f
/*
Packit aea12f
 * Return values for this function:
Packit aea12f
 *  -  0 : Not applicable.
Packit aea12f
 *  - >0 : Ok. Return size of extension data.
Packit aea12f
 *  - GNUTLS_E_INT_RET_0 : Size of extension data is zero.
Packit aea12f
 *  - <0 : There's been an error.
Packit aea12f
 *
Packit aea12f
 * In the client, generates the PskIdentity and PskBinderEntry messages.
Packit aea12f
 *
Packit aea12f
 *      PskIdentity identities<7..2^16-1>;
Packit aea12f
 *      PskBinderEntry binders<33..2^16-1>;
Packit aea12f
 *
Packit aea12f
 *      struct {
Packit aea12f
 *          opaque identity<1..2^16-1>;
Packit aea12f
 *          uint32 obfuscated_ticket_age;
Packit aea12f
 *      } PskIdentity;
Packit aea12f
 *
Packit aea12f
 *      opaque PskBinderEntry<32..255>;
Packit aea12f
 *
Packit aea12f
 * The server sends the selected identity, which is a zero-based index
Packit aea12f
 * of the PSKs offered by the client:
Packit aea12f
 *
Packit aea12f
 *      struct {
Packit aea12f
 *          uint16 selected_identity;
Packit aea12f
 *      } PreSharedKeyExtension;
Packit aea12f
 */
Packit aea12f
static int _gnutls_psk_send_params(gnutls_session_t session,
Packit aea12f
				   gnutls_buffer_t extdata)
Packit aea12f
{
Packit aea12f
	gnutls_psk_client_credentials_t cred = NULL;
Packit aea12f
	const version_entry_st *vers;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
Packit aea12f
		vers = _gnutls_version_max(session);
Packit aea12f
Packit aea12f
		if (!vers || !vers->tls13_sem)
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_SENT) {
Packit aea12f
			cred = (gnutls_psk_client_credentials_t)
Packit aea12f
					_gnutls_get_cred(session, GNUTLS_CRD_PSK);
Packit aea12f
		}
Packit aea12f
Packit aea12f
		if ((session->internals.flags & GNUTLS_NO_TICKETS) && !session->internals.priorities->have_psk)
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		return client_send_params(session, extdata, cred);
Packit aea12f
	} else {
Packit aea12f
		vers = get_version(session);
Packit aea12f
Packit aea12f
		if (!vers || !vers->tls13_sem)
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		if ((session->internals.flags & GNUTLS_NO_TICKETS) && !session->internals.priorities->have_psk)
Packit aea12f
			return 0;
Packit aea12f
Packit aea12f
		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED)
Packit aea12f
			return server_send_params(session, extdata);
Packit aea12f
		else
Packit aea12f
			return 0;
Packit aea12f
	}
Packit aea12f
}
Packit aea12f
Packit aea12f
static void swap_binders(gnutls_session_t session)
Packit aea12f
{
Packit aea12f
	struct binder_data_st tmp;
Packit aea12f
Packit aea12f
	memcpy(&tmp, &session->key.binders[0], sizeof(struct binder_data_st));
Packit aea12f
	memcpy(&session->key.binders[0], &session->key.binders[1], sizeof(struct binder_data_st));
Packit aea12f
	memcpy(&session->key.binders[1], &tmp, sizeof(struct binder_data_st));
Packit aea12f
}
Packit aea12f
Packit aea12f
/*
Packit aea12f
 * Return values for this function:
Packit aea12f
 *  -  0 : Not applicable.
Packit aea12f
 *  - >0 : Ok. Return size of extension data.
Packit aea12f
 *  - <0 : There's been an error.
Packit aea12f
 */
Packit aea12f
static int _gnutls_psk_recv_params(gnutls_session_t session,
Packit aea12f
				   const unsigned char *data, size_t len)
Packit aea12f
{
Packit aea12f
	unsigned i;
Packit aea12f
	gnutls_psk_server_credentials_t pskcred;
Packit aea12f
	const version_entry_st *vers = get_version(session);
Packit aea12f
	int ret;
Packit aea12f
Packit aea12f
	if (!vers || !vers->tls13_sem)
Packit aea12f
		return 0;
Packit aea12f
Packit aea12f
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
Packit aea12f
		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_SENT) {
Packit aea12f
			uint16_t selected_identity = _gnutls_read_uint16(data);
Packit aea12f
Packit aea12f
			for (i=0;i<sizeof(session->key.binders)/sizeof(session->key.binders[0]);i++) {
Packit aea12f
				if (session->key.binders[i].prf != NULL && session->key.binders[i].idx == selected_identity) {
Packit aea12f
					if (session->key.binders[i].resumption) {
Packit aea12f
						session->internals.resumed = RESUME_TRUE;
Packit aea12f
						_gnutls_handshake_log("EXT[%p]: selected PSK-resumption mode\n", session);
Packit aea12f
					} else {
Packit aea12f
						_gnutls_handshake_log("EXT[%p]: selected PSK mode\n", session);
Packit aea12f
					}
Packit aea12f
Packit aea12f
					/* different PSK is selected, than the one we calculated early secrets */
Packit aea12f
					if (i != 0) {
Packit aea12f
						/* ensure that selected binder is set on (our) index zero */
Packit aea12f
						swap_binders(session);
Packit aea12f
Packit aea12f
						ret = _gnutls_generate_early_secrets_for_psk(session);
Packit aea12f
						if (ret < 0)
Packit aea12f
							return gnutls_assert_val(ret);
Packit aea12f
					}
Packit aea12f
					session->internals.hsk_flags |= HSK_PSK_SELECTED;
Packit aea12f
				}
Packit aea12f
			}
Packit aea12f
Packit aea12f
			return 0;
Packit aea12f
		} else {
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
Packit aea12f
		}
Packit aea12f
	} else {
Packit aea12f
		if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED) {
Packit aea12f
			if (session->internals.hsk_flags & HSK_PSK_KE_MODE_INVALID) {
Packit aea12f
				/* We received a "psk_ke_modes" extension, but with a value we don't support */
Packit aea12f
				return 0;
Packit aea12f
			}
Packit aea12f
Packit aea12f
			pskcred = (gnutls_psk_server_credentials_t)
Packit aea12f
					_gnutls_get_cred(session, GNUTLS_CRD_PSK);
Packit aea12f
Packit aea12f
			/* If there are no PSK credentials, this extension is not applicable,
Packit aea12f
			 * so we return zero. */
Packit aea12f
			if (pskcred == NULL && (session->internals.flags & GNUTLS_NO_TICKETS))
Packit aea12f
				return 0;
Packit aea12f
Packit aea12f
			return server_recv_params(session, data, len, pskcred);
Packit aea12f
		} else {
Packit aea12f
			return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
Packit aea12f
		}
Packit aea12f
	}
Packit aea12f
}
Packit aea12f
Packit aea12f
const hello_ext_entry_st ext_mod_pre_shared_key = {
Packit aea12f
	.name = "Pre Shared Key",
Packit aea12f
	.tls_id = PRE_SHARED_KEY_TLS_ID,
Packit aea12f
	.gid = GNUTLS_EXTENSION_PRE_SHARED_KEY,
Packit Service 991b93
	.client_parse_point = GNUTLS_EXT_TLS,
Packit Service 991b93
	.server_parse_point = GNUTLS_EXT_TLS,
Packit aea12f
	.validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO,
Packit aea12f
	.send_func = _gnutls_psk_send_params,
Packit aea12f
	.recv_func = _gnutls_psk_recv_params
Packit aea12f
};