%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2007-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% %% %%---------------------------------------------------------------------- %% Purpose: TODO %%---------------------------------------------------------------------- %% RFC 8446 %% A.1. Client %% %% START <----+ %% Send ClientHello | | Recv HelloRetryRequest %% [K_send = early data] | | %% v | %% / WAIT_SH ----+ %% | | Recv ServerHello %% | | K_recv = handshake %% Can | V %% send | WAIT_EE %% early | | Recv EncryptedExtensions %% data | +--------+--------+ %% | Using | | Using certificate %% | PSK | v %% | | WAIT_CERT_CR %% | | Recv | | Recv CertificateRequest %% | | Certificate | v %% | | | WAIT_CERT %% | | | | Recv Certificate %% | | v v %% | | WAIT_CV %% | | | Recv CertificateVerify %% | +> WAIT_FINISHED <+ %% | | Recv Finished %% \ | [Send EndOfEarlyData] %% | K_send = handshake %% | [Send Certificate [+ CertificateVerify]] %% Can send | Send Finished %% app data --> | K_send = K_recv = application %% after here v %% CONNECTED %% %% A.2. Server %% %% START <-----+ %% Recv ClientHello | | Send HelloRetryRequest %% v | %% RECVD_CH ----+ %% | Select parameters %% v %% NEGOTIATED %% | Send ServerHello %% | K_send = handshake %% | Send EncryptedExtensions %% | [Send CertificateRequest] %% Can send | [Send Certificate + CertificateVerify] %% app data | Send Finished %% after --> | K_send = application %% here +--------+--------+ %% No 0-RTT | | 0-RTT %% | | %% K_recv = handshake | | K_recv = early data %% [Skip decrypt errors] | +------> WAIT_EOED -+ %% | | Recv | | Recv EndOfEarlyData %% | | early data | | K_recv = handshake %% | +------------+ | %% | | %% +> WAIT_FLIGHT2 <--------+ %% | %% +--------+--------+ %% No auth | | Client auth %% | | %% | v %% | WAIT_CERT %% | Recv | | Recv Certificate %% | empty | v %% | Certificate | WAIT_CV %% | | | Recv %% | v | CertificateVerify %% +-> WAIT_FINISHED <---+ %% | Recv Finished %% | K_recv = application %% v %% CONNECTED -module(tls_connection_1_3). -include("ssl_alert.hrl"). -include("ssl_connection.hrl"). -export([hello/4]). -export([gen_handshake/4]). hello(internal, {common_client_hello, Type, ServerHelloExt}, State, Connection) -> do_server_hello(Type, ServerHelloExt, State, Connection). do_server_hello(Type, #{next_protocol_negotiation := _NextProtocols} = _ServerHelloExt, #state{negotiated_version = _Version, session = #session{session_id = _SessId}, connection_states = _ConnectionStates0, ssl_options = #ssl_options{versions = [_HighestVersion|_]}} = State0, _Connection) when is_atom(Type) -> %% NEGOTIATED %% | Send ServerHello %% | K_send = handshake %% | Send EncryptedExtensions %% | [Send CertificateRequest] %% Can send | [Send Certificate + CertificateVerify] %% app data | Send Finished %% after --> | K_send = application %% here +--------+--------+ %% No 0-RTT | | 0-RTT %% | | %% K_recv = handshake | | K_recv = early data %% [Skip decrypt errors] | +------> WAIT_EOED -+ %% | | Recv | | Recv EndOfEarlyData %% | | early data | | K_recv = handshake %% | +------------+ | %% | | %% +> WAIT_FLIGHT2 <--------+ %% Will be called implicitly %% {Record, State} = Connection:next_record(State2#state{session = Session}), %% Connection:next_event(wait_flight2, Record, State, Actions), %% OR %% Connection:next_event(WAIT_EOED, Record, State, Actions) {next_state, wait_flight2, State0, []}. %% TODO: Add new states to tls_connection! %% State0. gen_handshake(StateName, Type, Event, #state{negotiated_version = Version} = State) -> try tls_connection_1_3:StateName(Type, Event, State, ?MODULE) of Result -> Result catch _:_ -> ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, malformed_handshake_data), Version, StateName, State) end.