From: tb Date: Mon, 28 Jun 2021 15:35:14 +0000 (+0000) Subject: Expand info callback support for TLSv1.3 X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=2d0d1bb887eb5bcad5457bc2e8dab6df8f354041;p=openbsd Expand info callback support for TLSv1.3 During the TLSv1.3 handshake, update the legacy state and call the info callback at the appropriate moment. This is done by mapping the TLSv1.3 states to the states in the old state machine whenever that is possible. The callbacks are called at the beginning and end of the handshake, and just before the state machine advances. This should fix a periodic warning in logs of tor relays about a variable that wasn't set although it should have been. input/ok jsing, ok inoguchi (early version) --- diff --git a/lib/libssl/tls13_handshake.c b/lib/libssl/tls13_handshake.c index c18a2dfe062..578cea338f9 100644 --- a/lib/libssl/tls13_handshake.c +++ b/lib/libssl/tls13_handshake.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_handshake.c,v 1.65 2021/03/21 18:36:34 jsing Exp $ */ +/* $OpenBSD: tls13_handshake.c,v 1.66 2021/06/28 15:35:14 tb Exp $ */ /* * Copyright (c) 2018-2019 Theo Buehler * Copyright (c) 2019 Joel Sing @@ -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, @@ -344,9 +347,20 @@ tls13_handshake_perform(struct tls13_ctx *ctx) 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 (;;) { @@ -356,9 +370,12 @@ tls13_handshake_perform(struct tls13_ctx *ctx) 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; } @@ -385,8 +402,14 @@ 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 (!tls13_handshake_set_legacy_state(ctx)) + return TLS13_IO_FAILURE; } } @@ -517,3 +540,158 @@ tls13_handshake_recv_action(struct tls13_ctx *ctx, 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 (ctx->mode == action->sender) + *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; +} diff --git a/lib/libssl/tls13_internal.h b/lib/libssl/tls13_internal.h index 973661acc9b..30ef7dd9312 100644 --- a/lib/libssl/tls13_internal.h +++ b/lib/libssl/tls13_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_internal.h,v 1.89 2021/03/21 18:36:34 jsing Exp $ */ +/* $OpenBSD: tls13_internal.h,v 1.90 2021/06/28 15:35:14 tb Exp $ */ /* * Copyright (c) 2018 Bob Beck * Copyright (c) 2018 Theo Buehler @@ -81,6 +81,8 @@ __BEGIN_HIDDEN_DECLS #define TLS13_INFO_HANDSHAKE_STARTED SSL_CB_HANDSHAKE_START #define TLS13_INFO_HANDSHAKE_COMPLETED SSL_CB_HANDSHAKE_DONE +#define TLS13_INFO_ACCEPT_LOOP SSL_CB_ACCEPT_LOOP +#define TLS13_INFO_CONNECT_LOOP SSL_CB_CONNECT_LOOP typedef void (*tls13_alert_cb)(uint8_t _alert_desc, void *_cb_arg); typedef ssize_t (*tls13_phh_recv_cb)(void *_cb_arg, CBS *_cbs);