File fix-upstream-CVE-2022-37026.patch of Package erlang.30244
Index: otp-OTP-22.2.7/lib/ssl/src/ssl_connection.erl
===================================================================
--- otp-OTP-22.2.7.orig/lib/ssl/src/ssl_connection.erl
+++ otp-OTP-22.2.7/lib/ssl/src/ssl_connection.erl
@@ -64,7 +64,7 @@
%% General gen_statem state functions with extra callback argument
%% to determine if it is an SSL/TLS or DTLS gen_statem machine
--export([init/4, error/4, hello/4, user_hello/4, abbreviated/4, certify/4, cipher/4,
+-export([init/4, error/4, hello/4, user_hello/4, abbreviated/4, certify/4, wait_cert_verify/4, cipher/4,
connection/4, downgrade/4]).
%% gen_statem callbacks
@@ -976,7 +976,7 @@ certify(internal, #certificate{asn1_cert
ssl_options = #{verify := verify_peer,
fail_if_no_peer_cert := false}} =
State0, Connection) ->
- Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_requested = false});
+ Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_status = empty});
certify(internal, #certificate{},
#state{static_env = #static_env{role = server},
connection_env = #connection_env{negotiated_version = Version},
@@ -992,14 +992,19 @@ certify(internal, #certificate{} = Cert,
cert_db_ref = CertDbRef,
crl_db = CRLDbInfo},
connection_env = #connection_env{negotiated_version = Version},
- ssl_options = Opts} = State, Connection) ->
+ ssl_options = Opts} = State0, Connection) ->
case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef,
Opts, CRLDbInfo, Role, Host) of
{PeerCert, PublicKeyInfo} ->
- handle_peer_cert(Role, PeerCert, PublicKeyInfo,
- State#state{client_certificate_requested = false}, Connection);
+ State = case Role of
+ server ->
+ State0#state{client_certificate_status = needs_verifying};
+ client ->
+ State0
+ end,
+ handle_peer_cert(Role, PeerCert, PublicKeyInfo, State, Connection);
#alert{} = Alert ->
- handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
certify(internal, #server_key_exchange{exchange_keys = Keys},
#state{static_env = #static_env{role = client},
@@ -1065,7 +1070,7 @@ certify(internal, #certificate_request{}
%% The client does not have a certificate and will send an empty reply, the server may fail
%% or accept the connection by its own preference. No signature algorihms needed as there is
%% no certificate to verify.
- Connection:next_event(?FUNCTION_NAME, no_record, State#state{client_certificate_requested = true});
+ Connection:next_event(?FUNCTION_NAME, no_record, State#state{client_certificate_status = requested});
certify(internal, #certificate_request{} = CertRequest,
#state{static_env = #static_env{role = client},
handshake_env = HsEnv,
@@ -1078,7 +1083,7 @@ certify(internal, #certificate_request{}
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State);
NegotiatedHashSign ->
Connection:next_event(?FUNCTION_NAME, no_record,
- State#state{client_certificate_requested = true,
+ State#state{client_certificate_status = requested,
handshake_env = HsEnv#handshake_env{cert_hashsign_algorithm = NegotiatedHashSign}})
end;
%% PSK and RSA_PSK might bypass the Server-Key-Exchange
@@ -1153,13 +1158,6 @@ certify(internal, #server_hello_done{},
#alert{} = Alert ->
handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0)
end;
-certify(internal = Type, #client_key_exchange{} = Msg,
- #state{static_env = #static_env{role = server},
- client_certificate_requested = true,
- ssl_options = #{fail_if_no_peer_cert := true}} = State,
- Connection) ->
- %% We expect a certificate here
- handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection);
certify(internal, #client_key_exchange{exchange_keys = Keys},
State = #state{handshake_env = #handshake_env{kex_algorithm = KeyAlg},
connection_env = #connection_env{negotiated_version = Version}}, Connection) ->
@@ -1203,24 +1201,22 @@ certify(Type, Msg, State, Connection) ->
handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
--spec cipher(gen_statem:event_type(),
- #hello_request{} | #certificate_verify{} | #finished{} | term(),
+-spec wait_cert_verify(gen_statem:event_type(),
+ #hello_request{} | #certificate_verify{} | term(),
#state{}, tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-cipher({call, From}, Msg, State, Connection) ->
- handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
-cipher(info, Msg, State, _) ->
- handle_info(Msg, ?FUNCTION_NAME, State);
-cipher(internal, #certificate_verify{signature = Signature,
- hashsign_algorithm = CertHashSign},
- #state{static_env = #static_env{role = server},
- handshake_env = #handshake_env{tls_handshake_history = Hist,
- kex_algorithm = KexAlg,
- public_key_info = PubKeyInfo} = HsEnv,
- connection_env = #connection_env{negotiated_version = Version},
- session = #session{master_secret = MasterSecret}
- } = State, Connection) ->
+wait_cert_verify(internal, #certificate_verify{signature = Signature,
+ hashsign_algorithm = CertHashSign},
+ #state{static_env = #static_env{role = server,
+ protocol_cb = Connection},
+ client_certificate_status = needs_verifying,
+ handshake_env = #handshake_env{tls_handshake_history = Hist,
+ kex_algorithm = KexAlg,
+ public_key_info = PubKeyInfo},
+ connection_env = #connection_env{negotiated_version = Version},
+ session = #session{master_secret = MasterSecret} = Session0
+ } = State, Connection) ->
TLSVersion = ssl:tls_version(Version),
%% Use negotiated value if TLS-1.2 otherwhise return default
@@ -1228,11 +1224,28 @@ cipher(internal, #certificate_verify{sig
case ssl_handshake:certificate_verify(Signature, PubKeyInfo,
TLSVersion, HashSign, MasterSecret, Hist) of
valid ->
- Connection:next_event(?FUNCTION_NAME, no_record,
- State#state{handshake_env = HsEnv#handshake_env{cert_hashsign_algorithm = HashSign}});
+ Connection:next_event(cipher, no_record,
+ State#state{client_certificate_status = verified,
+ session = Session0#session{sign_alg = HashSign}});
#alert{} = Alert ->
- handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ throw(Alert)
end;
+wait_cert_verify(internal, #hello_request{}, _, _) ->
+ keep_state_and_data;
+wait_cert_verify(Type, Event, State, _) ->
+ ssl_gen_statem:handle_common_event(Type, Event, ?FUNCTION_NAME, State).
+
+%%--------------------------------------------------------------------
+-spec cipher(gen_statem:event_type(),
+ #hello_request{} | #finished{} | term(),
+ #state{}, tls_connection | dtls_connection) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+cipher({call, From}, Msg, State, Connection) ->
+ handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
+cipher(info, Msg, State, _) ->
+ handle_info(Msg, ?FUNCTION_NAME, State);
+
%% client must send a next protocol message if we are expecting it
cipher(internal, #finished{},
#state{static_env = #static_env{role = server},
@@ -1387,10 +1400,6 @@ handle_common_event(internal, {protocol_
Connection:handle_protocol_record(TLSorDTLSRecord, StateName, State);
handle_common_event(timeout, hibernate, _, _, _) ->
{keep_state_and_data, [hibernate]};
-handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
- #state{connection_env = #connection_env{negotiated_version = Version}} = State, _) ->
- handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version,
- StateName, State);
handle_common_event({timeout, handshake}, close, _StateName, #state{start_or_recv_from = StartFrom} = State, _) ->
{stop_and_reply,
{shutdown, user_timeout},
@@ -1839,12 +1848,12 @@ handle_peer_cert_key(_, _, _, _, State)
certify_client(#state{static_env = #static_env{role = client,
cert_db = CertDbHandle,
cert_db_ref = CertDbRef},
- client_certificate_requested = true,
+ client_certificate_status = requested,
session = #session{own_certificate = OwnCert}}
= State, Connection) ->
Certificate = ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, client),
Connection:queue_handshake(Certificate, State);
-certify_client(#state{client_certificate_requested = false} = State, _) ->
+certify_client(#state{client_certificate_status = not_requested} = State, _) ->
State.
verify_client_cert(#state{static_env = #static_env{role = client},
@@ -1852,7 +1861,7 @@ verify_client_cert(#state{static_env = #
cert_hashsign_algorithm = HashSign},
connection_env = #connection_env{negotiated_version = Version,
private_key = PrivateKey},
- client_certificate_requested = true,
+ client_certificate_status = requested,
session = #session{master_secret = MasterSecret,
own_certificate = OwnCert}} = State, Connection) ->
@@ -1865,7 +1874,7 @@ verify_client_cert(#state{static_env = #
#alert{} = Alert ->
throw(Alert)
end;
-verify_client_cert(#state{client_certificate_requested = false} = State, _) ->
+verify_client_cert(#state{client_certificate_status = not_requested} = State, _) ->
State.
client_certify_and_key_exchange(#state{connection_env = #connection_env{negotiated_version = Version}} =
@@ -1875,7 +1884,7 @@ client_certify_and_key_exchange(#state{c
{State2, Actions} = finalize_handshake(State1, certify, Connection),
State = State2#state{
%% Reinitialize
- client_certificate_requested = false},
+ client_certificate_status = not_requested},
Connection:next_event(cipher, no_record, State, Actions)
catch
throw:#alert{} = Alert ->
@@ -1894,7 +1903,8 @@ server_certify_and_key_exchange(State0,
certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS},
#state{connection_env = #connection_env{private_key = Key},
- handshake_env = #handshake_env{client_hello_version = {Major, Minor} = Version}}
+ handshake_env = #handshake_env{client_hello_version = {Major, Minor} = Version},
+ client_certificate_status = CCStatus}
= State, Connection) ->
FakeSecret = make_premaster_secret(Version, rsa),
%% Countermeasure for Bleichenbacher attack always provide some kind of premaster secret
@@ -1914,55 +1924,63 @@ certify_client_key_exchange(#encrypted_p
#alert{description = ?DECRYPT_ERROR} ->
FakeSecret
end,
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey},
#state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
- kex_keys = {_, ServerDhPrivateKey}}
- } = State,
+ kex_keys = {_, ServerDhPrivateKey}},
+ client_certificate_status = CCStatus} = State,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientPublicDhKey, ServerDhPrivateKey, Params),
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_ec_diffie_hellman_public{dh_public = ClientPublicEcDhPoint},
- #state{handshake_env = #handshake_env{kex_keys = ECDHKey}} = State, Connection) ->
+ #state{handshake_env = #handshake_env{kex_keys = ECDHKey}, client_certificate_status = CCStatus} = State, Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(#'ECPoint'{point = ClientPublicEcDhPoint}, ECDHKey),
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_psk_identity{} = ClientKey,
#state{ssl_options =
- #{user_lookup_fun := PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup}, client_certificate_status = CCStatus} = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, PSKLookup),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey,
#state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params,
kex_keys = {_, ServerDhPrivateKey}},
ssl_options =
- #{user_lookup_fun := PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup}, client_certificate_status = CCStatus} = State0,
Connection) ->
PremasterSecret =
ssl_handshake:premaster_secret(ClientKey, ServerDhPrivateKey, Params, PSKLookup),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_certificate_status = CCStatus);
certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey,
#state{handshake_env = #handshake_env{kex_keys = ServerEcDhPrivateKey},
ssl_options =
- #{user_lookup_fun := PSKLookup}} = State,
+ #{user_lookup_fun := PSKLookup}, client_certificate_status = CCStatus} = State,
Connection) ->
PremasterSecret =
ssl_handshake:premaster_secret(ClientKey, ServerEcDhPrivateKey, PSKLookup),
- calculate_master_secret(PremasterSecret, State, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_rsa_psk_identity{} = ClientKey,
#state{connection_env = #connection_env{private_key = Key},
ssl_options =
- #{user_lookup_fun := PSKLookup}} = State0,
+ #{user_lookup_fun := PSKLookup}, client_certificate_status = CCStatus} = State0,
Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, PSKLookup),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher);
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_kex_next_state(CCStatus));
certify_client_key_exchange(#client_srp_public{} = ClientKey,
#state{handshake_env = #handshake_env{srp_params = Params,
- kex_keys = Key}
+ kex_keys = Key},
+ client_certificate_status = CCStatus
} = State0, Connection) ->
PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, Params),
- calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher).
+ calculate_master_secret(PremasterSecret, State0, Connection, certify, client_kex_next_state(CCStatus)).
+
+client_kex_next_state(needs_verifying) ->
+ wait_cert_verify;
+client_kex_next_state(empty) ->
+ cipher;
+client_kex_next_state(not_requested) ->
+ cipher.
certify_server(#state{handshake_env = #handshake_env{kex_algorithm = KexAlg}} =
State, _) when KexAlg == dh_anon;
@@ -2295,7 +2313,7 @@ request_client_cert(#state{static_env =
Msg = ssl_handshake:certificate_request(CipherSuite, CertDbHandle, CertDbRef,
HashSigns, TLSVersion),
State = Connection:queue_handshake(Msg, State0),
- State#state{client_certificate_requested = true};
+ State#state{client_certificate_status = requested};
request_client_cert(#state{ssl_options = #{verify := verify_none}} =
State, _) ->
Index: otp-OTP-22.2.7/lib/ssl/src/ssl_connection.hrl
===================================================================
--- otp-OTP-22.2.7.orig/lib/ssl/src/ssl_connection.hrl
+++ otp-OTP-22.2.7/lib/ssl/src/ssl_connection.hrl
@@ -109,7 +109,7 @@
%% need to worry about packet loss in TLS. In DTLS we
%% need to track DTLS handshake seqnr
flight_buffer = [] :: list() | map(),
- client_certificate_requested = false :: boolean(),
+ client_certificate_status = not_requested :: not_requested | requested | empty | needs_verifying | verified,
protocol_specific = #{} :: map(),
session :: #session{} | secret_printout(),
key_share,
@@ -141,8 +141,8 @@
%% session_cache_cb - not implemented
%% crl_db - not implemented
%% client_hello_version - Bleichenbacher mitigation in TLS 1.2
-%% client_certificate_requested - Built into TLS 1.3 state machine
-%% key_algorithm - not used
+%% client_certificate_status - Built into TLS 1.3 state machine
+%% key_algorithm - only uses not_requested and requested
%% diffie_hellman_params - used in TLS 1.2 ECDH key exchange
%% diffie_hellman_keys - used in TLS 1.2 ECDH key exchange
%% psk_identity - not used
Index: otp-OTP-22.2.7/lib/ssl/src/tls_handshake_1_3.erl
===================================================================
--- otp-OTP-22.2.7.orig/lib/ssl/src/tls_handshake_1_3.erl
+++ otp-OTP-22.2.7/lib/ssl/src/tls_handshake_1_3.erl
@@ -1045,7 +1045,7 @@ handle_resumption(#state{handshake_env =
State#state{handshake_env = HSEnv}.
-maybe_queue_cert_cert_cv(#state{client_certificate_requested = false} = State) ->
+maybe_queue_cert_cert_cv(#state{client_certificate_status = not_requested} = State) ->
{ok, State};
maybe_queue_cert_cert_cv(#state{connection_states = _ConnectionStates0,
session = #session{session_id = _SessionId,
@@ -1204,7 +1204,7 @@ maybe_send_session_ticket(#state{connect
process_certificate_request(#certificate_request_1_3{},
#state{session = #session{own_certificate = undefined}} = State) ->
- {ok, {State#state{client_certificate_requested = true}, wait_cert}};
+ {ok, {State#state{client_certificate_status = requested}, wait_cert}};
process_certificate_request(#certificate_request_1_3{
extensions = Extensions},
@@ -1219,10 +1219,10 @@ process_certificate_request(#certificate
%% Check if server supports signature algorithm of client certificate
case check_cert_sign_algo(SignAlgo, SignHash, ServerSignAlgs, ServerSignAlgsCert) of
ok ->
- {ok, {State#state{client_certificate_requested = true}, wait_cert}};
+ {ok, {State#state{client_certificate_status = requested}, wait_cert}};
{error, _} ->
%% Certificate not supported: send empty certificate in state 'wait_finished'
- {ok, {State#state{client_certificate_requested = true,
+ {ok, {State#state{client_certificate_status = requested,
session = Session#session{own_certificate = undefined}}, wait_cert}}
end.
Index: otp-OTP-22.2.7/lib/ssl/src/tls_connection.erl
===================================================================
--- otp-OTP-22.2.7.orig/lib/ssl/src/tls_connection.erl
+++ otp-OTP-22.2.7/lib/ssl/src/tls_connection.erl
@@ -67,7 +67,7 @@
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
- hello/3, user_hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
+ hello/3, user_hello/3, certify/3, wait_cert_verify/3, cipher/3, abbreviated/3, %% Handshake states
connection/3]).
%% TLS 1.3 state functions (server)
-export([start/3, %% common state with client
@@ -304,7 +304,28 @@ next_event(StateName, #alert{} = Alert,
{next_state, StateName, State, [{next_event, internal, Alert} | Actions]}.
%%% TLS record protocol level application data messages
-handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName,
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA}, StateName,
+ #state{static_env = #static_env{role = server},
+ connection_env = #connection_env{negotiated_version = Version},
+ handshake_env = #handshake_env{renegotiation = {false, first}}
+ } = State) when StateName == initial_hello;
+ StateName == hello;
+ StateName == certify;
+ StateName == wait_cert_verify;
+ StateName == wait_ocsp_stapling;
+ StateName == abbreviated;
+ StateName == cipher
+ ->
+ %% Application data can not be sent before initial handshake pre TLS-1.3.
+ Alert = ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE, application_data_before_initial_handshake),
+ ssl_gen_statem:handle_own_alert(Alert, Version, StateName, State);
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA}, start = StateName,
+ #state{static_env = #static_env{role = server},
+ connection_env = #connection_env{negotiated_version = Version}
+ } = State) ->
+ Alert = ?ALERT_REC(?FATAL, ?DECODE_ERROR, invalid_tls_13_message),
+ ssl_gen_statem:handle_own_alert(Alert, Version, StateName, State);
+handle_protocol_record(#ssl_tls{type = ?APPLICATION_DATA, fragment = Data}, StateName,
#state{start_or_recv_from = From,
socket_options = #socket_options{active = false}} = State0) when From =/= undefined ->
case ssl_connection:read_application_data(Data, State0) of
@@ -793,6 +814,18 @@ certify(Type, Event, State) ->
gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
+-spec wait_cert_verify(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_cert_verify(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_cert_verify(Type, Event, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
+ try gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ end.
+
+%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
Index: otp-OTP-22.2.7/lib/ssl/src/dtls_connection.erl
===================================================================
--- otp-OTP-22.2.7.orig/lib/ssl/src/dtls_connection.erl
+++ otp-OTP-22.2.7/lib/ssl/src/dtls_connection.erl
@@ -55,7 +55,7 @@
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
- hello/3, user_hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
+ hello/3, user_hello/3, certify/3, wait_cert_verify/3, cipher/3, abbreviated/3, %% Handshake states
connection/3]).
%% gen_statem callbacks
-export([callback_mode/0, terminate/3, code_change/4, format_status/2]).
@@ -658,6 +658,23 @@ certify(Type, Event, State) ->
gen_handshake(?FUNCTION_NAME, Type, Event, State).
%%--------------------------------------------------------------------
+-spec wait_cert_verify(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_cert_verify(enter, _Event, State0) ->
+ {State, Actions} = handle_flight_timer(State0),
+ {keep_state, State, Actions};
+wait_cert_verify(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_cert_verify(state_timeout, Event, State) ->
+ handle_state_timeout(Event, ?FUNCTION_NAME, State);
+wait_cert_verify(Type, Event, #state{connection_env = #connection_env{negotiated_version = Version}} = State) ->
+ try gen_handshake(?FUNCTION_NAME, Type, Event, State)
+ catch throw:#alert{} = Alert ->
+ ssl_gen_statem:handle_own_alert(Alert, Version, ?FUNCTION_NAME, State)
+ end.
+
+%%--------------------------------------------------------------------
-spec cipher(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------