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 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(), {atom(), atom(), ssl_record:ssl_version(), [ssl_record:ssl_version()]}, binary(), 166 ssl_options()) -> {[binary()], binary()} | #alert{}. 167%% 168%% Description: Given old buffer and new data from UDP/SCTP, packs up a records 169%% and returns it as a list of tls_compressed binaries also returns leftover 170%% data 171%%-------------------------------------------------------------------- 172get_dtls_records(Data, Vinfo, Buffer, SslOpts) -> 173 BinData = list_to_binary([Buffer, Data]), 174 get_dtls_records_aux(Vinfo, BinData, [], SslOpts). 175 176%%==================================================================== 177%% Encoding DTLS records 178%%==================================================================== 179 180%%-------------------------------------------------------------------- 181-spec encode_handshake(iolist(), ssl_record:ssl_version(), integer(), ssl_record:connection_states()) -> 182 {iolist(), ssl_record:connection_states()}. 183% 184%% Description: Encodes a handshake message to send on the ssl-socket. 185%%-------------------------------------------------------------------- 186encode_handshake(Frag, Version, Epoch, ConnectionStates) -> 187 encode_plain_text(?HANDSHAKE, Version, Epoch, Frag, ConnectionStates). 188 189 190%%-------------------------------------------------------------------- 191-spec encode_alert_record(#alert{}, ssl_record:ssl_version(), ssl_record:connection_states()) -> 192 {iolist(), ssl_record:connection_states()}. 193%% 194%% Description: Encodes an alert message to send on the ssl-socket. 195%%-------------------------------------------------------------------- 196encode_alert_record(#alert{level = Level, description = Description}, 197 Version, ConnectionStates) -> 198 #{epoch := Epoch} = ssl_record:current_connection_state(ConnectionStates, write), 199 encode_plain_text(?ALERT, Version, Epoch, <<?BYTE(Level), ?BYTE(Description)>>, 200 ConnectionStates). 201 202%%-------------------------------------------------------------------- 203-spec encode_change_cipher_spec(ssl_record:ssl_version(), integer(), ssl_record:connection_states()) -> 204 {iolist(), ssl_record:connection_states()}. 205%% 206%% Description: Encodes a change_cipher_spec-message to send on the ssl socket. 207%%-------------------------------------------------------------------- 208encode_change_cipher_spec(Version, Epoch, ConnectionStates) -> 209 encode_plain_text(?CHANGE_CIPHER_SPEC, Version, Epoch, ?byte(?CHANGE_CIPHER_SPEC_PROTO), ConnectionStates). 210 211%%-------------------------------------------------------------------- 212-spec encode_data(binary(), ssl_record:ssl_version(), ssl_record:connection_states()) -> 213 {iolist(),ssl_record:connection_states()}. 214%% 215%% Description: Encodes data to send on the ssl-socket. 216%%-------------------------------------------------------------------- 217encode_data(Data, Version, ConnectionStates) -> 218 #{epoch := Epoch} = ssl_record:current_connection_state(ConnectionStates, write), 219 encode_plain_text(?APPLICATION_DATA, Version, Epoch, Data, ConnectionStates). 220 221encode_plain_text(Type, Version, Epoch, Data, ConnectionStates) -> 222 Write0 = get_connection_state_by_epoch(Epoch, ConnectionStates, write), 223 {CipherFragment, Write1} = encode_plain_text(Type, Version, Data, Write0), 224 {CipherText, Write} = encode_dtls_cipher_text(Type, Version, CipherFragment, Write1), 225 {CipherText, set_connection_state_by_epoch(Write, Epoch, ConnectionStates, write)}. 226 227%%==================================================================== 228%% Decoding 229%%==================================================================== 230 231decode_cipher_text(#ssl_tls{epoch = Epoch} = CipherText, ConnnectionStates0) -> 232 ReadState = get_connection_state_by_epoch(Epoch, ConnnectionStates0, read), 233 decode_cipher_text(CipherText, ReadState, ConnnectionStates0). 234 235 236%%==================================================================== 237%% Protocol version handling 238%%==================================================================== 239 240%%-------------------------------------------------------------------- 241-spec protocol_version(dtls_atom_version() | ssl_record:ssl_version()) -> 242 ssl_record:ssl_version() | dtls_atom_version(). 243%% 244%% Description: Creates a protocol version record from a version atom 245%% or vice versa. 246%%-------------------------------------------------------------------- 247protocol_version('dtlsv1.2') -> 248 {254, 253}; 249protocol_version(dtlsv1) -> 250 {254, 255}; 251protocol_version({254, 253}) -> 252 'dtlsv1.2'; 253protocol_version({254, 255}) -> 254 dtlsv1. 255%%-------------------------------------------------------------------- 256-spec lowest_protocol_version(ssl_record:ssl_version(), ssl_record:ssl_version()) -> ssl_record:ssl_version(). 257%% 258%% Description: Lowes protocol version of two given versions 259%%-------------------------------------------------------------------- 260lowest_protocol_version(Version = {M, N}, {M, O}) when N > O -> 261 Version; 262lowest_protocol_version({M, _}, Version = {M, _}) -> 263 Version; 264lowest_protocol_version(Version = {M,_}, {N, _}) when M > N -> 265 Version; 266lowest_protocol_version(_,Version) -> 267 Version. 268 269%%-------------------------------------------------------------------- 270-spec lowest_protocol_version([ssl_record:ssl_version()]) -> ssl_record:ssl_version(). 271%% 272%% Description: Lowest protocol version present in a list 273%%-------------------------------------------------------------------- 274lowest_protocol_version([]) -> 275 lowest_protocol_version(); 276lowest_protocol_version(Versions) -> 277 [Ver | Vers] = Versions, 278 lowest_list_protocol_version(Ver, Vers). 279 280%%-------------------------------------------------------------------- 281-spec highest_protocol_version([ssl_record:ssl_version()]) -> ssl_record:ssl_version(). 282%% 283%% Description: Highest protocol version present in a list 284%%-------------------------------------------------------------------- 285highest_protocol_version([]) -> 286 highest_protocol_version(); 287highest_protocol_version(Versions) -> 288 [Ver | Vers] = Versions, 289 highest_list_protocol_version(Ver, Vers). 290 291%%-------------------------------------------------------------------- 292-spec highest_protocol_version(ssl_record:ssl_version(), ssl_record:ssl_version()) -> ssl_record:ssl_version(). 293%% 294%% Description: Highest protocol version of two given versions 295%%-------------------------------------------------------------------- 296highest_protocol_version(Version = {M, N}, {M, O}) when N < O -> 297 Version; 298highest_protocol_version({M, _}, 299 Version = {M, _}) -> 300 Version; 301highest_protocol_version(Version = {M,_}, 302 {N, _}) when M < N -> 303 Version; 304highest_protocol_version(_,Version) -> 305 Version. 306 307%%-------------------------------------------------------------------- 308-spec is_higher(V1 :: ssl_record:ssl_version(), V2::ssl_record:ssl_version()) -> boolean(). 309%% 310%% Description: Is V1 > V2 311%%-------------------------------------------------------------------- 312is_higher({M, N}, {M, O}) when N < O -> 313 true; 314is_higher({M, _}, {N, _}) when M < N -> 315 true; 316is_higher(_, _) -> 317 false. 318 319%%-------------------------------------------------------------------- 320-spec supported_protocol_versions() -> [ssl_record:ssl_version()]. 321%% 322%% Description: Protocol versions supported 323%%-------------------------------------------------------------------- 324supported_protocol_versions() -> 325 Fun = fun(Version) -> 326 protocol_version(Version) 327 end, 328 case application:get_env(ssl, dtls_protocol_version) of 329 undefined -> 330 lists:map(Fun, supported_protocol_versions([])); 331 {ok, []} -> 332 lists:map(Fun, supported_protocol_versions([])); 333 {ok, Vsns} when is_list(Vsns) -> 334 supported_protocol_versions(lists:map(Fun, Vsns)); 335 {ok, Vsn} -> 336 supported_protocol_versions([Fun(Vsn)]) 337 end. 338 339supported_protocol_versions([]) -> 340 Vsns = case sufficient_dtlsv1_2_crypto_support() of 341 true -> 342 ?ALL_DATAGRAM_SUPPORTED_VERSIONS; 343 false -> 344 ?MIN_DATAGRAM_SUPPORTED_VERSIONS 345 end, 346 application:set_env(ssl, dtls_protocol_version, Vsns), 347 Vsns; 348 349supported_protocol_versions([_|_] = Vsns) -> 350 case sufficient_dtlsv1_2_crypto_support() of 351 true -> 352 Vsns; 353 false -> 354 case Vsns -- ['dtlsv1.2'] of 355 [] -> 356 ?MIN_SUPPORTED_VERSIONS; 357 NewVsns -> 358 NewVsns 359 end 360 end. 361 362%%-------------------------------------------------------------------- 363-spec is_acceptable_version(ssl_record:ssl_version(), Supported :: [ssl_record:ssl_version()]) -> boolean(). 364%% 365%% Description: ssl version 2 is not acceptable security risks are too big. 366%% 367%%-------------------------------------------------------------------- 368is_acceptable_version(Version, Versions) -> 369 lists:member(Version, Versions). 370 371-spec hello_version(ssl_record:ssl_version(), [ssl_record:ssl_version()]) -> ssl_record:ssl_version(). 372hello_version(Version, Versions) -> 373 case dtls_v1:corresponding_tls_version(Version) of 374 TLSVersion when TLSVersion >= {3, 3} -> 375 Version; 376 _ -> 377 lowest_protocol_version(Versions) 378 end. 379 380 381%%-------------------------------------------------------------------- 382%%% Internal functions 383%%-------------------------------------------------------------------- 384initial_connection_state(ConnectionEnd, BeastMitigation) -> 385 #{security_parameters => 386 ssl_record:initial_security_params(ConnectionEnd), 387 epoch => undefined, 388 sequence_number => 0, 389 replay_window => init_replay_window(?REPLAY_WINDOW_SIZE), 390 beast_mitigation => BeastMitigation, 391 compression_state => undefined, 392 cipher_state => undefined, 393 mac_secret => undefined, 394 secure_renegotiation => undefined, 395 client_verify_data => undefined, 396 server_verify_data => undefined 397 }. 398 399get_dtls_records_aux({DataTag, StateName, _, Versions} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer), 400 ?UINT16(Epoch), ?UINT48(SequenceNumber), 401 ?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord, 402 Acc, #{log_level := LogLevel} = SslOpts) 403 when ((StateName == hello) 404 orelse ((StateName == certify) andalso (DataTag == udp)) 405 orelse ((StateName == abbreviated) andalso (DataTag == udp))) andalso ((Type == ?HANDSHAKE) 406 orelse 407 (Type == ?ALERT)) -> 408 ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]), 409 case is_acceptable_version({MajVer, MinVer}, Versions) of 410 true -> 411 get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type, 412 version = {MajVer, MinVer}, 413 epoch = Epoch, sequence_number = SequenceNumber, 414 fragment = Data} | Acc], SslOpts); 415 false -> 416 ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC) 417 end; 418get_dtls_records_aux({_, _, Version, _} = Vinfo, <<?BYTE(Type),?BYTE(MajVer),?BYTE(MinVer), 419 ?UINT16(Epoch), ?UINT48(SequenceNumber), 420 ?UINT16(Length), Data:Length/binary, Rest/binary>> = RawDTLSRecord, 421 Acc, #{log_level := LogLevel} = SslOpts) when (Type == ?APPLICATION_DATA) orelse 422 (Type == ?HANDSHAKE) orelse 423 (Type == ?ALERT) orelse 424 (Type == ?CHANGE_CIPHER_SPEC) -> 425 ssl_logger:debug(LogLevel, inbound, 'record', [RawDTLSRecord]), 426 case {MajVer, MinVer} of 427 Version -> 428 get_dtls_records_aux(Vinfo, Rest, [#ssl_tls{type = Type, 429 version = {MajVer, MinVer}, 430 epoch = Epoch, sequence_number = SequenceNumber, 431 fragment = Data} | Acc], SslOpts); 432 _ -> 433 ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC) 434 end; 435get_dtls_records_aux(_, <<?BYTE(_), ?BYTE(_MajVer), ?BYTE(_MinVer), 436 ?UINT16(Length), _/binary>>, 437 _Acc, _) when Length > ?MAX_CIPHER_TEXT_LENGTH -> 438 ?ALERT_REC(?FATAL, ?RECORD_OVERFLOW); 439 440get_dtls_records_aux(_, Data, Acc, _) -> 441 case size(Data) =< ?MAX_CIPHER_TEXT_LENGTH + ?INITIAL_BYTES of 442 true -> 443 {lists:reverse(Acc), Data}; 444 false -> 445 ?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE) 446 end. 447%%-------------------------------------------------------------------- 448 449init_replay_window(Size) -> 450 #{size => Size, 451 top => Size, 452 bottom => 0, 453 mask => 0 bsl 64 454 }. 455 456replay_detect(#ssl_tls{sequence_number = SequenceNumber}, #{replay_window := Window}) -> 457 is_replay(SequenceNumber, Window). 458 459 460is_replay(SequenceNumber, #{bottom := Bottom}) when SequenceNumber < Bottom -> 461 true; 462is_replay(SequenceNumber, #{size := Size, 463 top := Top, 464 bottom := Bottom, 465 mask := Mask}) when (SequenceNumber >= Bottom) andalso (SequenceNumber =< Top) -> 466 Index = (SequenceNumber rem Size), 467 (Index band Mask) == 1; 468 469is_replay(_, _) -> 470 false. 471 472update_replay_window(SequenceNumber, #{replay_window := #{size := Size, 473 top := Top, 474 bottom := Bottom, 475 mask := Mask0} = Window0} = ConnectionStates) -> 476 NoNewBits = SequenceNumber - Top, 477 Index = SequenceNumber rem Size, 478 Mask = (Mask0 bsl NoNewBits) bor Index, 479 Window = Window0#{top => SequenceNumber, 480 bottom => Bottom + NoNewBits, 481 mask => Mask}, 482 ConnectionStates#{replay_window := Window}. 483 484%%-------------------------------------------------------------------- 485 486encode_dtls_cipher_text(Type, {MajVer, MinVer}, Fragment, 487 #{epoch := Epoch, sequence_number := Seq} = WriteState) -> 488 Length = erlang:iolist_size(Fragment), 489 {[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Epoch), 490 ?UINT48(Seq), ?UINT16(Length)>>, Fragment], 491 WriteState#{sequence_number => Seq + 1}}. 492 493encode_plain_text(Type, Version, Data, #{compression_state := CompS0, 494 cipher_state := CipherS0, 495 epoch := Epoch, 496 sequence_number := Seq, 497 security_parameters := 498 #security_parameters{ 499 cipher_type = ?AEAD, 500 bulk_cipher_algorithm = BCAlg, 501 compression_algorithm = CompAlg} 502 } = WriteState0) -> 503 {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0), 504 AAD = start_additional_data(Type, Version, Epoch, Seq), 505 CipherS = ssl_record:nonce_seed(BCAlg, <<?UINT16(Epoch), ?UINT48(Seq)>>, CipherS0), 506 WriteState = WriteState0#{compression_state => CompS1, 507 cipher_state => CipherS}, 508 TLSVersion = dtls_v1:corresponding_tls_version(Version), 509 ssl_record:cipher_aead(TLSVersion, Comp, WriteState, AAD); 510encode_plain_text(Type, Version, Fragment, #{compression_state := CompS0, 511 epoch := Epoch, 512 sequence_number := Seq, 513 cipher_state := CipherS0, 514 security_parameters := 515 #security_parameters{compression_algorithm = CompAlg, 516 bulk_cipher_algorithm = 517 BulkCipherAlgo} 518 }= WriteState0) -> 519 {Comp, CompS1} = ssl_record:compress(CompAlg, Fragment, CompS0), 520 WriteState1 = WriteState0#{compression_state => CompS1}, 521 MAC = calc_mac_hash(Type, Version, WriteState1, Epoch, Seq, Comp), 522 TLSVersion = dtls_v1:corresponding_tls_version(Version), 523 {CipherFragment, CipherS1} = 524 ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MAC, Fragment, TLSVersion), 525 {CipherFragment, WriteState0#{cipher_state => CipherS1}}. 526 527%%-------------------------------------------------------------------- 528decode_cipher_text(#ssl_tls{type = Type, version = Version, 529 epoch = Epoch, 530 sequence_number = Seq, 531 fragment = CipherFragment} = CipherText, 532 #{compression_state := CompressionS0, 533 cipher_state := CipherS0, 534 security_parameters := 535 #security_parameters{ 536 cipher_type = ?AEAD, 537 bulk_cipher_algorithm = 538 BulkCipherAlgo, 539 compression_algorithm = CompAlg}} = ReadState0, 540 ConnnectionStates0) -> 541 AAD = start_additional_data(Type, Version, Epoch, Seq), 542 CipherS = ssl_record:nonce_seed(BulkCipherAlgo, <<?UINT16(Epoch), ?UINT48(Seq)>>, CipherS0), 543 TLSVersion = dtls_v1:corresponding_tls_version(Version), 544 case ssl_record:decipher_aead(BulkCipherAlgo, CipherS, AAD, CipherFragment, TLSVersion) of 545 PlainFragment when is_binary(PlainFragment) -> 546 {Plain, CompressionS} = ssl_record:uncompress(CompAlg, 547 PlainFragment, CompressionS0), 548 ReadState1 = ReadState0#{compression_state := CompressionS, 549 cipher_state := CipherS}, 550 ReadState = update_replay_window(Seq, ReadState1), 551 ConnnectionStates = set_connection_state_by_epoch(ReadState, Epoch, ConnnectionStates0, read), 552 {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates}; 553 #alert{} = Alert -> 554 Alert 555 end; 556decode_cipher_text(#ssl_tls{type = Type, version = Version, 557 epoch = Epoch, 558 sequence_number = Seq, 559 fragment = CipherFragment} = CipherText, 560 #{compression_state := CompressionS0, 561 security_parameters := 562 #security_parameters{ 563 compression_algorithm = CompAlg}} = ReadState0, 564 ConnnectionStates0) -> 565 {PlainFragment, Mac, ReadState1} = ssl_record:decipher(dtls_v1:corresponding_tls_version(Version), 566 CipherFragment, ReadState0, true), 567 MacHash = calc_mac_hash(Type, Version, ReadState1, Epoch, Seq, PlainFragment), 568 case ssl_record:is_correct_mac(Mac, MacHash) of 569 true -> 570 {Plain, CompressionS1} = ssl_record:uncompress(CompAlg, 571 PlainFragment, CompressionS0), 572 573 ReadState2 = ReadState1#{compression_state => CompressionS1}, 574 ReadState = update_replay_window(Seq, ReadState2), 575 ConnnectionStates = set_connection_state_by_epoch(ReadState, Epoch, ConnnectionStates0, read), 576 {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates}; 577 false -> 578 ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC) 579 end. 580%%-------------------------------------------------------------------- 581 582calc_mac_hash(Type, Version, #{mac_secret := MacSecret, 583 security_parameters := #security_parameters{mac_algorithm = MacAlg}}, 584 Epoch, SeqNo, Fragment) -> 585 Length = erlang:iolist_size(Fragment), 586 mac_hash(Version, MacAlg, MacSecret, Epoch, SeqNo, Type, 587 Length, Fragment). 588 589mac_hash({Major, Minor}, MacAlg, MacSecret, Epoch, SeqNo, Type, Length, Fragment) -> 590 Value = [<<?UINT16(Epoch), ?UINT48(SeqNo), ?BYTE(Type), 591 ?BYTE(Major), ?BYTE(Minor), ?UINT16(Length)>>, 592 Fragment], 593 dtls_v1:hmac_hash(MacAlg, MacSecret, Value). 594 595start_additional_data(Type, {MajVer, MinVer}, Epoch, SeqNo) -> 596 <<?UINT16(Epoch), ?UINT48(SeqNo), ?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer)>>. 597 598%%-------------------------------------------------------------------- 599 600lowest_list_protocol_version(Ver, []) -> 601 Ver; 602lowest_list_protocol_version(Ver1, [Ver2 | Rest]) -> 603 lowest_list_protocol_version(lowest_protocol_version(Ver1, Ver2), Rest). 604 605highest_list_protocol_version(Ver, []) -> 606 Ver; 607highest_list_protocol_version(Ver1, [Ver2 | Rest]) -> 608 highest_list_protocol_version(highest_protocol_version(Ver1, Ver2), Rest). 609 610highest_protocol_version() -> 611 highest_protocol_version(supported_protocol_versions()). 612 613lowest_protocol_version() -> 614 lowest_protocol_version(supported_protocol_versions()). 615 616sufficient_dtlsv1_2_crypto_support() -> 617 CryptoSupport = crypto:supports(), 618 proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)). 619 620