early-access version 2698
This commit is contained in:
238
externals/libressl/ssl/tls13_handshake.c
vendored
238
externals/libressl/ssl/tls13_handshake.c
vendored
@@ -1,6 +1,6 @@
|
||||
/* $OpenBSD: tls13_handshake.c,v 1.64 2020/07/30 16:23:17 tb Exp $ */
|
||||
/* $OpenBSD: tls13_handshake.c,v 1.70 2021/09/16 19:25:30 jsing Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Theo Buehler <tb@openbsd.org>
|
||||
* Copyright (c) 2018-2021 Theo Buehler <tb@openbsd.org>
|
||||
* Copyright (c) 2019 Joel Sing <jsing@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -48,6 +48,9 @@ static int tls13_handshake_send_action(struct tls13_ctx *ctx,
|
||||
static int tls13_handshake_recv_action(struct tls13_ctx *ctx,
|
||||
const struct tls13_handshake_action *action);
|
||||
|
||||
static int tls13_handshake_set_legacy_state(struct tls13_ctx *ctx);
|
||||
static int tls13_handshake_legacy_info_callback(struct tls13_ctx *ctx);
|
||||
|
||||
static const struct tls13_handshake_action state_machine[] = {
|
||||
[CLIENT_HELLO] = {
|
||||
.handshake_type = TLS13_MT_CLIENT_HELLO,
|
||||
@@ -328,6 +331,18 @@ tls13_handshake_advance_state_machine(struct tls13_ctx *ctx)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tls13_handshake_end_of_flight(struct tls13_ctx *ctx,
|
||||
const struct tls13_handshake_action *previous)
|
||||
{
|
||||
const struct tls13_handshake_action *current;
|
||||
|
||||
if ((current = tls13_handshake_active_action(ctx)) == NULL)
|
||||
return 1;
|
||||
|
||||
return current->sender != previous->sender;
|
||||
}
|
||||
|
||||
int
|
||||
tls13_handshake_msg_record(struct tls13_ctx *ctx)
|
||||
{
|
||||
@@ -341,40 +356,64 @@ int
|
||||
tls13_handshake_perform(struct tls13_ctx *ctx)
|
||||
{
|
||||
const struct tls13_handshake_action *action;
|
||||
int sending;
|
||||
int ret;
|
||||
|
||||
if (!ctx->handshake_started) {
|
||||
/*
|
||||
* Set legacy state to connect/accept and call info callback
|
||||
* to signal that the handshake started.
|
||||
*/
|
||||
if (!tls13_handshake_set_legacy_state(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
if (!tls13_handshake_legacy_info_callback(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
|
||||
ctx->handshake_started = 1;
|
||||
if (ctx->info_cb != NULL)
|
||||
ctx->info_cb(ctx, TLS13_INFO_HANDSHAKE_STARTED, 1);
|
||||
|
||||
/* Set legacy state for initial ClientHello read or write. */
|
||||
if (!tls13_handshake_set_legacy_state(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if ((action = tls13_handshake_active_action(ctx)) == NULL)
|
||||
return TLS13_IO_FAILURE;
|
||||
|
||||
if (ctx->need_flush) {
|
||||
if ((ret = tls13_record_layer_flush(ctx->rl)) !=
|
||||
TLS13_IO_SUCCESS)
|
||||
return ret;
|
||||
ctx->need_flush = 0;
|
||||
}
|
||||
|
||||
if (action->handshake_complete) {
|
||||
ctx->handshake_completed = 1;
|
||||
tls13_record_layer_handshake_completed(ctx->rl);
|
||||
if (ctx->info_cb != NULL)
|
||||
ctx->info_cb(ctx,
|
||||
TLS13_INFO_HANDSHAKE_COMPLETED, 1);
|
||||
|
||||
if (!tls13_handshake_set_legacy_state(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
if (!tls13_handshake_legacy_info_callback(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
|
||||
return TLS13_IO_SUCCESS;
|
||||
}
|
||||
|
||||
sending = action->sender == ctx->mode;
|
||||
|
||||
DEBUGF("%s %s %s\n", tls13_handshake_mode_name(ctx->mode),
|
||||
(action->sender == ctx->mode) ? "sending" : "receiving",
|
||||
sending ? "sending" : "receiving",
|
||||
tls13_handshake_message_name(action->handshake_type));
|
||||
|
||||
if (ctx->alert)
|
||||
if (ctx->alert != 0)
|
||||
return tls13_send_alert(ctx->rl, ctx->alert);
|
||||
|
||||
if (action->sender == ctx->mode)
|
||||
if (sending)
|
||||
ret = tls13_handshake_send_action(ctx, action);
|
||||
else
|
||||
ret = tls13_handshake_recv_action(ctx, action);
|
||||
|
||||
if (ctx->alert)
|
||||
if (ctx->alert != 0)
|
||||
return tls13_send_alert(ctx->rl, ctx->alert);
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -385,8 +424,18 @@ tls13_handshake_perform(struct tls13_ctx *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!tls13_handshake_legacy_info_callback(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
|
||||
if (!tls13_handshake_advance_state_machine(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
|
||||
if (sending)
|
||||
ctx->need_flush = tls13_handshake_end_of_flight(ctx,
|
||||
action);
|
||||
|
||||
if (!tls13_handshake_set_legacy_state(ctx))
|
||||
return TLS13_IO_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,8 +477,9 @@ tls13_handshake_send_action(struct tls13_ctx *ctx,
|
||||
|
||||
if (action->send_preserve_transcript_hash) {
|
||||
if (!tls1_transcript_hash_value(ctx->ssl,
|
||||
ctx->hs->transcript_hash, sizeof(ctx->hs->transcript_hash),
|
||||
&ctx->hs->transcript_hash_len))
|
||||
ctx->hs->tls13.transcript_hash,
|
||||
sizeof(ctx->hs->tls13.transcript_hash),
|
||||
&ctx->hs->tls13.transcript_hash_len))
|
||||
return TLS13_IO_FAILURE;
|
||||
}
|
||||
|
||||
@@ -471,8 +521,9 @@ tls13_handshake_recv_action(struct tls13_ctx *ctx,
|
||||
|
||||
if (action->recv_preserve_transcript_hash) {
|
||||
if (!tls1_transcript_hash_value(ctx->ssl,
|
||||
ctx->hs->transcript_hash, sizeof(ctx->hs->transcript_hash),
|
||||
&ctx->hs->transcript_hash_len))
|
||||
ctx->hs->tls13.transcript_hash,
|
||||
sizeof(ctx->hs->tls13.transcript_hash),
|
||||
&ctx->hs->tls13.transcript_hash_len))
|
||||
return TLS13_IO_FAILURE;
|
||||
}
|
||||
|
||||
@@ -510,8 +561,163 @@ tls13_handshake_recv_action(struct tls13_ctx *ctx,
|
||||
tls13_handshake_msg_free(ctx->hs_msg);
|
||||
ctx->hs_msg = NULL;
|
||||
|
||||
if (ctx->ssl->method->internal->version < TLS1_3_VERSION)
|
||||
if (ctx->ssl->method->version < TLS1_3_VERSION)
|
||||
return TLS13_IO_USE_LEGACY;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct tls13_handshake_legacy_state {
|
||||
int recv;
|
||||
int send;
|
||||
};
|
||||
|
||||
static const struct tls13_handshake_legacy_state legacy_states[] = {
|
||||
[CLIENT_HELLO] = {
|
||||
.recv = SSL3_ST_SR_CLNT_HELLO_A,
|
||||
.send = SSL3_ST_CW_CLNT_HELLO_A,
|
||||
},
|
||||
[SERVER_HELLO_RETRY_REQUEST] = {
|
||||
.recv = SSL3_ST_CR_SRVR_HELLO_A,
|
||||
.send = SSL3_ST_SW_SRVR_HELLO_A,
|
||||
},
|
||||
[CLIENT_HELLO_RETRY] = {
|
||||
.recv = SSL3_ST_SR_CLNT_HELLO_A,
|
||||
.send = SSL3_ST_CW_CLNT_HELLO_A,
|
||||
},
|
||||
[SERVER_HELLO] = {
|
||||
.recv = SSL3_ST_CR_SRVR_HELLO_A,
|
||||
.send = SSL3_ST_SW_SRVR_HELLO_A,
|
||||
},
|
||||
[SERVER_ENCRYPTED_EXTENSIONS] = {
|
||||
.send = 0,
|
||||
.recv = 0,
|
||||
},
|
||||
[SERVER_CERTIFICATE_REQUEST] = {
|
||||
.recv = SSL3_ST_CR_CERT_REQ_A,
|
||||
.send = SSL3_ST_SW_CERT_REQ_A,
|
||||
},
|
||||
[SERVER_CERTIFICATE] = {
|
||||
.recv = SSL3_ST_CR_CERT_A,
|
||||
.send = SSL3_ST_SW_CERT_A,
|
||||
},
|
||||
[SERVER_CERTIFICATE_VERIFY] = {
|
||||
.send = 0,
|
||||
.recv = 0,
|
||||
},
|
||||
[SERVER_FINISHED] = {
|
||||
.recv = SSL3_ST_CR_FINISHED_A,
|
||||
.send = SSL3_ST_SW_FINISHED_A,
|
||||
},
|
||||
[CLIENT_END_OF_EARLY_DATA] = {
|
||||
.send = 0,
|
||||
.recv = 0,
|
||||
},
|
||||
[CLIENT_CERTIFICATE] = {
|
||||
.recv = SSL3_ST_SR_CERT_VRFY_A,
|
||||
.send = SSL3_ST_CW_CERT_VRFY_B,
|
||||
},
|
||||
[CLIENT_CERTIFICATE_VERIFY] = {
|
||||
.send = 0,
|
||||
.recv = 0,
|
||||
},
|
||||
[CLIENT_FINISHED] = {
|
||||
.recv = SSL3_ST_SR_FINISHED_A,
|
||||
.send = SSL3_ST_CW_FINISHED_A,
|
||||
},
|
||||
[APPLICATION_DATA] = {
|
||||
.recv = 0,
|
||||
.send = 0,
|
||||
},
|
||||
};
|
||||
|
||||
CTASSERT(sizeof(state_machine) / sizeof(state_machine[0]) ==
|
||||
sizeof(legacy_states) / sizeof(legacy_states[0]));
|
||||
|
||||
static int
|
||||
tls13_handshake_legacy_state(struct tls13_ctx *ctx, int *out_state)
|
||||
{
|
||||
const struct tls13_handshake_action *action;
|
||||
enum tls13_message_type mt;
|
||||
|
||||
*out_state = 0;
|
||||
|
||||
if (!ctx->handshake_started) {
|
||||
if (ctx->mode == TLS13_HS_CLIENT)
|
||||
*out_state = SSL_ST_CONNECT;
|
||||
else
|
||||
*out_state = SSL_ST_ACCEPT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ctx->handshake_completed) {
|
||||
*out_state = SSL_ST_OK;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((mt = tls13_handshake_active_state(ctx)) == INVALID)
|
||||
return 0;
|
||||
|
||||
if ((action = tls13_handshake_active_action(ctx)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (action->sender == ctx->mode)
|
||||
*out_state = legacy_states[mt].send;
|
||||
else
|
||||
*out_state = legacy_states[mt].recv;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tls13_handshake_info_position(struct tls13_ctx *ctx)
|
||||
{
|
||||
if (!ctx->handshake_started)
|
||||
return TLS13_INFO_HANDSHAKE_STARTED;
|
||||
|
||||
if (ctx->handshake_completed)
|
||||
return TLS13_INFO_HANDSHAKE_COMPLETED;
|
||||
|
||||
if (ctx->mode == TLS13_HS_CLIENT)
|
||||
return TLS13_INFO_CONNECT_LOOP;
|
||||
else
|
||||
return TLS13_INFO_ACCEPT_LOOP;
|
||||
}
|
||||
|
||||
static int
|
||||
tls13_handshake_legacy_info_callback(struct tls13_ctx *ctx)
|
||||
{
|
||||
int state, where;
|
||||
|
||||
if (!tls13_handshake_legacy_state(ctx, &state))
|
||||
return 0;
|
||||
|
||||
/* Do nothing if there's no corresponding legacy state. */
|
||||
if (state == 0)
|
||||
return 1;
|
||||
|
||||
if (ctx->info_cb != NULL) {
|
||||
where = tls13_handshake_info_position(ctx);
|
||||
ctx->info_cb(ctx, where, 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tls13_handshake_set_legacy_state(struct tls13_ctx *ctx)
|
||||
{
|
||||
int state;
|
||||
|
||||
if (!tls13_handshake_legacy_state(ctx, &state))
|
||||
return 0;
|
||||
|
||||
/* Do nothing if there's no corresponding legacy state. */
|
||||
if (state == 0)
|
||||
return 1;
|
||||
|
||||
ctx->hs->state = state;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user