|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2017-2018 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Functions that relate to the TLS handshake procedure.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include "dh.h"
|
|
Packit Service |
4684c1 |
#include "debug.h"
|
|
Packit Service |
4684c1 |
#include "algorithms.h"
|
|
Packit Service |
4684c1 |
#include "cipher.h"
|
|
Packit Service |
4684c1 |
#include "buffers.h"
|
|
Packit Service |
4684c1 |
#include "mbuffers.h"
|
|
Packit Service |
4684c1 |
#include "kx.h"
|
|
Packit Service |
4684c1 |
#include "handshake.h"
|
|
Packit Service |
4684c1 |
#include "num.h"
|
|
Packit Service |
4684c1 |
#include "hash_int.h"
|
|
Packit Service |
4684c1 |
#include "db.h"
|
|
Packit Service |
4684c1 |
#include "hello_ext.h"
|
|
Packit Service |
4684c1 |
#include "supplemental.h"
|
|
Packit Service |
4684c1 |
#include "auth.h"
|
|
Packit Service |
4684c1 |
#include "sslv2_compat.h"
|
|
Packit Service |
4684c1 |
#include <auth/cert.h>
|
|
Packit Service |
4684c1 |
#include "constate.h"
|
|
Packit Service |
4684c1 |
#include <record.h>
|
|
Packit Service |
4684c1 |
#include <state.h>
|
|
Packit Service |
4684c1 |
#include <random.h>
|
|
Packit Service |
4684c1 |
#include <dtls.h>
|
|
Packit Service |
4684c1 |
#include "secrets.h"
|
|
Packit Service |
4684c1 |
#include "tls13/hello_retry.h"
|
|
Packit Service |
4684c1 |
#include "tls13/encrypted_extensions.h"
|
|
Packit Service |
4684c1 |
#include "tls13/certificate_request.h"
|
|
Packit Service |
4684c1 |
#include "tls13/certificate_verify.h"
|
|
Packit Service |
4684c1 |
#include "tls13/certificate.h"
|
|
Packit Service |
4684c1 |
#include "tls13/early_data.h"
|
|
Packit Service |
4684c1 |
#include "tls13/finished.h"
|
|
Packit Service |
4684c1 |
#include "tls13/key_update.h"
|
|
Packit Service |
4684c1 |
#include "ext/pre_shared_key.h"
|
|
Packit Service |
4684c1 |
#include "locks.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int generate_rms_keys(gnutls_session_t session);
|
|
Packit Service |
4684c1 |
static int generate_hs_traffic_keys(gnutls_session_t session);
|
|
Packit Service |
4684c1 |
static int generate_ap_traffic_keys(gnutls_session_t session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define SAVE_TRANSCRIPT \
|
|
Packit Service |
4684c1 |
if (session->internals.flags & GNUTLS_POST_HANDSHAKE_AUTH) { \
|
|
Packit Service |
4684c1 |
/* If post-handshake auth is in use we need a copy of the original \
|
|
Packit Service |
4684c1 |
* handshake transcript */ \
|
|
Packit Service |
4684c1 |
memcpy( &session->internals.post_handshake_hash_buffer, \
|
|
Packit Service |
4684c1 |
&session->internals.handshake_hash_buffer, \
|
|
Packit Service |
4684c1 |
sizeof(session->internals.handshake_hash_buffer)); \
|
|
Packit Service |
4684c1 |
_gnutls_buffer_init(&session->internals.handshake_hash_buffer); \
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* _gnutls13_handshake_client
|
|
Packit Service |
4684c1 |
* This function performs the client side of the handshake of the TLS/SSL protocol.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls13_handshake_client(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (STATE) {
|
|
Packit Service |
4684c1 |
case STATE99:
|
|
Packit Service |
4684c1 |
case STATE100:
|
|
Packit Service |
4684c1 |
#ifdef TLS13_APPENDIX_D4
|
|
Packit Service |
4684c1 |
/* We send it before keys are generated. That works because CCS
|
|
Packit Service |
4684c1 |
* is always being cached and queued and not being sent directly */
|
|
Packit Service |
4684c1 |
ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100));
|
|
Packit Service |
4684c1 |
STATE = STATE100;
|
|
Packit Service |
4684c1 |
IMED_RET("send change cipher spec", ret, 0);
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE101:
|
|
Packit Service |
4684c1 |
/* Note that we check IN_FLIGHT, not ACCEPTED
|
|
Packit Service |
4684c1 |
* here. This is because the client sends early data
|
|
Packit Service |
4684c1 |
* speculatively. */
|
|
Packit Service |
4684c1 |
if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) {
|
|
Packit Service |
4684c1 |
ret = _tls13_write_connection_state_init(session, STAGE_EARLY);
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
_gnutls_epoch_bump(session);
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_dup(session, EPOCH_WRITE_CURRENT);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
STATE = STATE101;
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set early traffic keys", ret, 0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE102:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_early_data(session);
|
|
Packit Service |
4684c1 |
STATE = STATE102;
|
|
Packit Service |
4684c1 |
IMED_RET("send early data", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE103:
|
|
Packit Service |
4684c1 |
STATE = STATE103;
|
|
Packit Service |
4684c1 |
ret = generate_hs_traffic_keys(session);
|
|
Packit Service |
4684c1 |
/* Note that we check IN_FLIGHT, not ACCEPTED
|
|
Packit Service |
4684c1 |
* here. This is because the client sends early data
|
|
Packit Service |
4684c1 |
* speculatively. */
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate hs traffic keys", ret, 0);
|
|
Packit Service |
4684c1 |
if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)
|
|
Packit Service |
4684c1 |
ret = _tls13_read_connection_state_init(session, STAGE_HS);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
ret = _tls13_connection_state_init(session, STAGE_HS);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set hs traffic keys", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE104:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_encrypted_extensions(session);
|
|
Packit Service |
4684c1 |
STATE = STATE104;
|
|
Packit Service |
4684c1 |
IMED_RET("recv encrypted extensions", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE105:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_certificate_request(session);
|
|
Packit Service |
4684c1 |
STATE = STATE105;
|
|
Packit Service |
4684c1 |
IMED_RET("recv certificate request", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE106:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_certificate(session);
|
|
Packit Service |
4684c1 |
STATE = STATE106;
|
|
Packit Service |
4684c1 |
IMED_RET("recv certificate", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE107:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_certificate_verify(session);
|
|
Packit Service |
4684c1 |
STATE = STATE107;
|
|
Packit Service |
4684c1 |
IMED_RET("recv server certificate verify", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE108:
|
|
Packit Service |
4684c1 |
ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);
|
|
Packit Service |
4684c1 |
STATE = STATE108;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE109:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_finished(session);
|
|
Packit Service |
4684c1 |
STATE = STATE109;
|
|
Packit Service |
4684c1 |
IMED_RET("recv finished", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE110:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_end_of_early_data(session, AGAIN(STATE110));
|
|
Packit Service |
4684c1 |
STATE = STATE110;
|
|
Packit Service |
4684c1 |
IMED_RET("send end of early data", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Note that we check IN_FLIGHT, not ACCEPTED
|
|
Packit Service |
4684c1 |
* here. This is because the client sends early data
|
|
Packit Service |
4684c1 |
* speculatively. */
|
|
Packit Service |
4684c1 |
if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) {
|
|
Packit Service |
4684c1 |
session->internals.hsk_flags &= ~HSK_EARLY_DATA_IN_FLIGHT;
|
|
Packit Service |
4684c1 |
ret = _tls13_write_connection_state_init(session, STAGE_HS);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set hs traffic key after sending early data", ret, 0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE111:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_certificate(session, AGAIN(STATE111));
|
|
Packit Service |
4684c1 |
STATE = STATE111;
|
|
Packit Service |
4684c1 |
IMED_RET("send certificate", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE112:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE112));
|
|
Packit Service |
4684c1 |
STATE = STATE112;
|
|
Packit Service |
4684c1 |
IMED_RET("send certificate verify", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE113:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_finished(session, AGAIN(STATE113));
|
|
Packit Service |
4684c1 |
STATE = STATE113;
|
|
Packit Service |
4684c1 |
IMED_RET("send finished", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE114:
|
|
Packit Service |
4684c1 |
STATE = STATE114;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
generate_ap_traffic_keys(session);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate app keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = generate_rms_keys(session);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate rms keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* set traffic keys */
|
|
Packit Service |
4684c1 |
ret = _tls13_connection_state_init(session, STAGE_APP);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set app keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
STATE = STATE0;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* no lock of post_negotiation_lock is required here as this is not run
|
|
Packit Service |
4684c1 |
* after handshake */
|
|
Packit Service |
4684c1 |
session->internals.recv_state = RECV_STATE_0;
|
|
Packit Service |
4684c1 |
session->internals.initial_negotiation_completed = 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
SAVE_TRANSCRIPT;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.resumed != RESUME_FALSE)
|
|
Packit Service |
4684c1 |
_gnutls_set_resumed_parameters(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int generate_non_auth_rms_keys(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
/* we simulate client finished */
|
|
Packit Service |
4684c1 |
uint8_t finished[MAX_HASH_SIZE+TLS_HANDSHAKE_HEADER_SIZE];
|
|
Packit Service |
4684c1 |
unsigned spos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls13_compute_finished(session->security_parameters.prf,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.hs_ckey,
|
|
Packit Service |
4684c1 |
&session->internals.handshake_hash_buffer,
|
|
Packit Service |
4684c1 |
finished+TLS_HANDSHAKE_HEADER_SIZE);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
spos = session->internals.handshake_hash_buffer.length;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
finished[0] = GNUTLS_HANDSHAKE_FINISHED;
|
|
Packit Service |
4684c1 |
_gnutls_write_uint24(session->security_parameters.prf->output_size, finished+1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer, finished,
|
|
Packit Service |
4684c1 |
TLS_HANDSHAKE_HEADER_SIZE+session->security_parameters.prf->output_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_derive_secret(session, RMS_MASTER_LABEL, sizeof(RMS_MASTER_LABEL)-1,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer.data,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer.length,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_rms);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer.length = spos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int generate_rms_keys(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_derive_secret(session, RMS_MASTER_LABEL, sizeof(RMS_MASTER_LABEL)-1,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer.data,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer_client_finished_len,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_rms);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int generate_ap_traffic_keys(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
uint8_t zero[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_derive_secret(session, DERIVED_LABEL, sizeof(DERIVED_LABEL)-1,
|
|
Packit Service |
4684c1 |
NULL, 0, session->key.proto.tls13.temp_secret,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(zero, 0, session->security_parameters.prf->output_size);
|
|
Packit Service |
4684c1 |
ret = _tls13_update_secret(session, zero, session->security_parameters.prf->output_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_derive_secret(session, EXPORTER_MASTER_LABEL, sizeof(EXPORTER_MASTER_LABEL)-1,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer.data,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer_server_finished_len,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_expkey);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_call_keylog_func(session, "EXPORTER_SECRET",
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_expkey,
|
|
Packit Service |
4684c1 |
session->security_parameters.prf->output_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_epoch_bump(session);
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int generate_hs_traffic_keys(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
unsigned null_key = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(session->key.proto.tls13.temp_secret_size == 0))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_derive_secret(session, DERIVED_LABEL, sizeof(DERIVED_LABEL)-1,
|
|
Packit Service |
4684c1 |
NULL, 0, session->key.proto.tls13.temp_secret,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret);
|
|
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 |
if ((session->security_parameters.entity == GNUTLS_CLIENT &&
|
|
Packit Service |
4684c1 |
(!(session->internals.hsk_flags & HSK_KEY_SHARE_RECEIVED) ||
|
|
Packit Service |
4684c1 |
(!(session->internals.hsk_flags & HSK_PSK_KE_MODE_DHE_PSK) &&
|
|
Packit Service |
4684c1 |
session->internals.resumed != RESUME_FALSE))) ||
|
|
Packit Service |
4684c1 |
(session->security_parameters.entity == GNUTLS_SERVER &&
|
|
Packit Service |
4684c1 |
!(session->internals.hsk_flags & HSK_KEY_SHARE_SENT))) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((session->internals.hsk_flags & HSK_PSK_SELECTED) &&
|
|
Packit Service |
4684c1 |
(session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK)) {
|
|
Packit Service |
4684c1 |
null_key = 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (null_key) {
|
|
Packit Service |
4684c1 |
uint8_t digest[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
unsigned digest_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(session->security_parameters.prf == NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
digest_size = session->security_parameters.prf->output_size;
|
|
Packit Service |
4684c1 |
memset(digest, 0, digest_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_update_secret(session, digest, digest_size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
if (unlikely(session->key.key.size == 0))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_update_secret(session, session->key.key.data, session->key.key.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 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* _gnutls13_handshake_server
|
|
Packit Service |
4684c1 |
* This function does the server stuff of the handshake protocol.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls13_handshake_server(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (STATE) {
|
|
Packit Service |
4684c1 |
case STATE90:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_handshake_hash_buffers_synth(session, session->security_parameters.prf, 0);
|
|
Packit Service |
4684c1 |
STATE = STATE90;
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("reset handshake buffers", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE91:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_hello_retry_request(session, AGAIN(STATE91));
|
|
Packit Service |
4684c1 |
STATE = STATE91;
|
|
Packit Service |
4684c1 |
IMED_RET("send hello retry request", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE92:
|
|
Packit Service |
4684c1 |
#ifdef TLS13_APPENDIX_D4
|
|
Packit Service |
4684c1 |
ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE92));
|
|
Packit Service |
4684c1 |
STATE = STATE92;
|
|
Packit Service |
4684c1 |
IMED_RET("send change cipher spec", ret, 0);
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE93:
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_recv_handshake(session,
|
|
Packit Service |
4684c1 |
GNUTLS_HANDSHAKE_CLIENT_HELLO,
|
|
Packit Service |
4684c1 |
0, NULL);
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_INT_RET_0) {
|
|
Packit Service |
4684c1 |
/* this is triggered by post_client_hello, and instructs the
|
|
Packit Service |
4684c1 |
* handshake to proceed but be put on hold */
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_INTERRUPTED;
|
|
Packit Service |
4684c1 |
STATE = STATE94; /* hello already parsed -> move to next state */
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
STATE = STATE93;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
IMED_RET("recv client hello", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE94:
|
|
Packit Service |
4684c1 |
ret = _gnutls_send_server_hello(session, AGAIN(STATE94));
|
|
Packit Service |
4684c1 |
STATE = STATE94;
|
|
Packit Service |
4684c1 |
IMED_RET("send hello", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE99:
|
|
Packit Service |
4684c1 |
case STATE100:
|
|
Packit Service |
4684c1 |
#ifdef TLS13_APPENDIX_D4
|
|
Packit Service |
4684c1 |
/* don't send CCS twice: when HRR has already been
|
|
Packit Service |
4684c1 |
* sent, CCS should have followed it (see above) */
|
|
Packit Service |
4684c1 |
if (!(session->internals.hsk_flags & HSK_HRR_SENT)) {
|
|
Packit Service |
4684c1 |
ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100));
|
|
Packit Service |
4684c1 |
STATE = STATE100;
|
|
Packit Service |
4684c1 |
IMED_RET("send change cipher spec", ret, 0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE101:
|
|
Packit Service |
4684c1 |
STATE = STATE101;
|
|
Packit Service |
4684c1 |
if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
|
|
Packit Service |
4684c1 |
ret = _tls13_read_connection_state_init(session, STAGE_EARLY);
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
_gnutls_epoch_bump(session);
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set early traffic keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = generate_hs_traffic_keys(session);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate hs traffic keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_write_connection_state_init(session, STAGE_HS);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = generate_hs_traffic_keys(session);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate hs traffic keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_connection_state_init(session, STAGE_HS);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set hs traffic keys", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE102:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_encrypted_extensions(session, AGAIN(STATE102));
|
|
Packit Service |
4684c1 |
STATE = STATE102;
|
|
Packit Service |
4684c1 |
IMED_RET("send encrypted extensions", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE103:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_certificate_request(session, AGAIN(STATE103));
|
|
Packit Service |
4684c1 |
STATE = STATE103;
|
|
Packit Service |
4684c1 |
IMED_RET("send certificate request", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE104:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_certificate(session, AGAIN(STATE104));
|
|
Packit Service |
4684c1 |
STATE = STATE104;
|
|
Packit Service |
4684c1 |
IMED_RET("send certificate", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE105:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE105));
|
|
Packit Service |
4684c1 |
STATE = STATE105;
|
|
Packit Service |
4684c1 |
IMED_RET("send certificate verify", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE106:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_finished(session, AGAIN(STATE106));
|
|
Packit Service |
4684c1 |
STATE = STATE106;
|
|
Packit Service |
4684c1 |
IMED_RET("send finished", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE107:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_end_of_early_data(session);
|
|
Packit Service |
4684c1 |
STATE = STATE107;
|
|
Packit Service |
4684c1 |
IMED_RET("recv end of early data", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
|
|
Packit Service |
4684c1 |
ret = _tls13_read_connection_state_init(session, STAGE_HS);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set hs traffic key after receiving early data", ret, 0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE108:
|
|
Packit Service |
4684c1 |
/* At this point our sending keys should be the app keys
|
|
Packit Service |
4684c1 |
* see 4.4.4 at draft-ietf-tls-tls13-28 */
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
generate_ap_traffic_keys(session);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate app keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* If the session is unauthenticated, try to optimize the handshake by
|
|
Packit Service |
4684c1 |
* sending the session ticket early. */
|
|
Packit Service |
4684c1 |
if (!(session->internals.hsk_flags & (HSK_CRT_REQ_SENT|HSK_PSK_SELECTED))) {
|
|
Packit Service |
4684c1 |
STATE = STATE108;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = generate_non_auth_rms_keys(session);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate rms keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.hsk_flags |= HSK_EARLY_START_USED;
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: unauthenticated session eligible for early start\n", session);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_write_connection_state_init(session, STAGE_APP);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set write app keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: switching early to application traffic keys\n", session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE109:
|
|
Packit Service |
4684c1 |
if (session->internals.resumed != RESUME_FALSE)
|
|
Packit Service |
4684c1 |
_gnutls_set_resumed_parameters(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.hsk_flags & HSK_EARLY_START_USED) {
|
|
Packit Service |
4684c1 |
if (!(session->internals.flags & GNUTLS_NO_AUTO_SEND_TICKET))
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_session_ticket(session, TLS13_TICKETS_TO_SEND,
|
|
Packit Service |
4684c1 |
AGAIN(STATE109));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
STATE = STATE109;
|
|
Packit Service |
4684c1 |
IMED_RET("send session ticket", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* complete this phase of the handshake. We
|
|
Packit Service |
4684c1 |
* should be called again by gnutls_record_recv()
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.flags & GNUTLS_ENABLE_EARLY_START) {
|
|
Packit Service |
4684c1 |
STATE = STATE113; /* finished */
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.recv_state = RECV_STATE_EARLY_START;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE110:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_certificate(session);
|
|
Packit Service |
4684c1 |
STATE = STATE110;
|
|
Packit Service |
4684c1 |
IMED_RET("recv certificate", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE111:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_certificate_verify(session);
|
|
Packit Service |
4684c1 |
STATE = STATE111;
|
|
Packit Service |
4684c1 |
IMED_RET("recv certificate verify", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE112:
|
|
Packit Service |
4684c1 |
ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);
|
|
Packit Service |
4684c1 |
STATE = STATE112;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE113: /* can enter from STATE109 */
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_finished(session);
|
|
Packit Service |
4684c1 |
STATE = STATE113;
|
|
Packit Service |
4684c1 |
IMED_RET("recv finished", ret, 0);
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE114:
|
|
Packit Service |
4684c1 |
/* If we did request a client certificate, then we can
|
|
Packit Service |
4684c1 |
* only send the tickets here */
|
|
Packit Service |
4684c1 |
STATE = STATE114;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(session->internals.hsk_flags & HSK_EARLY_START_USED)) {
|
|
Packit Service |
4684c1 |
ret = generate_rms_keys(session);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("generate rms keys", ret, 0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_read_connection_state_init(session, STAGE_APP);
|
|
Packit Service |
4684c1 |
IMED_RET_FATAL("set read app keys", ret, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case STATE115:
|
|
Packit Service |
4684c1 |
if (!(session->internals.hsk_flags & (HSK_TLS13_TICKET_SENT|HSK_EARLY_START_USED)) &&
|
|
Packit Service |
4684c1 |
!(session->internals.flags & GNUTLS_NO_AUTO_SEND_TICKET)) {
|
|
Packit Service |
4684c1 |
ret = _gnutls13_send_session_ticket(session, TLS13_TICKETS_TO_SEND,
|
|
Packit Service |
4684c1 |
AGAIN(STATE115));
|
|
Packit Service |
4684c1 |
STATE = STATE115;
|
|
Packit Service |
4684c1 |
IMED_RET("send session ticket", ret, 0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
STATE = STATE0;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* explicitly reset any early start flags */
|
|
Packit Service |
4684c1 |
gnutls_mutex_lock(&session->internals.post_negotiation_lock);
|
|
Packit Service |
4684c1 |
session->internals.recv_state = RECV_STATE_0;
|
|
Packit Service |
4684c1 |
session->internals.initial_negotiation_completed = 1;
|
|
Packit Service |
4684c1 |
gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
SAVE_TRANSCRIPT;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Processes handshake messages received asynchronously after initial handshake.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* It is called once per message and should return success, or a fatal error code.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls13_recv_async_handshake(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
handshake_buffer_st hsk;
|
|
Packit Service |
4684c1 |
recv_state_t next_state = RECV_STATE_0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* The following messages are expected asynchronously after
|
|
Packit Service |
4684c1 |
* the handshake process is complete */
|
|
Packit Service |
4684c1 |
if (unlikely(session->internals.handshake_in_progress))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
do {
|
|
Packit Service |
4684c1 |
_gnutls_handshake_buffer_init(&hsk;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* the received handshake message has already been pushed into
|
|
Packit Service |
4684c1 |
* handshake buffers. As we do not need to use the handshake hash
|
|
Packit Service |
4684c1 |
* buffers we call the lower level receive functions */
|
|
Packit Service |
4684c1 |
ret = _gnutls_handshake_io_recv_int(session, GNUTLS_HANDSHAKE_ANY, &hsk, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
session->internals.last_handshake_in = hsk.htype;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_call_hook_func(session, hsk.htype, GNUTLS_HOOK_PRE, 1,
|
|
Packit Service |
4684c1 |
hsk.data.data, hsk.data.length);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch(hsk.htype) {
|
|
Packit Service |
4684c1 |
case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
|
|
Packit Service |
4684c1 |
if (!(session->security_parameters.entity == GNUTLS_CLIENT) ||
|
|
Packit Service |
4684c1 |
!(session->internals.flags & GNUTLS_POST_HANDSHAKE_AUTH)) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_buffer_reset(&session->internals.reauth_buffer);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* include the handshake headers in reauth buffer */
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_data(&session->internals.reauth_buffer,
|
|
Packit Service |
4684c1 |
hsk.header, hsk.header_size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_data(&session->internals.reauth_buffer,
|
|
Packit Service |
4684c1 |
hsk.data.data, hsk.data.length);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.flags & GNUTLS_AUTO_REAUTH) {
|
|
Packit Service |
4684c1 |
ret = gnutls_reauth(session, 0);
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
|
|
Packit Service |
4684c1 |
next_state = RECV_STATE_REAUTH;
|
|
Packit Service |
4684c1 |
} else if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
/* Application is expected to handle re-authentication
|
|
Packit Service |
4684c1 |
* explicitly. */
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_REAUTH_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
case GNUTLS_HANDSHAKE_KEY_UPDATE:
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_key_update(session, &hsk.data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Handshake messages MUST NOT span key changes, i.e., we
|
|
Packit Service |
4684c1 |
* should not have any other pending handshake messages from
|
|
Packit Service |
4684c1 |
* the same record. */
|
|
Packit Service |
4684c1 |
if (session->internals.handshake_recv_buffer_size != 0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET:
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity != GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls13_recv_session_ticket(session, &hsk.data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(session->internals.tls13_ticket.resumption_master_secret,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_rms,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.tls13_ticket.prf = session->security_parameters.prf;
|
|
Packit Service |
4684c1 |
session->internals.hsk_flags |= HSK_TICKET_RECEIVED;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_UNEXPECTED_PACKET;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_call_hook_func(session, hsk.htype, GNUTLS_HOOK_POST, 1, hsk.data.data, hsk.data.length);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
_gnutls_handshake_buffer_clear(&hsk;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
} while (_gnutls_record_buffer_get_size(session) > 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.recv_state = next_state;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
/* if we have pending/partial handshake data in buffers, ensure that
|
|
Packit Service |
4684c1 |
* next read will read handshake data */
|
|
Packit Service |
4684c1 |
if (_gnutls_record_buffer_get_size(session) > 0)
|
|
Packit Service |
4684c1 |
session->internals.recv_state = RECV_STATE_ASYNC_HANDSHAKE;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
session->internals.recv_state = next_state;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_buffer_clear(&hsk;;
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_session_ticket_send:
|
|
Packit Service |
4684c1 |
* @session: is a #gnutls_session_t type.
|
|
Packit Service |
4684c1 |
* @nr: the number of tickets to send
|
|
Packit Service |
4684c1 |
* @flags: must be zero
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Sends a fresh session ticket to the peer. This is relevant only
|
|
Packit Service |
4684c1 |
* in server side under TLS1.3. This function may also return %GNUTLS_E_AGAIN
|
|
Packit Service |
4684c1 |
* or %GNUTLS_E_INTERRUPTED and in that case it must be called again.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: %GNUTLS_E_SUCCESS on success, or a negative error code.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int gnutls_session_ticket_send(gnutls_session_t session, unsigned nr, unsigned flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret = 0;
|
|
Packit Service |
4684c1 |
const version_entry_st *vers = get_version(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!vers->tls13_sem || session->security_parameters.entity == GNUTLS_CLIENT)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (nr == 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (TICKET_STATE) {
|
|
Packit Service |
4684c1 |
case TICKET_STATE0:
|
|
Packit Service |
4684c1 |
ret = _gnutls_io_write_flush(session);
|
|
Packit Service |
4684c1 |
TICKET_STATE = TICKET_STATE0;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
FALLTHROUGH;
|
|
Packit Service |
4684c1 |
case TICKET_STATE1:
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls13_send_session_ticket(session, nr, TICKET_STATE==TICKET_STATE1?1:0);
|
|
Packit Service |
4684c1 |
TICKET_STATE = TICKET_STATE1;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INTERNAL_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
TICKET_STATE = TICKET_STATE0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|