From b8698e11d9883dab7da69566fc2cd28afaf199a8 Mon Sep 17 00:00:00 2001 From: tb <> Date: Sun, 10 May 2020 17:13:30 +0000 Subject: Send dummy ChangeCipherSpec messages from the TLSv1.3 server If the client has requested middle box compatibility mode by sending a non-empty legacy_session_id, the server must send a dummy CCS right after its first handshake message. This means right after ServerHello or HelloRetryRequest. Two important improvements over the backed-out diffr: make sure that First: client and server can send their dummy CCS at the correct moment (right before the next flight or right after the current flight). Second: as jsing noted, we also need to deal with the corner case that tls13_send_dummy_ccs() can return TLS13_IO_WANT_POLLOUT. with/ok jsing --- src/lib/libssl/tls13_handshake.c | 15 ++++++++++++++- src/lib/libssl/tls13_internal.h | 4 +++- src/lib/libssl/tls13_server.c | 25 ++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/lib/libssl/tls13_handshake.c b/src/lib/libssl/tls13_handshake.c index a09659bffc..11fc1db9f9 100644 --- a/src/lib/libssl/tls13_handshake.c +++ b/src/lib/libssl/tls13_handshake.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_handshake.c,v 1.61 2020/05/10 16:56:11 jsing Exp $ */ +/* $OpenBSD: tls13_handshake.c,v 1.62 2020/05/10 17:13:29 tb Exp $ */ /* * Copyright (c) 2018-2019 Theo Buehler * Copyright (c) 2019 Joel Sing @@ -102,6 +102,7 @@ static const struct tls13_handshake_action state_machine[] = { .sender = TLS13_HS_SERVER, .send = tls13_server_hello_retry_request_send, .recv = tls13_server_hello_retry_request_recv, + .sent = tls13_server_hello_retry_request_sent, }, [SERVER_ENCRYPTED_EXTENSIONS] = { .handshake_type = TLS13_MT_ENCRYPTED_EXTENSIONS, @@ -391,6 +392,10 @@ tls13_handshake_send_action(struct tls13_ctx *ctx, if ((ret = tls13_send_dummy_ccs(ctx->rl)) != TLS13_IO_SUCCESS) return ret; ctx->send_dummy_ccs = 0; + if (ctx->send_dummy_ccs_after) { + ctx->send_dummy_ccs_after = 0; + return TLS13_IO_SUCCESS; + } } /* If we have no handshake message, we need to build one. */ @@ -428,6 +433,14 @@ tls13_handshake_send_action(struct tls13_ctx *ctx, if (action->sent != NULL && !action->sent(ctx)) return TLS13_IO_FAILURE; + if (ctx->send_dummy_ccs_after) { + ctx->send_dummy_ccs = 1; + if ((ret = tls13_send_dummy_ccs(ctx->rl)) != TLS13_IO_SUCCESS) + return ret; + ctx->send_dummy_ccs = 0; + ctx->send_dummy_ccs_after = 0; + } + return TLS13_IO_SUCCESS; } diff --git a/src/lib/libssl/tls13_internal.h b/src/lib/libssl/tls13_internal.h index f27f46df52..7ec166f3fa 100644 --- a/src/lib/libssl/tls13_internal.h +++ b/src/lib/libssl/tls13_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_internal.h,v 1.74 2020/05/10 16:59:51 jsing Exp $ */ +/* $OpenBSD: tls13_internal.h,v 1.75 2020/05/10 17:13:30 tb Exp $ */ /* * Copyright (c) 2018 Bob Beck * Copyright (c) 2018 Theo Buehler @@ -253,6 +253,7 @@ struct tls13_ctx { int handshake_completed; int middlebox_compat; int send_dummy_ccs; + int send_dummy_ccs_after; int close_notify_sent; int close_notify_recv; @@ -355,6 +356,7 @@ int tls13_server_hello_send(struct tls13_ctx *ctx, CBB *cbb); int tls13_server_hello_sent(struct tls13_ctx *ctx); int tls13_server_hello_retry_request_recv(struct tls13_ctx *ctx, CBS *cbs); int tls13_server_hello_retry_request_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_hello_retry_request_sent(struct tls13_ctx *ctx); int tls13_server_encrypted_extensions_recv(struct tls13_ctx *ctx, CBS *cbs); int tls13_server_encrypted_extensions_send(struct tls13_ctx *ctx, CBB *cbb); int tls13_server_certificate_recv(struct tls13_ctx *ctx, CBS *cbs); diff --git a/src/lib/libssl/tls13_server.c b/src/lib/libssl/tls13_server.c index f96d054500..9616f392e1 100644 --- a/src/lib/libssl/tls13_server.c +++ b/src/lib/libssl/tls13_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_server.c,v 1.42 2020/05/10 16:59:51 jsing Exp $ */ +/* $OpenBSD: tls13_server.c,v 1.43 2020/05/10 17:13:30 tb Exp $ */ /* * Copyright (c) 2019, 2020 Joel Sing * Copyright (c) 2020 Bob Beck @@ -334,6 +334,20 @@ tls13_server_hello_retry_request_send(struct tls13_ctx *ctx, CBB *cbb) return 1; } +int +tls13_server_hello_retry_request_sent(struct tls13_ctx *ctx) +{ + /* + * If the client has requested middlebox compatibility mode, + * we MUST send a dummy CCS following our first handshake message. + * See RFC 8446 Appendix D.4. + */ + if (ctx->hs->legacy_session_id_len > 0) + ctx->send_dummy_ccs_after = 1; + + return 1; +} + int tls13_client_hello_retry_recv(struct tls13_ctx *ctx, CBS *cbs) { @@ -368,6 +382,15 @@ tls13_server_hello_send(struct tls13_ctx *ctx, CBB *cbb) int tls13_server_hello_sent(struct tls13_ctx *ctx) { + /* + * If the client has requested middlebox compatibility mode, + * we MUST send a dummy CCS following our first handshake message. + * See RFC 8446 Appendix D.4. + */ + if ((ctx->handshake_stage.hs_type & WITHOUT_HRR) && + ctx->hs->legacy_session_id_len > 0) + ctx->send_dummy_ccs_after = 1; + return tls13_server_engage_record_protection(ctx); } -- cgit v1.2.3-55-g6feb