1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2013-2019. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19
20%%
21%%----------------------------------------------------------------------
22%% Purpose: Handle DTLS record protocol. (Parts that are not shared with SSL/TLS)
23%%----------------------------------------------------------------------
24-module(dtls_record).
25
26-include("dtls_record.hrl").
27-include("ssl_internal.hrl").
28-include("ssl_alert.hrl").
29-include("dtls_handshake.hrl").
30-include("ssl_cipher.hrl").
31
32%% Handling of incoming data
33-export([get_dtls_records/4,  init_connection_states/2, empty_connection_state/1]).
34
35-export([save_current_connection_state/2, next_epoch/2, get_connection_state_by_epoch/3, replay_detect/2,
36         init_connection_state_seq/2, current_connection_state_epoch/2]).
37
38%% Encoding
39-export([encode_handshake/4, encode_alert_record/3,
40	 encode_change_cipher_spec/3, encode_data/3, encode_plain_text/5]).
41
42%% Decoding
43-export([decode_cipher_text/2]).
44
45%% Protocol version handling
46-export([protocol_version/1, lowest_protocol_version/1, lowest_protocol_version/2,
47	 highest_protocol_version/1, highest_protocol_version/2,
48	 is_higher/2, supported_protocol_versions/0,
49	 is_acceptable_version/2, hello_version/2]).
50
51%% Debug (whitebox testing)
52-export([init_replay_window/0, is_replay/2, update_replay_window/2]).
53
54
55-export_type([dtls_atom_version/0]).
56
57-type dtls_atom_version()  :: dtlsv1 | 'dtlsv1.2'.
58
59-define(REPLAY_WINDOW_SIZE, 58).  %% No bignums
60
61-compile(inline).
62
63%%====================================================================
64%%  Handling of incoming data
65%%====================================================================
66%%--------------------------------------------------------------------
67-spec init_connection_states(client | server, one_n_minus_one | zero_n | disabled) ->
68 				    ssl_record:connection_states().
69%% %
70						%
71%% Description: Creates a connection_states record with appropriate
72%% values for the initial SSL connection setup.
73%%--------------------------------------------------------------------
74init_connection_states(Role, BeastMitigation) ->
75    ConnectionEnd = ssl_record:record_protocol_role(Role),
76    Initial = initial_connection_state(ConnectionEnd, BeastMitigation),
77    Current = Initial#{epoch := 0},
78    InitialPending = ssl_record:empty_connection_state(ConnectionEnd, BeastMitigation),
79    Pending = empty_connection_state(InitialPending),
80    #{saved_read  => Current,
81      current_read  => Current,
82      pending_read  => Pending,
83      saved_write => Current,
84      current_write => Current,
85      pending_write => Pending}.
86
87empty_connection_state(Empty) ->
88    Empty#{epoch => undefined, replay_window => init_replay_window()}.
89
90%%--------------------------------------------------------------------
91-spec save_current_connection_state(ssl_record:connection_states(), read | write) ->
92				      ssl_record:connection_states().
93%%
94%% Description: Returns the instance of the connection_state map
95%% where the current read|write state has been copied to the save state.
96%%--------------------------------------------------------------------
97save_current_connection_state(#{current_read := Current} = States, read) ->
98    States#{saved_read := Current};
99
100save_current_connection_state(#{current_write := Current} = States, write) ->
101    States#{saved_write := Current}.
102
103next_epoch(#{pending_read := Pending,
104	     current_read := #{epoch := Epoch}} = States, read) ->
105    States#{pending_read := Pending#{epoch := Epoch + 1,
106                                     replay_window := init_replay_window()}};
107
108next_epoch(#{pending_write := Pending,
109	     current_write := #{epoch := Epoch}} = States, write) ->
110    States#{pending_write := Pending#{epoch := Epoch + 1,
111                                      replay_window := init_replay_window()}}.
112
113get_connection_state_by_epoch(Epoch, #{current_write := #{epoch := Epoch} = Current},
114			      write) ->
115    Current;
116get_connection_state_by_epoch(Epoch, #{saved_write := #{epoch := Epoch} = Saved},
117			      write) ->
118    Saved;
119get_connection_state_by_epoch(Epoch, #{current_read := #{epoch := Epoch} = Current},
120			      read) ->
121    Current;
122get_connection_state_by_epoch(Epoch, #{saved_read := #{epoch := Epoch} = Saved},
123			      read) ->
124    Saved.
125
126set_connection_state_by_epoch(WriteState, Epoch, #{current_write := #{epoch := Epoch}} = States,
127			      write) ->
128    States#{current_write := WriteState};
129set_connection_state_by_epoch(WriteState, Epoch, #{saved_write := #{epoch := Epoch}} = States,
130			      write) ->
131    States#{saved_write := WriteState};
132set_connection_state_by_epoch(ReadState, Epoch, #{current_read := #{epoch := Epoch}} = States,
133			      read) ->
134    States#{current_read := ReadState};
135set_connection_state_by_epoch(ReadState, Epoch, #{saved_read := #{epoch := Epoch}} = States,
136			      read) ->
137    States#{saved_read := ReadState}.
138
139%%--------------------------------------------------------------------
140-spec init_connection_state_seq(ssl_record:ssl_version(), ssl_record:connection_states()) ->
141				       ssl_record:connection_state().
142%%
143%% Description: Copy the read sequence number to the write sequence number
144%% This is only valid for DTLS in the first client_hello
145%%--------------------------------------------------------------------
146init_connection_state_seq({254, _},
147			  #{current_read := #{epoch := 0, sequence_number := Seq},
148			    current_write := #{epoch := 0} = Write} = ConnnectionStates0) ->
149    ConnnectionStates0#{current_write => Write#{sequence_number => Seq}};
150init_connection_state_seq(_, ConnnectionStates) ->
151    ConnnectionStates.
152
153%%--------------------------------------------------------
154-spec current_connection_state_epoch(ssl_record:connection_states(), read | write) ->
155					    integer().
156%%
157%% Description: Returns the epoch the connection_state record
158%% that is currently defined as the current connection state.
159%%--------------------------------------------------------------------
160current_connection_state_epoch(#{current_read := #{epoch := Epoch}},
161			       read) ->
162    Epoch;
163current_connection_state_epoch(#{current_write := #{epoch := Epoch}},
164			       write) ->
165    Epoch.
166
167%%--------------------------------------------------------------------
168-spec get_dtls_records(binary(), {atom(), atom(), ssl_record:ssl_version(), [ssl_record:ssl_version()]}, binary(),
169                       ssl_options()) -> {[binary()], binary()} | #alert{}.
170%%
171%% Description: Given old buffer and new data from UDP/SCTP, packs up a records
172%% and returns it as a list of tls_compressed binaries also returns leftover
173%% data
174%%--------------------------------------------------------------------
175get_dtls_records(Data, Vinfo, Buffer, SslOpts) ->
176    BinData = list_to_binary([Buffer, Data]),
177    get_dtls_records_aux(Vinfo, BinData, [], SslOpts).
178
179%%====================================================================
180%% Encoding DTLS records
181%%====================================================================
182
183%%--------------------------------------------------------------------
184-spec encode_handshake(iolist(), ssl_record:ssl_version(), integer(), ssl_record:connection_states()) ->
185			      {iolist(), ssl_record:connection_states()}.
186%
187%% Description: Encodes a handshake message to send on the ssl-socket.
188%%--------------------------------------------------------------------
189encode_handshake(Frag, Version, Epoch, ConnectionStates) ->
190    encode_plain_text(?HANDSHAKE, Version, Epoch, Frag, ConnectionStates).
191
192
193%%--------------------------------------------------------------------
194-spec encode_alert_record(#alert{}, ssl_record:ssl_version(), ssl_record:connection_states()) ->
195				 {iolist(), ssl_record:connection_states()}.
196%%
197%% Description: Encodes an alert message to send on the ssl-socket.
198%%--------------------------------------------------------------------
199encode_alert_record(#alert{level = Level, description = Description},
200                    Version, ConnectionStates) ->
201    #{epoch := Epoch} = ssl_record:current_connection_state(ConnectionStates, write),
202    encode_plain_text(?ALERT, Version, Epoch, <<?BYTE(Level), ?BYTE(Description)>>,
203		      ConnectionStates).
204
205%%--------------------------------------------------------------------
206-spec encode_change_cipher_spec(ssl_record:ssl_version(), integer(), ssl_record:connection_states()) ->
207				       {iolist(), ssl_record:connection_states()}.
208%%
209%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
210%%--------------------------------------------------------------------
211encode_change_cipher_spec(Version, Epoch, ConnectionStates) ->
212    encode_plain_text(?CHANGE_CIPHER_SPEC, Version, Epoch, ?byte(?CHANGE_CIPHER_SPEC_PROTO), ConnectionStates).
213
214%%--------------------------------------------------------------------
215-spec encode_data(binary(), ssl_record:ssl_version(), ssl_record:connection_states()) ->
216			 {iolist(),ssl_record:connection_states()}.
217%%
218%% Description: Encodes data to send on the ssl-socket.
219%%--------------------------------------------------------------------
220encode_data(Data, Version, ConnectionStates) ->
221    #{epoch := Epoch, max_fragment_length := MaxFragmentLength}
222        = ssl_record:current_connection_state(ConnectionStates, write),
223    MaxLength = if is_integer(MaxFragmentLength) ->
224                        MaxFragmentLength;
225                   true ->
226                        ?MAX_PLAIN_TEXT_LENGTH
227                end,
228    case iolist_size(Data) of
229	N when N > MaxLength ->
230            Frags = tls_record:split_iovec(erlang:iolist_to_iovec(Data), MaxLength),
231            {RevCipherText, ConnectionStates1} =
232                lists:foldl(fun(Frag, {Acc, CS0}) ->
233                                    {CipherText, CS1} =
234                                        encode_plain_text(?APPLICATION_DATA, Version, Epoch, Frag, CS0),
235                                    {[CipherText|Acc], CS1}
236                            end, {[], ConnectionStates}, Frags),
237            {lists:reverse(RevCipherText), ConnectionStates1};
238        _ ->
239            encode_plain_text(?APPLICATION_DATA, Version, Epoch, Data, ConnectionStates)
240    end.
241
242encode_plain_text(Type, Version, Epoch, Data, ConnectionStates) ->
243    Write0 = get_connection_state_by_epoch(Epoch, ConnectionStates, write),
244    {CipherFragment, Write1} = encode_plain_text(Type, Version, Data, Write0),
245    {CipherText, Write} = encode_dtls_cipher_text(Type, Version, CipherFragment, Write1),
246    {CipherText, set_connection_state_by_epoch(Write, Epoch, ConnectionStates, write)}.
247
248%%====================================================================
249%% Decoding
250%%====================================================================
251
252decode_cipher_text(#ssl_tls{epoch = Epoch} = CipherText, ConnnectionStates0) ->
253    ReadState = get_connection_state_by_epoch(Epoch, ConnnectionStates0, read),
254    decode_cipher_text(CipherText, ReadState, ConnnectionStates0).
255
256
257%%====================================================================
258%% Protocol version handling
259%%====================================================================
260
261%%--------------------------------------------------------------------
262-spec protocol_version(dtls_atom_version() | ssl_record:ssl_version()) ->
263			      ssl_record:ssl_version() | dtls_atom_version().
264%%
265%% Description: Creates a protocol version record from a version atom
266%% or vice versa.
267%%--------------------------------------------------------------------
268protocol_version('dtlsv1.2') ->
269    {254, 253};
270protocol_version(dtlsv1) ->
271    {254, 255};
272protocol_version({254, 253}) ->
273    'dtlsv1.2';
274protocol_version({254, 255}) ->
275    dtlsv1.
276%%--------------------------------------------------------------------
277-spec lowest_protocol_version(ssl_record:ssl_version(), ssl_record:ssl_version()) -> ssl_record:ssl_version().
278%%
279%% Description: Lowes protocol version of two given versions
280%%--------------------------------------------------------------------
281lowest_protocol_version(Version = {M, N}, {M, O}) when N > O ->
282    Version;
283lowest_protocol_version({M, _}, Version = {M, _}) ->
284    Version;
285lowest_protocol_version(Version = {M,_}, {N, _}) when M > N ->
286    Version;
287lowest_protocol_version(_,Version) ->
288    Version.
289
290%%--------------------------------------------------------------------
291-spec lowest_protocol_version([ssl_record:ssl_version()]) -> ssl_record:ssl_version().
292%%
293%% Description: Lowest protocol version present in a list
294%%--------------------------------------------------------------------
295lowest_protocol_version([]) ->
296    lowest_protocol_version();
297lowest_protocol_version(Versions) ->
298    [Ver | Vers] = Versions,
299    lowest_list_protocol_version(Ver, Vers).
300
301%%--------------------------------------------------------------------
302-spec highest_protocol_version([ssl_record:ssl_version()]) -> ssl_record:ssl_version().
303%%
304%% Description: Highest protocol version present in a list
305%%--------------------------------------------------------------------
306highest_protocol_version([]) ->
307    highest_protocol_version();
308highest_protocol_version(Versions) ->
309    [Ver | Vers] = Versions,
310    highest_list_protocol_version(Ver, Vers).
311
312%%--------------------------------------------------------------------
313-spec highest_protocol_version(ssl_record:ssl_version(), ssl_record:ssl_version()) -> ssl_record:ssl_version().
314%%
315%% Description: Highest protocol version of two given versions
316%%--------------------------------------------------------------------
317highest_protocol_version(Version = {M, N}, {M, O})   when N < O ->
318    Version;
319highest_protocol_version({M, _},
320			Version = {M, _}) ->
321    Version;
322highest_protocol_version(Version = {M,_},
323			{N, _}) when M < N ->
324    Version;
325highest_protocol_version(_,Version) ->
326    Version.
327
328%%--------------------------------------------------------------------
329-spec is_higher(V1 :: ssl_record:ssl_version(), V2::ssl_record:ssl_version()) -> boolean().
330%%
331%% Description: Is V1 > V2
332%%--------------------------------------------------------------------
333is_higher({M, N}, {M, O}) when N < O ->
334    true;
335is_higher({M, _}, {N, _}) when M < N ->
336    true;
337is_higher(_, _) ->
338    false.
339
340%%--------------------------------------------------------------------
341-spec supported_protocol_versions() -> [ssl_record:ssl_version()].
342%%
343%% Description: Protocol versions supported
344%%--------------------------------------------------------------------
345supported_protocol_versions() ->
346    Fun = fun(Version) ->
347		  protocol_version(Version)
348	  end,
349    case application:get_env(ssl, dtls_protocol_version) of
350	undefined ->
351	    lists:map(Fun, supported_protocol_versions([]));
352	{ok, []} ->
353	    lists:map(Fun, supported_protocol_versions([]));
354	{ok, Vsns} when is_list(Vsns) ->
355	    supported_protocol_versions(lists:map(Fun, Vsns));
356	{ok, Vsn} ->
357	    supported_protocol_versions([Fun(Vsn)])
358     end.
359
360supported_protocol_versions([]) ->
361    Vsns = case sufficient_dtlsv1_2_crypto_support() of
362	       true ->
363		   ?ALL_DATAGRAM_SUPPORTED_VERSIONS;
364	       false ->
365		   ?MIN_DATAGRAM_SUPPORTED_VERSIONS
366	   end,
367    application:set_env(ssl, dtls_protocol_version, Vsns),
368    Vsns;
369
370supported_protocol_versions([_|_] = Vsns) ->
371    case sufficient_dtlsv1_2_crypto_support() of
372	true ->
373	    Vsns;
374	false ->
375	    case Vsns -- ['dtlsv1.2'] of
376		[] ->
377		    ?MIN_SUPPORTED_VERSIONS;
378		NewVsns ->
379		    NewVsns
380	    end
381    end.
382
383%%--------------------------------------------------------------------
384-spec is_acceptable_version(ssl_record:ssl_version(), Supported :: [ssl_record:ssl_version()]) -> boolean().
385%%
386%% Description: ssl version 2 is not acceptable security risks are too big.
387%%
388%%--------------------------------------------------------------------
389is_acceptable_version(Version, Versions) ->
390    lists:member(Version, Versions).
391
392-spec hello_version(ssl_record:ssl_version(), [ssl_record:ssl_version()]) -> ssl_record:ssl_version().
393hello_version(Version, Versions) ->
394    case dtls_v1:corresponding_tls_version(Version) of
395        TLSVersion when TLSVersion >= {3, 3} ->
396            Version;
397        _ ->
398            lowest_protocol_version(Versions)
399    end.
400
401
402%%--------------------------------------------------------------------
403%%% Internal functions
404%%--------------------------------------------------------------------
405initial_connection_state(ConnectionEnd, BeastMitigation) ->
406    #{security_parameters =>
407	  ssl_record:initial_security_params(ConnectionEnd),
408      epoch => undefined,
409      sequence_number => 0,
410      replay_window => init_replay_window(),
411      beast_mitigation => BeastMitigation,
412      compression_state  => undefined,
413      cipher_state  => undefined,
414      mac_secret  => undefined,
415      secure_renegotiation => undefined,
416      client_verify_data => undefined,
417      server_verify_data => undefined,
418      max_fragment_length => undefined
419     }.
420
421get_dtls_records_aux({DataTag, StateName, _, Versions} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
422                                                         ?UINT16(Epoch), ?UINT48(SequenceNumber),
423                                                         ?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord,
424		     Acc, #{log_level := LogLevel} = SslOpts)
425  when ((StateName == hello)
426        orelse ((StateName == certify) andalso (DataTag == udp))
427        orelse ((StateName == abbreviated) andalso (DataTag == udp))) andalso ((Type == ?HANDSHAKE)
428                                                                               orelse
429                                                                                 (Type == ?ALERT)) ->
430    ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]),
431    case is_acceptable_version({MajVer, MinVer}, Versions) of
432        true ->
433            get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type,
434                                                 version = {MajVer, MinVer},
435                                                 epoch = Epoch, sequence_number = SequenceNumber,
436                                                 fragment = Data} | Acc], SslOpts);
437        false ->
438              ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
439        end;
440get_dtls_records_aux({_, _, Version, _} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer),
441		       ?UINT16(Epoch), ?UINT48(SequenceNumber),
442		       ?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord,
443		     Acc, #{log_level := LogLevel} = SslOpts) when (Type == ?APPLICATION_DATA) orelse
444                                        (Type == ?HANDSHAKE) orelse
445                                        (Type == ?ALERT) orelse
446                                        (Type == ?CHANGE_CIPHER_SPEC) ->
447    ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]),
448    case {MajVer, MinVer} of
449        Version ->
450            get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type,
451                                                 version = {MajVer, MinVer},
452                                                 epoch = Epoch, sequence_number = SequenceNumber,
453                                                 fragment = Data} | Acc], SslOpts);
454        _ ->
455            ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
456    end;
457get_dtls_records_aux(_, <<?BYTE(_), ?BYTE(_MajVer), ?BYTE(_MinVer),
458		       ?UINT16(Length), _/binary>>,
459		     _Acc, _) when Length > ?MAX_CIPHER_TEXT_LENGTH ->
460    ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW);
461
462get_dtls_records_aux(_, Data, Acc, _) ->
463    case byte_size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of
464	true ->
465	    {lists:reverse(Acc), Data};
466	false ->
467	    ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
468    end.
469%%--------------------------------------------------------------------
470
471init_replay_window() ->
472    init_replay_window(?REPLAY_WINDOW_SIZE).
473
474init_replay_window(Size) ->
475    #{top => Size-1,
476      bottom => 0,
477      mask => 0
478     }.
479
480replay_detect(#ssl_tls{sequence_number = SequenceNumber}, #{replay_window := Window}) ->
481    is_replay(SequenceNumber, Window).
482
483is_replay(SequenceNumber, #{bottom := Bottom})
484  when SequenceNumber < Bottom ->
485    true;
486is_replay(SequenceNumber, #{top := Top, bottom := Bottom, mask :=  Mask})
487  when (Bottom =< SequenceNumber) andalso (SequenceNumber =< Top) ->
488    Index = SequenceNumber - Bottom,
489    ((Mask bsr Index) band 1) =:= 1;
490is_replay(_, _) ->
491    false.
492
493update_replay_window(SequenceNumber,
494                     #{replay_window :=
495                           #{top := Top,
496                             bottom := Bottom,
497                             mask :=  Mask0} = Window0}
498                     = ConnectionStates) ->
499    NoNewBits = SequenceNumber - Top,
500    Window =
501        case NoNewBits > 0 of
502            true ->
503                NewBottom = Bottom + NoNewBits,
504                Index = SequenceNumber - NewBottom,
505                Mask = (Mask0 bsr NoNewBits) bor (1 bsl Index),
506                Window0#{top => Top + NoNewBits,
507                         bottom => NewBottom,
508                         mask => Mask};
509            false ->
510                Index = SequenceNumber - Bottom,
511                Mask = Mask0 bor (1 bsl Index),
512                Window0#{mask => Mask}
513        end,
514    ConnectionStates#{replay_window := Window}.
515
516%%--------------------------------------------------------------------
517
518encode_dtls_cipher_text(Type, {MajVer, MinVer}, Fragment,
519		       #{epoch := Epoch, sequence_number := Seq} = WriteState) ->
520    Length = erlang:iolist_size(Fragment),
521    {[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Epoch),
522	?UINT48(Seq), ?UINT16(Length)>>, Fragment],
523     WriteState#{sequence_number => Seq + 1}}.
524
525encode_plain_text(Type, Version, Data, #{compression_state := CompS0,
526                                         cipher_state := CipherS0,
527					 epoch := Epoch,
528					 sequence_number := Seq,
529					 security_parameters :=
530					     #security_parameters{
531						cipher_type = ?AEAD,
532                                                bulk_cipher_algorithm = BCAlg,
533						compression_algorithm = CompAlg}
534					} = WriteState0) ->
535    {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
536    AAD = start_additional_data(Type, Version, Epoch, Seq),
537    CipherS = ssl_record:nonce_seed(BCAlg, <<?UINT16(Epoch), ?UINT48(Seq)>>, CipherS0),
538    WriteState = WriteState0#{compression_state => CompS1,
539                              cipher_state => CipherS},
540    TLSVersion = dtls_v1:corresponding_tls_version(Version),
541    ssl_record:cipher_aead(TLSVersion, Comp, WriteState, AAD);
542encode_plain_text(Type, Version, Fragment, #{compression_state := CompS0,
543					 epoch := Epoch,
544					 sequence_number := Seq,
545                                         cipher_state := CipherS0,
546					 security_parameters :=
547					     #security_parameters{compression_algorithm = CompAlg,
548                                                                  bulk_cipher_algorithm =
549                                                                      BulkCipherAlgo}
550					}= WriteState0) ->
551    {Comp, CompS1} = ssl_record:compress(CompAlg, Fragment, CompS0),
552    WriteState1 = WriteState0#{compression_state => CompS1},
553    MAC = calc_mac_hash(Type, Version, WriteState1, Epoch, Seq, Comp),
554    TLSVersion = dtls_v1:corresponding_tls_version(Version),
555    {CipherFragment, CipherS1} =
556	ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MAC, Fragment, TLSVersion),
557    {CipherFragment,  WriteState0#{cipher_state => CipherS1}}.
558
559%%--------------------------------------------------------------------
560decode_cipher_text(#ssl_tls{type = Type, version = Version,
561			    epoch = Epoch,
562			    sequence_number = Seq,
563			    fragment = CipherFragment} = CipherText,
564		   #{compression_state := CompressionS0,
565                     cipher_state := CipherS0,
566		     security_parameters :=
567			 #security_parameters{
568			    cipher_type = ?AEAD,
569                            bulk_cipher_algorithm =
570                                BulkCipherAlgo,
571			    compression_algorithm = CompAlg}} = ReadState0,
572		   ConnnectionStates0) ->
573    AAD = start_additional_data(Type, Version, Epoch, Seq),
574    CipherS = ssl_record:nonce_seed(BulkCipherAlgo, <<?UINT16(Epoch), ?UINT48(Seq)>>, CipherS0),
575    TLSVersion = dtls_v1:corresponding_tls_version(Version),
576    case ssl_record:decipher_aead(BulkCipherAlgo, CipherS, AAD, CipherFragment, TLSVersion) of
577	PlainFragment when is_binary(PlainFragment) ->
578	    {Plain, CompressionS} = ssl_record:uncompress(CompAlg,
579							   PlainFragment, CompressionS0),
580	    ReadState1 = ReadState0#{compression_state := CompressionS,
581                                     cipher_state := CipherS},
582            ReadState = update_replay_window(Seq, ReadState1),
583	    ConnnectionStates = set_connection_state_by_epoch(ReadState, Epoch, ConnnectionStates0, read),
584	    {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
585	  #alert{} = Alert ->
586	    Alert
587    end;
588decode_cipher_text(#ssl_tls{type = Type, version = Version,
589			    epoch = Epoch,
590			    sequence_number = Seq,
591			    fragment = CipherFragment} = CipherText,
592		   #{compression_state := CompressionS0,
593		     security_parameters :=
594			 #security_parameters{
595			    compression_algorithm = CompAlg}} = ReadState0,
596		   ConnnectionStates0) ->
597    {PlainFragment, Mac, ReadState1} = ssl_record:decipher(dtls_v1:corresponding_tls_version(Version),
598							   CipherFragment, ReadState0, true),
599    MacHash = calc_mac_hash(Type, Version, ReadState1, Epoch, Seq, PlainFragment),
600    case ssl_record:is_correct_mac(Mac, MacHash) of
601	true ->
602	    {Plain, CompressionS1} = ssl_record:uncompress(CompAlg,
603							   PlainFragment, CompressionS0),
604
605	    ReadState2 = ReadState1#{compression_state => CompressionS1},
606            ReadState = update_replay_window(Seq, ReadState2),
607	    ConnnectionStates = set_connection_state_by_epoch(ReadState, Epoch, ConnnectionStates0, read),
608	    {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
609	false ->
610	    ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
611    end.
612%%--------------------------------------------------------------------
613
614calc_mac_hash(Type, Version, #{mac_secret := MacSecret,
615			       security_parameters := #security_parameters{mac_algorithm = MacAlg}},
616	      Epoch, SeqNo, Fragment) ->
617    Length = erlang:iolist_size(Fragment),
618    mac_hash(Version, MacAlg, MacSecret, Epoch, SeqNo, Type,
619	     Length, Fragment).
620
621mac_hash({Major, Minor}, MacAlg, MacSecret, Epoch, SeqNo, Type, Length, Fragment) ->
622    Value = [<<?UINT16(Epoch), ?UINT48(SeqNo), ?BYTE(Type),
623       ?BYTE(Major), ?BYTE(Minor), ?UINT16(Length)>>,
624     Fragment],
625    dtls_v1:hmac_hash(MacAlg, MacSecret, Value).
626
627start_additional_data(Type, {MajVer, MinVer}, Epoch, SeqNo) ->
628    <<?UINT16(Epoch), ?UINT48(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>.
629
630%%--------------------------------------------------------------------
631
632lowest_list_protocol_version(Ver, []) ->
633    Ver;
634lowest_list_protocol_version(Ver1,  [Ver2 | Rest]) ->
635    lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest).
636
637highest_list_protocol_version(Ver, []) ->
638    Ver;
639highest_list_protocol_version(Ver1,  [Ver2 | Rest]) ->
640    highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest).
641
642highest_protocol_version() ->
643    highest_protocol_version(supported_protocol_versions()).
644
645lowest_protocol_version() ->
646    lowest_protocol_version(supported_protocol_versions()).
647
648sufficient_dtlsv1_2_crypto_support() ->
649    CryptoSupport = crypto:supports(),
650    proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
651
652