aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/dtls_connection.erl
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2013-09-10 09:52:45 +0200
committerIngela Anderton Andin <[email protected]>2013-09-10 09:52:45 +0200
commit23de86802028de4e1dd2fe8169d4f448c0ac72bc (patch)
treeb2291b45246bdfdcea7e3c9872246ee5bb98e88c /lib/ssl/src/dtls_connection.erl
parent04a107f23732fda1a95d6194fb6395e1c94fc534 (diff)
parent754b87eb181552d67c61c9a80c31ce52e4b39f19 (diff)
downloadotp-23de86802028de4e1dd2fe8169d4f448c0ac72bc.tar.gz
otp-23de86802028de4e1dd2fe8169d4f448c0ac72bc.tar.bz2
otp-23de86802028de4e1dd2fe8169d4f448c0ac72bc.zip
Merge branch 'ia/ssl/dtls-refactor/OTP-11292' into maint
* ia/ssl/dtls-refactor/OTP-11292: ssl: Refactor TLS/DTLS record handling ssl: Dialyzer fixes ssl: Solve rebase issues ssl: DTLS record handling ssl: Add DTLS record primitives ssl: Refactor to provide common handshake functions for TLS/DTLS ssl: Add DTLS handshake primitivs.
Diffstat (limited to 'lib/ssl/src/dtls_connection.erl')
-rw-r--r--lib/ssl/src/dtls_connection.erl322
1 files changed, 322 insertions, 0 deletions
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index ac2ee0d09f..fda488501c 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -17,3 +17,325 @@
%% %CopyrightEnd%
%%
-module(dtls_connection).
+
+%%-behaviour(gen_fsm).
+
+%% -include("dtls_handshake.hrl").
+%% -include("ssl_alert.hrl").
+%% -include("dtls_record.hrl").
+%% -include("ssl_cipher.hrl").
+%% -include("ssl_internal.hrl").
+%% -include("ssl_srp.hrl").
+%% -include_lib("public_key/include/public_key.hrl").
+
+
+%% %% Called by dtls_connection_sup
+%% %%-export([start_link/7]).
+
+%% %% gen_fsm callbacks
+%% -export([init/1, hello/2, certify/2, cipher/2,
+%% abbreviated/2, connection/2, handle_event/3,
+%% handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
+
+%% -record(message_sequences, {
+%% read = 0,
+%% write = 0
+%% }).
+
+%% -record(state, {
+%% role, % client | server
+%% user_application, % {MonitorRef, pid()}
+%% transport_cb, % atom() - callback module
+%% data_tag, % atom() - ex tcp.
+%% close_tag, % atom() - ex tcp_closed
+%% error_tag, % atom() - ex tcp_error
+%% host, % string() | ipadress()
+%% port, % integer()
+%% socket, % socket()
+%% ssl_options, % #ssl_options{}
+%% socket_options, % #socket_options{}
+%% connection_states, % #connection_states{} from ssl_record.hrl
+%% message_sequences = #message_sequences{},
+%% dtls_packets = [], % Not yet handled decode ssl/tls packets.
+%% dtls_record_buffer, % binary() buffer of incomplete records
+%% dtls_handshake_buffer, % binary() buffer of incomplete handshakes
+%% dtls_handshake_history, % tls_handshake_history()
+%% dtls_cipher_texts, % list() received but not deciphered yet
+%% cert_db, %
+%% session, % #session{} from tls_handshake.hrl
+%% session_cache, %
+%% session_cache_cb, %
+%% negotiated_version, % tls_version()
+%% client_certificate_requested = false,
+%% key_algorithm, % atom as defined by cipher_suite
+%% hashsign_algorithm, % atom as defined by cipher_suite
+%% public_key_info, % PKIX: {Algorithm, PublicKey, PublicKeyParams}
+%% private_key, % PKIX: #'RSAPrivateKey'{}
+%% diffie_hellman_params, % PKIX: #'DHParameter'{} relevant for server side
+%% diffie_hellman_keys, % {PublicKey, PrivateKey}
+%% psk_identity, % binary() - server psk identity hint
+%% srp_params, % #srp_user{}
+%% srp_keys, % {PublicKey, PrivateKey}
+%% premaster_secret, %
+%% file_ref_db, % ets()
+%% cert_db_ref, % ref()
+%% bytes_to_read, % integer(), # bytes to read in passive mode
+%% user_data_buffer, % binary()
+%% log_alert, % boolean()
+%% renegotiation, % {boolean(), From | internal | peer}
+%% start_or_recv_from, % "gen_fsm From"
+%% timer, % start_or_recv_timer
+%% send_queue, % queue()
+%% terminated = false, %
+%% allow_renegotiate = true,
+%% expecting_next_protocol_negotiation = false :: boolean(),
+%% next_protocol = undefined :: undefined | binary(),
+%% client_ecc, % {Curves, PointFmt}
+%% client_cookie = <<>>
+%% }).
+
+
+
+%% %%====================================================================
+%% %% Internal application API
+%% %%====================================================================
+
+
+%% %%====================================================================
+%% %% State functions
+%% %%====================================================================
+
+%% -spec hello(start | #hello_request{} | #client_hello{} | #server_hello{} | term(),
+%% #state{}) -> gen_fsm_state_return().
+%% %%--------------------------------------------------------------------
+%% hello(start, #state{host = Host, port = Port, role = client,
+%% ssl_options = SslOpts,
+%% session = #session{own_certificate = Cert} = Session0,
+%% session_cache = Cache, session_cache_cb = CacheCb,
+%% connection_states = ConnectionStates0,
+%% renegotiation = {Renegotiation, _},
+%% client_cookie = Cookie} = State0) ->
+%% Hello = dtls_handshake:client_hello(Host, Port, Cookie, ConnectionStates0, SslOpts,
+%% Cache, CacheCb, Renegotiation, Cert),
+
+%% Version = Hello#client_hello.client_version,
+%% State1 = State0#state{negotiated_version = Version, %% Requested version
+%% session =
+%% Session0#session{session_id = Hello#client_hello.session_id},
+%% dtls_handshake_history = ssl_handshake:init_handshake_history()},
+
+%% State2 = send_flight(Hello, waiting, State1),
+
+%% {Record, State} = next_record(State2),
+%% next_state(hello, hello, Record, State);
+
+%% hello(start, #state{role = server} = State0) ->
+%% {Record, State} = next_record(State0),
+%% next_state(hello, hello, Record, State);
+
+%% hello(#hello_request{}, #state{role = client} = State0) ->
+%% {Record, State} = next_record(State0),
+%% next_state(hello, hello, Record, State);
+
+%% hello(#server_hello{cipher_suite = CipherSuite,
+%% compression_method = Compression} = Hello,
+%% #state{session = #session{session_id = OldId},
+%% connection_states = ConnectionStates0,
+%% role = client,
+%% negotiated_version = ReqVersion,
+%% renegotiation = {Renegotiation, _},
+%% ssl_options = SslOptions} = State1) ->
+%% State0 = flight_done(State1),
+%% case ssl_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of
+%% #alert{} = Alert ->
+%% handle_own_alert(Alert, ReqVersion, hello, State0);
+%% {Version, NewId, ConnectionStates, NextProtocol} ->
+%% {KeyAlgorithm, _, _, _} =
+%% ssl_cipher:suite_definition(CipherSuite),
+
+%% PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
+
+%% NewNextProtocol = case NextProtocol of
+%% undefined ->
+%% State0#state.next_protocol;
+%% _ ->
+%% NextProtocol
+%% end,
+
+%% State = State0#state{key_algorithm = KeyAlgorithm,
+%% hashsign_algorithm = default_hashsign(Version, KeyAlgorithm),
+%% negotiated_version = Version,
+%% connection_states = ConnectionStates,
+%% premaster_secret = PremasterSecret,
+%% expecting_next_protocol_negotiation = NextProtocol =/= undefined,
+%% next_protocol = NewNextProtocol},
+
+%% case ssl_session:is_new(OldId, NewId) of
+%% true ->
+%% handle_new_session(NewId, CipherSuite, Compression,
+%% State#state{connection_states = ConnectionStates});
+%% false ->
+%% handle_resumed_session(NewId, State#state{connection_states = ConnectionStates})
+%% end
+%% end;
+
+%% hello(#hello_verify_request{cookie = Cookie},
+%% #state{host = Host, port = Port,
+%% session = #session{own_certificate = Cert},
+%% session_cache = Cache, session_cache_cb = CacheCb,
+%% ssl_options = SslOpts,
+%% connection_states = ConnectionStates0,
+%% renegotiation = {Renegotiation, _}} = State0) ->
+%% Hello = ssl_handshake:client_hello(Host, Port, Cookie, ConnectionStates0, SslOpts,
+%% Cache, CacheCb, Renegotiation, Cert),
+%% State1 = State0#state{
+%% tls_handshake_history = ssl_handshake:init_handshake_history(),
+%% client_cookie = Cookie},
+%% State2 = send_flight(Hello, waiting, State1),
+
+%% {Record, State} = next_record(State2),
+%% next_state(hello, hello, Record, State);
+
+%% hello(Hello = #client_hello{client_version = ClientVersion},
+%% State = #state{connection_states = ConnectionStates0,
+%% port = Port, session = #session{own_certificate = Cert} = Session0,
+%% renegotiation = {Renegotiation, _},
+%% session_cache = Cache,
+%% session_cache_cb = CacheCb,
+%% ssl_options = SslOpts}) ->
+%% case ssl_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb,
+%% ConnectionStates0, Cert}, Renegotiation) of
+%% {Version, {Type, Session}, ConnectionStates, ProtocolsToAdvertise,
+%% EcPointFormats, EllipticCurves} ->
+%% do_server_hello(Type, ProtocolsToAdvertise,
+%% EcPointFormats, EllipticCurves,
+%% State#state{connection_states = ConnectionStates,
+%% negotiated_version = Version,
+%% session = Session,
+%% client_ecc = {EllipticCurves, EcPointFormats}});
+%% #alert{} = Alert ->
+%% handle_own_alert(Alert, ClientVersion, hello, State)
+%% end;
+
+%% hello(timeout, State) ->
+%% { next_state, hello, State, hibernate };
+
+%% hello(Msg, State) ->
+%% handle_unexpected_message(Msg, hello, State).
+%% %%--------------------------------------------------------------------
+%% -spec abbreviated(#hello_request{} | #finished{} | term(),
+%% #state{}) -> gen_fsm_state_return().
+%% %%--------------------------------------------------------------------
+
+%% abbreviated(timeout, State) ->
+%% { next_state, abbreviated, State, hibernate };
+
+%% abbreviated(Msg, State) ->
+%% handle_unexpected_message(Msg, abbreviated, State).
+
+%% %%--------------------------------------------------------------------
+%% -spec certify(#hello_request{} | #certificate{} | #server_key_exchange{} |
+%% #certificate_request{} | #server_hello_done{} | #client_key_exchange{} | term(),
+%% #state{}) -> gen_fsm_state_return().
+%% %%--------------------------------------------------------------------
+
+
+%% certify(timeout, State) ->
+%% { next_state, certify, State, hibernate };
+
+%% certify(Msg, State) ->
+%% handle_unexpected_message(Msg, certify, State).
+
+
+%% %%--------------------------------------------------------------------
+%% -spec cipher(#hello_request{} | #certificate_verify{} | #finished{} | term(),
+%% #state{}) -> gen_fsm_state_return().
+%% %%--------------------------------------------------------------------
+
+%% cipher(timeout, State) ->
+%% { next_state, cipher, State, hibernate };
+
+%% cipher(Msg, State) ->
+%% handle_unexpected_message(Msg, cipher, State).
+
+%% %%--------------------------------------------------------------------
+%% -spec connection(#hello_request{} | #client_hello{} | term(),
+%% #state{}) -> gen_fsm_state_return().
+%% %%--------------------------------------------------------------------
+
+%% connection(timeout, State) ->
+%% {next_state, connection, State, hibernate};
+
+%% connection(Msg, State) ->
+%% handle_unexpected_message(Msg, connection, State).
+
+%% %%--------------------------------------------------------------------
+%% %%% Internal functions
+%% %%--------------------------------------------------------------------
+%% handle_unexpected_message(Msg, Info, #state{negotiated_version = Version} = State) ->
+%% Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE),
+%% handle_own_alert(Alert, Version, {Info, Msg}, State).
+
+%% send_flight(HandshakeRec, FlightState, State) ->
+%% send_flight(FlightState, buffer_flight(HandshakeRec, State)).
+
+%% send_flight(FlightState, State = #state{negotiated_version = Version,
+%% flight_buffer = Buffer}) ->
+
+%% State1 = do_send_flight(queue:to_list(Buffer), [], State),
+%% finish_send_flight(Version, FlightState, State1).
+
+%% resend_flight(State = #state{negotiated_version = Version,
+%% flight_state = FlightState,
+%% flight_buffer = Buffer})
+%% when FlightState == finished; FlightState == waiting ->
+%% State1 = do_send_flight(queue:to_list(Buffer), [], State),
+%% finish_send_flight(Version, FlightState, State1);
+
+%% resend_flight(State) ->
+%% State.
+
+%% flight_done(State) ->
+%% cancel_dtls_retransmit_timer(State#state{flight_state = done,
+%% flight_buffer = undefined}).
+
+%% do_send_flight([], BinMsgs, State = #state{transport_cb = Transport, socket = Socket}) ->
+%% Transport:send(Socket, lists:reverse(BinMsgs)),
+%% State;
+%% do_send_flight([{Epoch, MsgSeq, HandshakeRec}|T], BinMsgs0,
+%% State = #state{negotiated_version = Version,
+%% connection_states = ConnectionStates0}) ->
+%% CS0 = ssl_record:connection_state_by_epoch(ConnectionStates0, Epoch, write),
+%% {BinMsgs, CS1} = encode_handshake_rec(HandshakeRec, Version, MsgSeq, BinMsgs0, CS0),
+%% ConnectionStates1 = ssl_record:set_connection_state_by_epoch(ConnectionStates0, CS1, write),
+%% do_send_flight(T, BinMsgs, State#state{connection_states = ConnectionStates1}).
+
+%% cancel_dtls_retransmit_timer(State = #state{dtls_retransmit_timer = TimerRef}) ->
+%% cancel_timer(TimerRef),
+%% State#state{dtls_retransmit_timer = undefined}.
+
+%% rearm_dtls_retransmit_timer(State = #state{dtls_retransmit_timer = undefined}) ->
+%% TimerRef = erlang:start_timer(1000, self(), dtls_retransmit),
+%% State#state{dtls_retransmit_timer = TimerRef};
+%% rearm_dtls_retransmit_timer(State) ->
+%% State.
+
+%% finish_send_flight({254, _}, waiting, State) ->
+%% TimerRef = erlang:start_timer(1000, self(), dtls_retransmit),
+%% State#state{
+%% dtls_retransmit_timer = TimerRef,
+%% last_retransmit = timestamp(),
+%% flight_state = waiting};
+
+%% finish_send_flight(_, FlightState, State) ->
+%% State#state{flight_state = FlightState}.
+
+%% timestamp() ->
+%% {Mega, Sec, Micro} = erlang:now(),
+%% Mega * 1000000 * 1000 + Sec * 1000 + (Micro div 1000).
+
+%% encode_handshake_rec(HandshakeRec, Version, MsgSeq, BinMsgs0, CS0) ->
+%% {_, Fragments} = ssl_handshake:encode_handshake(HandshakeRec, Version, MsgSeq, 1400),
+%% lists:foldl(fun(F, {Bin, C0}) ->
+%% {B, C1} = ssl_record:encode_handshake(F, Version, C0),
+%% {[B|Bin], C1} end, {BinMsgs0, CS0}, Fragments).