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