1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2007-2020. 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: Help funtions for handling the TLS 1.3 (specific parts of) 23%%% TLS handshake protocol 24%%---------------------------------------------------------------------- 25 26-module(tls_handshake_1_3). 27 28-include("tls_handshake_1_3.hrl"). 29-include("ssl_alert.hrl"). 30-include("ssl_cipher.hrl"). 31-include("ssl_connection.hrl"). 32-include("ssl_internal.hrl"). 33-include("ssl_record.hrl"). 34-include_lib("public_key/include/public_key.hrl"). 35 36%% Encode 37-export([encode_handshake/1, decode_handshake/2]). 38 39%% Create handshake messages 40-export([certificate/5, 41 certificate_verify/4, 42 encrypted_extensions/1, 43 key_update/1]). 44 45-export([do_start/2, 46 do_negotiated/2, 47 do_wait_cert/2, 48 do_wait_cv/2, 49 do_wait_finished/2, 50 do_wait_sh/2, 51 do_wait_ee/2, 52 do_wait_cert_cr/2, 53 get_ticket_data/3, 54 maybe_add_binders/3, 55 maybe_add_binders/4, 56 maybe_automatic_session_resumption/1]). 57 58-export([is_valid_binder/4]). 59 60%% crypto:hash(sha256, "HelloRetryRequest"). 61-define(HELLO_RETRY_REQUEST_RANDOM, <<207,33,173,116,229,154,97,17, 62 190,29,140,2,30,101,184,145, 63 194,162,17,22,122,187,140,94, 64 7,158,9,226,200,168,51,156>>). 65 66%%==================================================================== 67%% Create handshake messages 68%%==================================================================== 69 70server_hello(MsgType, SessionId, KeyShare, PSK, ConnectionStates) -> 71 #{security_parameters := SecParams} = 72 ssl_record:pending_connection_state(ConnectionStates, read), 73 Extensions = server_hello_extensions(MsgType, KeyShare, PSK), 74 #server_hello{server_version = {3,3}, %% legacy_version 75 cipher_suite = SecParams#security_parameters.cipher_suite, 76 compression_method = 0, %% legacy attribute 77 random = server_hello_random(MsgType, SecParams), 78 session_id = SessionId, 79 extensions = Extensions 80 }. 81 82 83%% The server's extensions MUST contain "supported_versions". 84%% Additionally, it SHOULD contain the minimal set of extensions 85%% necessary for the client to generate a correct ClientHello pair. As 86%% with the ServerHello, a HelloRetryRequest MUST NOT contain any 87%% extensions that were not first offered by the client in its 88%% ClientHello, with the exception of optionally the "cookie" (see 89%% Section 4.2.2) extension. 90server_hello_extensions(hello_retry_request = MsgType, KeyShare, _) -> 91 SupportedVersions = #server_hello_selected_version{selected_version = {3,4}}, 92 Extensions = #{server_hello_selected_version => SupportedVersions}, 93 ssl_handshake:add_server_share(MsgType, Extensions, KeyShare); 94server_hello_extensions(MsgType, KeyShare, undefined) -> 95 SupportedVersions = #server_hello_selected_version{selected_version = {3,4}}, 96 Extensions = #{server_hello_selected_version => SupportedVersions}, 97 ssl_handshake:add_server_share(MsgType, Extensions, KeyShare); 98server_hello_extensions(MsgType, KeyShare, {SelectedIdentity, _}) -> 99 SupportedVersions = #server_hello_selected_version{selected_version = {3,4}}, 100 PreSharedKey = #pre_shared_key_server_hello{selected_identity = SelectedIdentity}, 101 Extensions = #{server_hello_selected_version => SupportedVersions, 102 pre_shared_key => PreSharedKey}, 103 ssl_handshake:add_server_share(MsgType, Extensions, KeyShare). 104 105 106server_hello_random(server_hello, #security_parameters{server_random = Random}) -> 107 Random; 108%% For reasons of backward compatibility with middleboxes (see 109%% Appendix D.4), the HelloRetryRequest message uses the same structure 110%% as the ServerHello, but with Random set to the special value of the 111%% SHA-256 of "HelloRetryRequest": 112%% 113%% CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91 114%% C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C 115server_hello_random(hello_retry_request, _) -> 116 ?HELLO_RETRY_REQUEST_RANDOM. 117 118 119encrypted_extensions(#state{handshake_env = #handshake_env{alpn = undefined}}) -> 120 #encrypted_extensions{ 121 extensions = #{} 122 }; 123encrypted_extensions(#state{handshake_env = #handshake_env{alpn = ALPNProtocol}}) -> 124 Extensions = ssl_handshake:add_alpn(#{}, ALPNProtocol), 125 #encrypted_extensions{ 126 extensions = Extensions 127 }. 128 129 130certificate_request(SignAlgs0, SignAlgsCert0) -> 131 %% Input arguments contain TLS 1.2 algorithms due to backward compatibility 132 %% reasons. These {Hash, Algo} tuples must be filtered before creating the 133 %% the extensions. 134 SignAlgs = filter_tls13_algs(SignAlgs0), 135 SignAlgsCert = filter_tls13_algs(SignAlgsCert0), 136 Extensions0 = add_signature_algorithms(#{}, SignAlgs), 137 Extensions = add_signature_algorithms_cert(Extensions0, SignAlgsCert), 138 #certificate_request_1_3{ 139 certificate_request_context = <<>>, 140 extensions = Extensions}. 141 142 143add_signature_algorithms(Extensions, SignAlgs) -> 144 Extensions#{signature_algorithms => 145 #signature_algorithms{signature_scheme_list = SignAlgs}}. 146 147 148add_signature_algorithms_cert(Extensions, undefined) -> 149 Extensions; 150add_signature_algorithms_cert(Extensions, SignAlgsCert) -> 151 Extensions#{signature_algorithms_cert => 152 #signature_algorithms_cert{signature_scheme_list = SignAlgsCert}}. 153 154 155filter_tls13_algs(undefined) -> undefined; 156filter_tls13_algs(Algo) -> 157 lists:filter(fun is_atom/1, Algo). 158 159 160%% enum { 161%% X509(0), 162%% RawPublicKey(2), 163%% (255) 164%% } CertificateType; 165%% 166%% struct { 167%% select (certificate_type) { 168%% case RawPublicKey: 169%% /* From RFC 7250 ASN.1_subjectPublicKeyInfo */ 170%% opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; 171%% 172%% case X509: 173%% opaque cert_data<1..2^24-1>; 174%% }; 175%% Extension extensions<0..2^16-1>; 176%% } CertificateEntry; 177%% 178%% struct { 179%% opaque certificate_request_context<0..2^8-1>; 180%% CertificateEntry certificate_list<0..2^24-1>; 181%% } Certificate; 182certificate(OwnCert, CertDbHandle, CertDbRef, _CRContext, Role) -> 183 case ssl_certificate:certificate_chain(OwnCert, CertDbHandle, CertDbRef) of 184 {ok, _, Chain} -> 185 CertList = chain_to_cert_list(Chain), 186 %% If this message is in response to a CertificateRequest, the value of 187 %% certificate_request_context in that message. Otherwise (in the case 188 %%of server authentication), this field SHALL be zero length. 189 {ok, #certificate_1_3{ 190 certificate_request_context = <<>>, 191 certificate_list = CertList}}; 192 {error, Error} when Role =:= server -> 193 {error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {no_suitable_certificates, Error})}; 194 {error, _Error} when Role =:= client -> 195 %% The client MUST send a Certificate message if and only if the server 196 %% has requested client authentication via a CertificateRequest message 197 %% (Section 4.3.2). If the server requests client authentication but no 198 %% suitable certificate is available, the client MUST send a Certificate 199 %% message containing no certificates (i.e., with the "certificate_list" 200 %% field having length 0). 201 {ok, #certificate_1_3{ 202 certificate_request_context = <<>>, 203 certificate_list = []}} 204 end. 205 206 207certificate_verify(PrivateKey, SignatureScheme, 208 #state{connection_states = ConnectionStates, 209 handshake_env = 210 #handshake_env{ 211 tls_handshake_history = {Messages, _}}}, Role) -> 212 #{security_parameters := SecParamsR} = 213 ssl_record:pending_connection_state(ConnectionStates, write), 214 #security_parameters{prf_algorithm = HKDFAlgo} = SecParamsR, 215 216 {HashAlgo, _, _} = 217 ssl_cipher:scheme_to_components(SignatureScheme), 218 219 Context = lists:reverse(Messages), 220 221 %% Transcript-Hash uses the HKDF hash function defined by the cipher suite. 222 THash = tls_v1:transcript_hash(Context, HKDFAlgo), 223 ContextString = context_string(Role), 224 225 %% Digital signatures use the hash function defined by the selected signature 226 %% scheme. 227 case sign(THash, ContextString, HashAlgo, PrivateKey) of 228 {ok, Signature} -> 229 {ok, #certificate_verify_1_3{ 230 algorithm = SignatureScheme, 231 signature = Signature 232 }}; 233 {error, #alert{} = Alert} -> 234 {error, Alert} 235 end. 236 237 238finished(#state{connection_states = ConnectionStates, 239 handshake_env = 240 #handshake_env{ 241 tls_handshake_history = {Messages, _}}}) -> 242 #{security_parameters := SecParamsR, 243 cipher_state := #cipher_state{finished_key = FinishedKey}} = 244 ssl_record:current_connection_state(ConnectionStates, write), 245 #security_parameters{prf_algorithm = HKDFAlgo} = SecParamsR, 246 247 VerifyData = tls_v1:finished_verify_data(FinishedKey, HKDFAlgo, Messages), 248 249 #finished{ 250 verify_data = VerifyData 251 }. 252 253 254key_update(Type) -> 255 #key_update{request_update = Type}. 256 257 258%%==================================================================== 259%% Encode handshake 260%%==================================================================== 261 262encode_handshake(#certificate_request_1_3{ 263 certificate_request_context = Context, 264 extensions = Exts})-> 265 EncContext = encode_cert_req_context(Context), 266 BinExts = encode_extensions(Exts), 267 {?CERTIFICATE_REQUEST, <<EncContext/binary, BinExts/binary>>}; 268encode_handshake(#certificate_1_3{ 269 certificate_request_context = Context, 270 certificate_list = Entries}) -> 271 EncContext = encode_cert_req_context(Context), 272 EncEntries = encode_cert_entries(Entries), 273 {?CERTIFICATE, <<EncContext/binary, EncEntries/binary>>}; 274encode_handshake(#certificate_verify_1_3{ 275 algorithm = Algorithm, 276 signature = Signature}) -> 277 EncAlgo = encode_algorithm(Algorithm), 278 EncSign = encode_signature(Signature), 279 {?CERTIFICATE_VERIFY, <<EncAlgo/binary, EncSign/binary>>}; 280encode_handshake(#encrypted_extensions{extensions = Exts})-> 281 {?ENCRYPTED_EXTENSIONS, encode_extensions(Exts)}; 282encode_handshake(#new_session_ticket{ 283 ticket_lifetime = LifeTime, 284 ticket_age_add = Age, 285 ticket_nonce = Nonce, 286 ticket = Ticket, 287 extensions = Exts}) -> 288 TicketSize = byte_size(Ticket), 289 NonceSize = byte_size(Nonce), 290 BinExts = encode_extensions(Exts), 291 {?NEW_SESSION_TICKET, <<?UINT32(LifeTime), ?UINT32(Age), 292 ?BYTE(NonceSize), Nonce/binary, 293 ?UINT16(TicketSize), Ticket/binary, 294 BinExts/binary>>}; 295encode_handshake(#end_of_early_data{}) -> 296 {?END_OF_EARLY_DATA, <<>>}; 297encode_handshake(#key_update{request_update = Update}) -> 298 EncUpdate = encode_key_update(Update), 299 {?KEY_UPDATE, <<EncUpdate/binary>>}; 300encode_handshake(HandshakeMsg) -> 301 ssl_handshake:encode_handshake(HandshakeMsg, {3,4}). 302 303 304%%==================================================================== 305%% Decode handshake 306%%==================================================================== 307 308 309decode_handshake(?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, 310 ?BYTE(SID_length), Session_ID:SID_length/binary, 311 Cipher_suite:2/binary, ?BYTE(Comp_method), 312 ?UINT16(ExtLen), Extensions:ExtLen/binary>>) 313 when Random =:= ?HELLO_RETRY_REQUEST_RANDOM -> 314 HelloExtensions = ssl_handshake:decode_hello_extensions(Extensions, {3,4}, {Major, Minor}, 315 hello_retry_request), 316 #server_hello{ 317 server_version = {Major,Minor}, 318 random = Random, 319 session_id = Session_ID, 320 cipher_suite = Cipher_suite, 321 compression_method = Comp_method, 322 extensions = HelloExtensions}; 323decode_handshake(?CERTIFICATE_REQUEST, <<?BYTE(0), ?UINT16(Size), EncExts:Size/binary>>) -> 324 Exts = decode_extensions(EncExts, certificate_request), 325 #certificate_request_1_3{ 326 certificate_request_context = <<>>, 327 extensions = Exts}; 328decode_handshake(?CERTIFICATE_REQUEST, <<?BYTE(CSize), Context:CSize/binary, 329 ?UINT16(Size), EncExts:Size/binary>>) -> 330 Exts = decode_extensions(EncExts, certificate_request), 331 #certificate_request_1_3{ 332 certificate_request_context = Context, 333 extensions = Exts}; 334decode_handshake(?CERTIFICATE, <<?BYTE(0), ?UINT24(Size), Certs:Size/binary>>) -> 335 CertList = decode_cert_entries(Certs), 336 #certificate_1_3{ 337 certificate_request_context = <<>>, 338 certificate_list = CertList 339 }; 340decode_handshake(?CERTIFICATE, <<?BYTE(CSize), Context:CSize/binary, 341 ?UINT24(Size), Certs:Size/binary>>) -> 342 CertList = decode_cert_entries(Certs), 343 #certificate_1_3{ 344 certificate_request_context = Context, 345 certificate_list = CertList 346 }; 347decode_handshake(?CERTIFICATE_VERIFY, <<?UINT16(EncAlgo), ?UINT16(Size), Signature:Size/binary>>) -> 348 Algorithm = ssl_cipher:signature_scheme(EncAlgo), 349 #certificate_verify_1_3{ 350 algorithm = Algorithm, 351 signature = Signature}; 352decode_handshake(?ENCRYPTED_EXTENSIONS, <<?UINT16(Size), EncExts:Size/binary>>) -> 353 #encrypted_extensions{ 354 extensions = decode_extensions(EncExts, encrypted_extensions) 355 }; 356decode_handshake(?NEW_SESSION_TICKET, <<?UINT32(LifeTime), ?UINT32(Age), 357 ?BYTE(NonceSize), Nonce:NonceSize/binary, 358 ?UINT16(TicketSize), Ticket:TicketSize/binary, 359 ?UINT16(BinExtSize), BinExts:BinExtSize/binary>>) -> 360 Exts = decode_extensions(BinExts, encrypted_extensions), 361 #new_session_ticket{ticket_lifetime = LifeTime, 362 ticket_age_add = Age, 363 ticket_nonce = Nonce, 364 ticket = Ticket, 365 extensions = Exts}; 366decode_handshake(?END_OF_EARLY_DATA, _) -> 367 #end_of_early_data{}; 368decode_handshake(?KEY_UPDATE, <<?BYTE(Update)>>) -> 369 #key_update{request_update = decode_key_update(Update)}; 370decode_handshake(Tag, HandshakeMsg) -> 371 ssl_handshake:decode_handshake({3,4}, Tag, HandshakeMsg). 372 373is_valid_binder(Binder, HHistory, PSK, Hash) -> 374 case HHistory of 375 [ClientHello2, HRR, MessageHash|_] -> 376 Truncated = truncate_client_hello(ClientHello2), 377 FinishedKey = calculate_finished_key(PSK, Hash), 378 Binder == calculate_binder(FinishedKey, Hash, [MessageHash, HRR, Truncated]); 379 [ClientHello1|_] -> 380 Truncated = truncate_client_hello(ClientHello1), 381 FinishedKey = calculate_finished_key(PSK, Hash), 382 Binder == calculate_binder(FinishedKey, Hash, Truncated) 383 end. 384 385%%-------------------------------------------------------------------- 386%%% Internal functions 387%%-------------------------------------------------------------------- 388encode_cert_req_context(<<>>) -> 389 <<?BYTE(0)>>; 390encode_cert_req_context(Bin) -> 391 Size = byte_size(Bin), 392 <<?BYTE(Size), Bin/binary>>. 393 394encode_cert_entries(Entries) -> 395 CertEntryList = encode_cert_entries(Entries, []), 396 Size = byte_size(CertEntryList), 397 <<?UINT24(Size), CertEntryList/binary>>. 398 399encode_cert_entries([], Acc) -> 400 iolist_to_binary(lists:reverse(Acc)); 401encode_cert_entries([#certificate_entry{data = Data, 402 extensions = Exts} | Rest], Acc) -> 403 DSize = byte_size(Data), 404 BinExts = encode_extensions(Exts), 405 encode_cert_entries(Rest, 406 [<<?UINT24(DSize), Data/binary, BinExts/binary>> | Acc]). 407 408encode_algorithm(Algo) -> 409 Scheme = ssl_cipher:signature_scheme(Algo), 410 <<?UINT16(Scheme)>>. 411 412encode_signature(Signature) -> 413 Size = byte_size(Signature), 414 <<?UINT16(Size), Signature/binary>>. 415 416encode_key_update(update_not_requested) -> 417 <<?BYTE(0)>>; 418encode_key_update(update_requested) -> 419 <<?BYTE(1)>>. 420 421%% enum { 422%% update_not_requested(0), update_requested(1), (255) 423%% } KeyUpdateRequest; 424%% 425%% request_update: Indicates whether the recipient of the KeyUpdate 426%% should respond with its own KeyUpdate. If an implementation 427%% receives any other value, it MUST terminate the connection with an 428%% "illegal_parameter" alert. 429decode_key_update(0) -> 430 update_not_requested; 431decode_key_update(1) -> 432 update_requested; 433decode_key_update(N) -> 434 throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, {request_update,N})). 435 436decode_cert_entries(Entries) -> 437 decode_cert_entries(Entries, []). 438 439decode_cert_entries(<<>>, Acc) -> 440 lists:reverse(Acc); 441decode_cert_entries(<<?UINT24(DSize), Data:DSize/binary, ?UINT16(Esize), BinExts:Esize/binary, 442 Rest/binary>>, Acc) -> 443 Exts = decode_extensions(BinExts, certificate_request), 444 decode_cert_entries(Rest, [#certificate_entry{data = Data, 445 extensions = Exts} | Acc]). 446 447encode_extensions(Exts)-> 448 ssl_handshake:encode_extensions(extensions_list(Exts)). 449 450decode_extensions(Exts, MessageType) -> 451 ssl_handshake:decode_extensions(Exts, {3,4}, MessageType). 452 453extensions_list(HelloExtensions) -> 454 [Ext || {_, Ext} <- maps:to_list(HelloExtensions)]. 455 456 457%% TODO: add extensions! 458chain_to_cert_list(L) -> 459 chain_to_cert_list(L, []). 460%% 461chain_to_cert_list([], Acc) -> 462 lists:reverse(Acc); 463chain_to_cert_list([H|T], Acc) -> 464 chain_to_cert_list(T, [certificate_entry(H)|Acc]). 465 466 467certificate_entry(DER) -> 468 #certificate_entry{ 469 data = DER, 470 extensions = #{} %% Extensions not supported. 471 }. 472 473%% The digital signature is then computed over the concatenation of: 474%% - A string that consists of octet 32 (0x20) repeated 64 times 475%% - The context string 476%% - A single 0 byte which serves as the separator 477%% - The content to be signed 478%% 479%% For example, if the transcript hash was 32 bytes of 01 (this length 480%% would make sense for SHA-256), the content covered by the digital 481%% signature for a server CertificateVerify would be: 482%% 483%% 2020202020202020202020202020202020202020202020202020202020202020 484%% 2020202020202020202020202020202020202020202020202020202020202020 485%% 544c5320312e332c207365727665722043657274696669636174655665726966 486%% 79 487%% 00 488%% 0101010101010101010101010101010101010101010101010101010101010101 489sign(THash, Context, HashAlgo, #'ECPrivateKey'{} = PrivateKey) -> 490 Content = build_content(Context, THash), 491 try public_key:sign(Content, HashAlgo, PrivateKey) of 492 Signature -> 493 {ok, Signature} 494 catch 495 error:badarg -> 496 {error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, badarg)} 497 end; 498sign(THash, Context, HashAlgo, PrivateKey) -> 499 Content = build_content(Context, THash), 500 501 %% The length of the Salt MUST be equal to the length of the output 502 %% of the digest algorithm: rsa_pss_saltlen = -1 503 try public_key:sign(Content, HashAlgo, PrivateKey, 504 [{rsa_padding, rsa_pkcs1_pss_padding}, 505 {rsa_pss_saltlen, -1}, 506 {rsa_mgf1_md, HashAlgo}]) of 507 Signature -> 508 {ok, Signature} 509 catch 510 error:badarg -> 511 {error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, badarg)} 512 end. 513 514 515verify(THash, Context, HashAlgo, Signature, {?'id-ecPublicKey', PublicKey, PublicKeyParams}) -> 516 Content = build_content(Context, THash), 517 try public_key:verify(Content, HashAlgo, Signature, {PublicKey, PublicKeyParams}) of 518 Result -> 519 {ok, Result} 520 catch 521 error:badarg -> 522 {error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, badarg)} 523 end; 524verify(THash, Context, HashAlgo, Signature, {?rsaEncryption, PublicKey, _PubKeyParams}) -> 525 Content = build_content(Context, THash), 526 527 %% The length of the Salt MUST be equal to the length of the output 528 %% of the digest algorithm: rsa_pss_saltlen = -1 529 try public_key:verify(Content, HashAlgo, Signature, PublicKey, 530 [{rsa_padding, rsa_pkcs1_pss_padding}, 531 {rsa_pss_saltlen, -1}, 532 {rsa_mgf1_md, HashAlgo}]) of 533 Result -> 534 {ok, Result} 535 catch 536 error:badarg -> 537 {error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, badarg)} 538 end. 539 540 541build_content(Context, THash) -> 542 Prefix = binary:copy(<<32>>, 64), 543 <<Prefix/binary,Context/binary,?BYTE(0),THash/binary>>. 544 545 546%%==================================================================== 547%% Handle handshake messages 548%%==================================================================== 549 550 551%% TLS Server 552do_start(#client_hello{cipher_suites = ClientCiphers, 553 session_id = SessionId, 554 extensions = Extensions} = _Hello, 555 #state{connection_states = _ConnectionStates0, 556 ssl_options = #{ciphers := ServerCiphers, 557 signature_algs := ServerSignAlgs, 558 supported_groups := ServerGroups0, 559 alpn_preferred_protocols := ALPNPreferredProtocols, 560 honor_cipher_order := HonorCipherOrder}, 561 session = #session{own_certificate = Cert}} = State0) -> 562 ClientGroups0 = maps:get(elliptic_curves, Extensions, undefined), 563 ClientGroups = get_supported_groups(ClientGroups0), 564 ServerGroups = get_supported_groups(ServerGroups0), 565 566 ClientShares0 = maps:get(key_share, Extensions, undefined), 567 ClientShares = get_key_shares(ClientShares0), 568 569 OfferedPSKs = get_offered_psks(Extensions), 570 571 ClientALPN0 = maps:get(alpn, Extensions, undefined), 572 ClientALPN = ssl_handshake:decode_alpn(ClientALPN0), 573 574 ClientSignAlgs = get_signature_scheme_list( 575 maps:get(signature_algs, Extensions, undefined)), 576 ClientSignAlgsCert = get_signature_scheme_list( 577 maps:get(signature_algs_cert, Extensions, undefined)), 578 579 {Ref,Maybe} = maybe(), 580 581 try 582 %% Handle ALPN extension if ALPN is configured 583 ALPNProtocol = Maybe(handle_alpn(ALPNPreferredProtocols, ClientALPN)), 584 585 %% If the server does not select a PSK, then the server independently selects a 586 %% cipher suite, an (EC)DHE group and key share for key establishment, 587 %% and a signature algorithm/certificate pair to authenticate itself to 588 %% the client. 589 Cipher = Maybe(select_cipher_suite(HonorCipherOrder, ClientCiphers, ServerCiphers)), 590 591 Groups = Maybe(select_common_groups(ServerGroups, ClientGroups)), 592 Maybe(validate_client_key_share(ClientGroups, ClientShares)), 593 594 {PublicKeyAlgo, SignAlgo, SignHash} = get_certificate_params(Cert), 595 596 %% Check if client supports signature algorithm of server certificate 597 Maybe(check_cert_sign_algo(SignAlgo, SignHash, ClientSignAlgs, ClientSignAlgsCert)), 598 599 %% Select signature algorithm (used in CertificateVerify message). 600 SelectedSignAlg = Maybe(select_sign_algo(PublicKeyAlgo, ClientSignAlgs, ServerSignAlgs)), 601 602 %% Select client public key. If no public key found in ClientShares or 603 %% ClientShares is empty, trigger HelloRetryRequest as we were able 604 %% to find an acceptable set of parameters but the ClientHello does not 605 %% contain sufficient information. 606 {Group, ClientPubKey} = get_client_public_key(Groups, ClientShares), 607 608 %% Generate server_share 609 KeyShare = ssl_cipher:generate_server_share(Group), 610 611 State1 = update_start_state(State0, 612 #{cipher => Cipher, 613 key_share => KeyShare, 614 session_id => SessionId, 615 group => Group, 616 sign_alg => SelectedSignAlg, 617 peer_public_key => ClientPubKey, 618 alpn => ALPNProtocol}), 619 620 %% 4.1.4. Hello Retry Request 621 %% 622 %% The server will send this message in response to a ClientHello 623 %% message if it is able to find an acceptable set of parameters but the 624 %% ClientHello does not contain sufficient information to proceed with 625 %% the handshake. 626 case Maybe(send_hello_retry_request(State1, ClientPubKey, KeyShare, SessionId)) of 627 {_, start} = NextStateTuple -> 628 NextStateTuple; 629 {_, negotiated} = NextStateTuple -> 630 %% Exclude any incompatible PSKs. 631 PSK = Maybe(handle_pre_shared_key(State1, OfferedPSKs, Cipher)), 632 Maybe(session_resumption(NextStateTuple, PSK)) 633 end 634 catch 635 {Ref, #alert{} = Alert} -> 636 Alert 637 end; 638%% TLS Client 639do_start(#server_hello{cipher_suite = SelectedCipherSuite, 640 session_id = SessionId, 641 extensions = Extensions}, 642 #state{static_env = #static_env{role = client, 643 host = Host, 644 port = Port, 645 transport_cb = Transport, 646 socket = Socket}, 647 handshake_env = #handshake_env{renegotiation = {Renegotiation, _}} = HsEnv, 648 connection_env = #connection_env{negotiated_version = NegotiatedVersion}, 649 ssl_options = #{ciphers := ClientCiphers, 650 supported_groups := ClientGroups0, 651 use_ticket := UseTicket, 652 session_tickets := SessionTickets, 653 log_level := LogLevel} = SslOpts, 654 session = #session{own_certificate = Cert} = Session0, 655 connection_states = ConnectionStates0 656 } = State0) -> 657 ClientGroups = get_supported_groups(ClientGroups0), 658 659 {Ref,Maybe} = maybe(), 660 try 661 ServerKeyShare = maps:get(key_share, Extensions, undefined), 662 SelectedGroup = get_selected_group(ServerKeyShare), 663 664 %% Upon receipt of this extension in a HelloRetryRequest, the client 665 %% MUST verify that (1) the selected_group field corresponds to a group 666 %% which was provided in the "supported_groups" extension in the 667 %% original ClientHello and (2) the selected_group field does not 668 %% correspond to a group which was provided in the "key_share" extension 669 %% in the original ClientHello. If either of these checks fails, then 670 %% the client MUST abort the handshake with an "illegal_parameter" 671 %% alert. 672 Maybe(validate_selected_group(SelectedGroup, ClientGroups)), 673 674 Maybe(validate_cipher_suite(SelectedCipherSuite, ClientCiphers)), 675 676 %% Otherwise, when sending the new ClientHello, the client MUST 677 %% replace the original "key_share" extension with one containing only a 678 %% new KeyShareEntry for the group indicated in the selected_group field 679 %% of the triggering HelloRetryRequest. 680 ClientKeyShare = ssl_cipher:generate_client_shares([SelectedGroup]), 681 TicketData = get_ticket_data(self(), SessionTickets, UseTicket), 682 Hello0 = tls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts, 683 SessionId, Renegotiation, Cert, ClientKeyShare, 684 TicketData), 685 686 %% Update state 687 State1 = update_start_state(State0, 688 #{cipher => SelectedCipherSuite, 689 key_share => ClientKeyShare, 690 session_id => SessionId, 691 group => SelectedGroup}), 692 693 %% Replace ClientHello1 with a special synthetic handshake message 694 State2 = replace_ch1_with_message_hash(State1), 695 #state{handshake_env = #handshake_env{tls_handshake_history = HHistory0}} = State2, 696 697 %% Update pre_shared_key extension with binders (TLS 1.3) 698 Hello = tls_handshake_1_3:maybe_add_binders(Hello0, HHistory0, TicketData, NegotiatedVersion), 699 700 {BinMsg, ConnectionStates, HHistory} = 701 tls_connection:encode_handshake(Hello, NegotiatedVersion, ConnectionStates0, HHistory0), 702 tls_socket:send(Transport, Socket, BinMsg), 703 ssl_logger:debug(LogLevel, outbound, 'handshake', Hello), 704 ssl_logger:debug(LogLevel, outbound, 'record', BinMsg), 705 706 State = State2#state{ 707 connection_states = ConnectionStates, 708 session = Session0#session{session_id = Hello#client_hello.session_id}, 709 handshake_env = HsEnv#handshake_env{tls_handshake_history = HHistory}, 710 key_share = ClientKeyShare}, 711 712 {State, wait_sh} 713 714 catch 715 {Ref, #alert{} = Alert} -> 716 Alert 717 end. 718 719 720do_negotiated({start_handshake, PSK0}, 721 #state{connection_states = ConnectionStates0, 722 session = #session{session_id = SessionId, 723 ecc = SelectedGroup, 724 dh_public_value = ClientPublicKey}, 725 ssl_options = #{} = SslOpts, 726 key_share = KeyShare} = State0) -> 727 ServerPrivateKey = get_server_private_key(KeyShare), 728 729 #{security_parameters := SecParamsR} = 730 ssl_record:pending_connection_state(ConnectionStates0, read), 731 #security_parameters{prf_algorithm = HKDF} = SecParamsR, 732 733 734 {Ref,Maybe} = maybe(), 735 try 736 %% Create server_hello 737 ServerHello = server_hello(server_hello, SessionId, KeyShare, PSK0, ConnectionStates0), 738 739 {State1, _} = tls_connection:send_handshake(ServerHello, State0), 740 741 PSK = get_pre_shared_key(PSK0, HKDF), 742 743 State2 = 744 calculate_handshake_secrets(ClientPublicKey, ServerPrivateKey, SelectedGroup, 745 PSK, State1), 746 747 State3 = ssl_record:step_encryption_state(State2), 748 749 %% Create EncryptedExtensions 750 EncryptedExtensions = encrypted_extensions(State2), 751 752 %% Encode EncryptedExtensions 753 State4 = tls_connection:queue_handshake(EncryptedExtensions, State3), 754 755 %% Create and send CertificateRequest ({verify, verify_peer}) 756 {State5, NextState} = maybe_send_certificate_request(State4, SslOpts, PSK0), 757 758 %% Create and send Certificate (if PSK is undefined) 759 State6 = Maybe(maybe_send_certificate(State5, PSK0)), 760 761 %% Create and send CertificateVerify (if PSK is undefined) 762 State7 = Maybe(maybe_send_certificate_verify(State6, PSK0)), 763 764 %% Create Finished 765 Finished = finished(State7), 766 767 %% Encode Finished 768 State8 = tls_connection:queue_handshake(Finished, State7), 769 770 %% Send first flight 771 {State9, _} = tls_connection:send_handshake_flight(State8), 772 773 {State9, NextState} 774 775 catch 776 {Ref, #alert{} = Alert} -> 777 Alert 778 end. 779 780 781do_wait_cert(#certificate_1_3{} = Certificate, State0) -> 782 {Ref,Maybe} = maybe(), 783 try 784 Maybe(process_certificate(Certificate, State0)) 785 catch 786 {Ref, #alert{} = Alert} -> 787 {Alert, State0}; 788 {Ref, {#alert{} = Alert, State}} -> 789 {Alert, State} 790 end. 791 792 793do_wait_cv(#certificate_verify_1_3{} = CertificateVerify, State0) -> 794 {Ref,Maybe} = maybe(), 795 try 796 State1 = Maybe(verify_signature_algorithm(State0, CertificateVerify)), 797 Maybe(verify_certificate_verify(State1, CertificateVerify)) 798 catch 799 {Ref, {#alert{} = Alert, State}} -> 800 {Alert, State} 801 end. 802 803%% TLS Server 804do_wait_finished(#finished{verify_data = VerifyData}, 805 #state{static_env = #static_env{role = server}} = State0) -> 806 {Ref,Maybe} = maybe(), 807 808 try 809 Maybe(validate_finished(State0, VerifyData)), 810 811 State1 = calculate_traffic_secrets(State0), 812 State2 = maybe_calculate_resumption_master_secret(State1), 813 State3 = forget_master_secret(State2), 814 815 %% Configure traffic keys 816 State4 = ssl_record:step_encryption_state(State3), 817 818 %% Send session ticket 819 maybe_send_session_ticket(State4) 820 821 catch 822 {Ref, #alert{} = Alert} -> 823 Alert 824 end; 825%% TLS Client 826do_wait_finished(#finished{verify_data = VerifyData}, 827 #state{static_env = #static_env{role = client}} = State0) -> 828 829 {Ref,Maybe} = maybe(), 830 831 try 832 Maybe(validate_finished(State0, VerifyData)), 833 834 %% Maybe send Certificate + CertificateVerify 835 State1 = Maybe(maybe_queue_cert_cert_cv(State0)), 836 837 Finished = finished(State1), 838 839 %% Encode Finished 840 State2 = tls_connection:queue_handshake(Finished, State1), 841 842 %% Send first flight 843 {State3, _} = tls_connection:send_handshake_flight(State2), 844 845 State4 = calculate_traffic_secrets(State3), 846 State5 = maybe_calculate_resumption_master_secret(State4), 847 State6 = forget_master_secret(State5), 848 849 %% Configure traffic keys 850 ssl_record:step_encryption_state(State6) 851 852 catch 853 {Ref, #alert{} = Alert} -> 854 Alert 855 end. 856 857 858do_wait_sh(#server_hello{cipher_suite = SelectedCipherSuite, 859 session_id = SessionId, 860 extensions = Extensions} = ServerHello, 861 #state{key_share = ClientKeyShare0, 862 ssl_options = #{ciphers := ClientCiphers, 863 supported_groups := ClientGroups0, 864 session_tickets := SessionTickets, 865 use_ticket := UseTicket}} = State0) -> 866 ClientGroups = get_supported_groups(ClientGroups0), 867 ServerKeyShare0 = maps:get(key_share, Extensions, undefined), 868 ServerPreSharedKey = maps:get(pre_shared_key, Extensions, undefined), 869 SelectedIdentity = get_selected_identity(ServerPreSharedKey), 870 ClientKeyShare = get_key_shares(ClientKeyShare0), 871 872 {Ref,Maybe} = maybe(), 873 try 874 %% Go to state 'start' if server replies with 'HelloRetryRequest'. 875 Maybe(maybe_hello_retry_request(ServerHello, State0)), 876 877 %% Resumption and PSK 878 State1 = handle_resumption(State0, SelectedIdentity), 879 ServerKeyShare = get_key_shares(ServerKeyShare0), 880 881 Maybe(validate_cipher_suite(SelectedCipherSuite, ClientCiphers)), 882 Maybe(validate_server_key_share(ClientGroups, ServerKeyShare)), 883 884 %% Get server public key 885 {SelectedGroup, ServerPublicKey} = get_server_public_key(ServerKeyShare), 886 887 {_, ClientPrivateKey} = get_client_private_key([SelectedGroup], ClientKeyShare), 888 889 %% Update state 890 State2 = update_start_state(State1, 891 #{cipher => SelectedCipherSuite, 892 key_share => ClientKeyShare0, 893 session_id => SessionId, 894 group => SelectedGroup, 895 peer_public_key => ServerPublicKey}), 896 897 #state{connection_states = ConnectionStates} = State2, 898 #{security_parameters := SecParamsR} = 899 ssl_record:pending_connection_state(ConnectionStates, read), 900 #security_parameters{prf_algorithm = HKDFAlgo} = SecParamsR, 901 902 PSK = Maybe(get_pre_shared_key(SessionTickets, UseTicket, HKDFAlgo, SelectedIdentity)), 903 State3 = calculate_handshake_secrets(ServerPublicKey, ClientPrivateKey, SelectedGroup, 904 PSK, State2), 905 State4 = ssl_record:step_encryption_state(State3), 906 907 {State4, wait_ee} 908 909 catch 910 {Ref, {State, StateName, ServerHello}} -> 911 {State, StateName, ServerHello}; 912 {Ref, #alert{} = Alert} -> 913 Alert 914 end. 915 916 917do_wait_ee(#encrypted_extensions{extensions = Extensions}, State0) -> 918 919 ALPNProtocol0 = maps:get(alpn, Extensions, undefined), 920 ALPNProtocol = get_alpn(ALPNProtocol0), 921 922 {Ref, Maybe} = maybe(), 923 924 try 925 %% Go to state 'wait_finished' if using PSK. 926 Maybe(maybe_resumption(State0)), 927 928 %% Update state 929 #state{handshake_env = HsEnv} = State0, 930 State1 = State0#state{handshake_env = HsEnv#handshake_env{alpn = ALPNProtocol}}, 931 932 {State1, wait_cert_cr} 933 catch 934 {Ref, {State, StateName}} -> 935 {State, StateName} 936 end. 937 938 939do_wait_cert_cr(#certificate_1_3{} = Certificate, State0) -> 940 {Ref,Maybe} = maybe(), 941 try 942 Maybe(process_certificate(Certificate, State0)) 943 catch 944 {Ref, #alert{} = Alert} -> 945 {Alert, State0}; 946 {Ref, {#alert{} = Alert, State}} -> 947 {Alert, State} 948 end; 949do_wait_cert_cr(#certificate_request_1_3{} = CertificateRequest, State0) -> 950 {Ref,Maybe} = maybe(), 951 try 952 Maybe(process_certificate_request(CertificateRequest, State0)) 953 catch 954 {Ref, #alert{} = Alert} -> 955 {Alert, State0} 956 end. 957 958 959%% For reasons of backward compatibility with middleboxes (see 960%% Appendix D.4), the HelloRetryRequest message uses the same structure 961%% as the ServerHello, but with Random set to the special value of the 962%% SHA-256 of "HelloRetryRequest": 963%% 964%% CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91 965%% C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C 966%% 967%% Upon receiving a message with type server_hello, implementations MUST 968%% first examine the Random value and, if it matches this value, process 969%% it as described in Section 4.1.4). 970maybe_hello_retry_request(#server_hello{random = ?HELLO_RETRY_REQUEST_RANDOM} = ServerHello, State0) -> 971 {error, {State0, start, ServerHello}}; 972maybe_hello_retry_request(_, _) -> 973 ok. 974 975 976maybe_resumption(#state{handshake_env = #handshake_env{resumption = true}} = State) -> 977 {error, {State, wait_finished}}; 978maybe_resumption(_) -> 979 ok. 980 981 982handle_resumption(State, undefined) -> 983 State; 984handle_resumption(#state{handshake_env = HSEnv0} = State, _) -> 985 HSEnv = HSEnv0#handshake_env{resumption = true}, 986 State#state{handshake_env = HSEnv}. 987 988 989maybe_queue_cert_cert_cv(#state{client_certificate_requested = false} = State) -> 990 {ok, State}; 991maybe_queue_cert_cert_cv(#state{connection_states = _ConnectionStates0, 992 session = #session{session_id = _SessionId, 993 own_certificate = OwnCert}, 994 ssl_options = #{} = _SslOpts, 995 key_share = _KeyShare, 996 handshake_env = #handshake_env{tls_handshake_history = _HHistory0}, 997 static_env = #static_env{ 998 role = client, 999 cert_db = CertDbHandle, 1000 cert_db_ref = CertDbRef, 1001 socket = _Socket, 1002 transport_cb = _Transport} 1003 } = State0) -> 1004 {Ref,Maybe} = maybe(), 1005 try 1006 %% Create Certificate 1007 Certificate = Maybe(certificate(OwnCert, CertDbHandle, CertDbRef, <<>>, client)), 1008 1009 %% Encode Certificate 1010 State1 = tls_connection:queue_handshake(Certificate, State0), 1011 1012 %% Maybe create and queue CertificateVerify 1013 State = Maybe(maybe_queue_cert_verify(Certificate, State1)), 1014 {ok, State} 1015 catch 1016 {Ref, #alert{} = Alert} -> 1017 {error, Alert} 1018 end. 1019 1020 1021%% Clients MUST send this message whenever authenticating via a certificate 1022%% (i.e., when the Certificate message is non-empty). 1023maybe_queue_cert_verify(#certificate_1_3{certificate_list = []}, State) -> 1024 {ok, State}; 1025maybe_queue_cert_verify(_Certificate, 1026 #state{connection_states = _ConnectionStates0, 1027 session = #session{sign_alg = SignatureScheme}, 1028 connection_env = #connection_env{private_key = CertPrivateKey}, 1029 static_env = #static_env{role = client} 1030 } = State) -> 1031 {Ref,Maybe} = maybe(), 1032 try 1033 CertificateVerify = Maybe(certificate_verify(CertPrivateKey, SignatureScheme, State, client)), 1034 {ok, tls_connection:queue_handshake(CertificateVerify, State)} 1035 catch 1036 {Ref, #alert{} = Alert} -> 1037 {error, Alert} 1038 end. 1039 1040 1041%% Recipients of Finished messages MUST verify that the contents are 1042%% correct and if incorrect MUST terminate the connection with a 1043%% "decrypt_error" alert. 1044validate_finished(#state{connection_states = ConnectionStates, 1045 handshake_env = 1046 #handshake_env{ 1047 tls_handshake_history = {Messages0, _}}}, VerifyData) -> 1048 #{security_parameters := SecParamsR, 1049 cipher_state := #cipher_state{finished_key = FinishedKey}} = 1050 ssl_record:current_connection_state(ConnectionStates, read), 1051 #security_parameters{prf_algorithm = HKDFAlgo} = SecParamsR, 1052 1053 %% Drop the peer's finished message, it is not part of the handshake context 1054 %% when the client/server calculates its finished message. 1055 [_|Messages] = Messages0, 1056 1057 ControlData = tls_v1:finished_verify_data(FinishedKey, HKDFAlgo, Messages), 1058 compare_verify_data(ControlData, VerifyData). 1059 1060 1061compare_verify_data(Data, Data) -> 1062 ok; 1063compare_verify_data(_, _) -> 1064 {error, ?ALERT_REC(?FATAL, ?DECRYPT_ERROR, decrypt_error)}. 1065 1066 1067send_hello_retry_request(#state{connection_states = ConnectionStates0} = State0, 1068 no_suitable_key, KeyShare, SessionId) -> 1069 ServerHello = server_hello(hello_retry_request, SessionId, KeyShare, undefined, ConnectionStates0), 1070 {State1, _} = tls_connection:send_handshake(ServerHello, State0), 1071 1072 %% Update handshake history 1073 State2 = replace_ch1_with_message_hash(State1), 1074 1075 {ok, {State2, start}}; 1076send_hello_retry_request(State0, _, _, _) -> 1077 %% Suitable key found. 1078 {ok, {State0, negotiated}}. 1079 1080session_resumption({#state{ssl_options = #{session_tickets := disabled}} = State, negotiated}, _) -> 1081 {ok, {State, negotiated}}; 1082session_resumption({#state{ssl_options = #{session_tickets := Tickets}} = State, negotiated}, undefined) 1083 when Tickets =/= disabled -> 1084 {ok, {State, negotiated}}; 1085session_resumption({#state{ssl_options = #{session_tickets := Tickets}} = State0, negotiated}, PSK) 1086 when Tickets =/= disabled -> 1087 State = handle_resumption(State0, ok), 1088 {ok, {State, negotiated, PSK}}. 1089 1090 1091%% Do not send CR during session resumption 1092maybe_send_certificate_request(State, _, PSK) when PSK =/= undefined -> 1093 {State, wait_finished}; 1094maybe_send_certificate_request(State, #{verify := verify_none}, _) -> 1095 {State, wait_finished}; 1096maybe_send_certificate_request(State, #{verify := verify_peer, 1097 signature_algs := SignAlgs, 1098 signature_algs_cert := SignAlgsCert}, _) -> 1099 CertificateRequest = certificate_request(SignAlgs, SignAlgsCert), 1100 {tls_connection:queue_handshake(CertificateRequest, State), wait_cert}. 1101 1102 1103maybe_send_certificate(State, PSK) when PSK =/= undefined -> 1104 {ok, State}; 1105maybe_send_certificate(#state{session = #session{own_certificate = OwnCert}, 1106 static_env = #static_env{ 1107 cert_db = CertDbHandle, 1108 cert_db_ref = CertDbRef}} = State, _) -> 1109 case certificate(OwnCert, CertDbHandle, CertDbRef, <<>>, server) of 1110 {ok, Certificate} -> 1111 {ok, tls_connection:queue_handshake(Certificate, State)}; 1112 Error -> 1113 Error 1114 end. 1115 1116 1117maybe_send_certificate_verify(State, PSK) when PSK =/= undefined -> 1118 {ok, State}; 1119maybe_send_certificate_verify(#state{session = #session{sign_alg = SignatureScheme}, 1120 connection_env = #connection_env{ 1121 private_key = CertPrivateKey}} = State, _) -> 1122 case certificate_verify(CertPrivateKey, SignatureScheme, State, server) of 1123 {ok, CertificateVerify} -> 1124 {ok, tls_connection:queue_handshake(CertificateVerify, State)}; 1125 Error -> 1126 Error 1127 end. 1128 1129 1130maybe_send_session_ticket(State) -> 1131 Number = case application:get_env(ssl, server_session_tickets_amount) of 1132 {ok, Size} when is_integer(Size) andalso 1133 Size > 0 -> 1134 Size; 1135 _ -> 1136 3 1137 end, 1138 maybe_send_session_ticket(State, Number). 1139%% 1140maybe_send_session_ticket(#state{ssl_options = #{session_tickets := disabled}} = State, _) -> 1141 %% Do nothing! 1142 State; 1143maybe_send_session_ticket(State, 0) -> 1144 State; 1145maybe_send_session_ticket(#state{connection_states = ConnectionStates, 1146 static_env = #static_env{trackers = Trackers}} = State0, N) -> 1147 Tracker = proplists:get_value(session_tickets_tracker, Trackers), 1148 #{security_parameters := SecParamsR} = 1149 ssl_record:current_connection_state(ConnectionStates, read), 1150 #security_parameters{prf_algorithm = HKDF, 1151 resumption_master_secret = RMS} = SecParamsR, 1152 Ticket = tls_server_session_ticket:new(Tracker, HKDF, RMS), 1153 {State, _} = tls_connection:send_handshake(Ticket, State0), 1154 maybe_send_session_ticket(State, N - 1). 1155 1156process_certificate_request(#certificate_request_1_3{}, 1157 #state{session = #session{own_certificate = undefined}} = State) -> 1158 {ok, {State#state{client_certificate_requested = true}, wait_cert}}; 1159 1160process_certificate_request(#certificate_request_1_3{ 1161 extensions = Extensions}, 1162 #state{session = #session{own_certificate = Cert} = Session} = State) -> 1163 ServerSignAlgs = get_signature_scheme_list( 1164 maps:get(signature_algs, Extensions, undefined)), 1165 ServerSignAlgsCert = get_signature_scheme_list( 1166 maps:get(signature_algs_cert, Extensions, undefined)), 1167 1168 {_PublicKeyAlgo, SignAlgo, SignHash} = get_certificate_params(Cert), 1169 1170 %% Check if server supports signature algorithm of client certificate 1171 case check_cert_sign_algo(SignAlgo, SignHash, ServerSignAlgs, ServerSignAlgsCert) of 1172 ok -> 1173 {ok, {State#state{client_certificate_requested = true}, wait_cert}}; 1174 {error, _} -> 1175 %% Certificate not supported: send empty certificate in state 'wait_finished' 1176 {ok, {State#state{client_certificate_requested = true, 1177 session = Session#session{own_certificate = undefined}}, wait_cert}} 1178 end. 1179 1180 1181process_certificate(#certificate_1_3{ 1182 certificate_request_context = <<>>, 1183 certificate_list = []}, 1184 #state{ssl_options = 1185 #{fail_if_no_peer_cert := false}} = State) -> 1186 {ok, {State, wait_finished}}; 1187process_certificate(#certificate_1_3{ 1188 certificate_request_context = <<>>, 1189 certificate_list = []}, 1190 #state{ssl_options = 1191 #{fail_if_no_peer_cert := true}} = State0) -> 1192 1193 %% At this point the client believes that the connection is up and starts using 1194 %% its traffic secrets. In order to be able send an proper Alert to the client 1195 %% the server should also change its connection state and use the traffic 1196 %% secrets. 1197 State1 = calculate_traffic_secrets(State0), 1198 State = ssl_record:step_encryption_state(State1), 1199 {error, {?ALERT_REC(?FATAL, ?CERTIFICATE_REQUIRED, certificate_required), State}}; 1200process_certificate(#certificate_1_3{certificate_list = Certs0}, 1201 #state{ssl_options = 1202 #{signature_algs := SignAlgs, 1203 signature_algs_cert := SignAlgsCert} = SslOptions, 1204 static_env = 1205 #static_env{ 1206 role = Role, 1207 host = Host, 1208 cert_db = CertDbHandle, 1209 cert_db_ref = CertDbRef, 1210 crl_db = CRLDbHandle}} = State0) -> 1211 %% TODO: handle extensions! 1212 %% Remove extensions from list of certificates! 1213 Certs = convert_certificate_chain(Certs0), 1214 case is_supported_signature_algorithm(Certs, SignAlgs, SignAlgsCert) of 1215 true -> 1216 case validate_certificate_chain(Certs, CertDbHandle, CertDbRef, 1217 SslOptions, CRLDbHandle, Role, Host) of 1218 {ok, {PeerCert, PublicKeyInfo}} -> 1219 State = store_peer_cert(State0, PeerCert, PublicKeyInfo), 1220 {ok, {State, wait_cv}}; 1221 {error, Reason} -> 1222 State = update_encryption_state(Role, State0), 1223 {error, {Reason, State}}; 1224 {ok, #alert{} = Alert} -> 1225 State = update_encryption_state(Role, State0), 1226 {error, {Alert, State}} 1227 end; 1228 false -> 1229 State1 = calculate_traffic_secrets(State0), 1230 State = ssl_record:step_encryption_state(State1), 1231 {error, {?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, 1232 "Client certificate uses unsupported signature algorithm"), State}} 1233 end. 1234 1235 1236%% TODO: check whole chain! 1237is_supported_signature_algorithm(Certs, SignAlgs, undefined) -> 1238 is_supported_signature_algorithm(Certs, SignAlgs); 1239is_supported_signature_algorithm(Certs, _, SignAlgsCert) -> 1240 is_supported_signature_algorithm(Certs, SignAlgsCert). 1241%% 1242is_supported_signature_algorithm([BinCert|_], SignAlgs0) -> 1243 #'OTPCertificate'{signatureAlgorithm = SignAlg} = 1244 public_key:pkix_decode_cert(BinCert, otp), 1245 SignAlgs = filter_tls13_algs(SignAlgs0), 1246 Scheme = ssl_cipher:signature_algorithm_to_scheme(SignAlg), 1247 lists:member(Scheme, SignAlgs). 1248 1249 1250%% Sets correct encryption state when sending Alerts in shared states that use different secrets. 1251%% - If client: use handshake secrets. 1252%% - If server: use traffic secrets as by this time the client's state machine 1253%% already stepped into the 'connection' state. 1254update_encryption_state(server, State0) -> 1255 State1 = calculate_traffic_secrets(State0), 1256 ssl_record:step_encryption_state(State1); 1257update_encryption_state(client, State) -> 1258 State. 1259 1260 1261validate_certificate_chain(Certs, CertDbHandle, CertDbRef, 1262 #{server_name_indication := ServerNameIndication, 1263 partial_chain := PartialChain, 1264 verify_fun := VerifyFun, 1265 customize_hostname_check := CustomizeHostnameCheck, 1266 crl_check := CrlCheck, 1267 log_level := LogLevel, 1268 depth := Depth} = SslOptions, 1269 CRLDbHandle, Role, Host) -> 1270 ServerName = ssl_handshake:server_name(ServerNameIndication, Host, Role), 1271 [PeerCert | ChainCerts ] = Certs, 1272 try 1273 {TrustedCert, CertPath} = 1274 ssl_certificate:trusted_cert_and_path(Certs, CertDbHandle, CertDbRef, 1275 PartialChain), 1276 ValidationFunAndState = 1277 ssl_handshake:validation_fun_and_state(VerifyFun, Role, 1278 CertDbHandle, CertDbRef, ServerName, 1279 CustomizeHostnameCheck, 1280 CrlCheck, CRLDbHandle, CertPath, LogLevel), 1281 Options = [{max_path_length, Depth}, 1282 {verify_fun, ValidationFunAndState}], 1283 %% TODO: Validate if Certificate is using a supported signature algorithm 1284 %% (signature_algs_cert)! 1285 case public_key:pkix_path_validation(TrustedCert, CertPath, Options) of 1286 {ok, {PublicKeyInfo,_}} -> 1287 {ok, {PeerCert, PublicKeyInfo}}; 1288 {error, Reason} -> 1289 {ok, ssl_handshake:handle_path_validation_error(Reason, PeerCert, ChainCerts, 1290 SslOptions, Options, 1291 CertDbHandle, CertDbRef)} 1292 end 1293 catch 1294 error:{badmatch,{error, {asn1, Asn1Reason}}} -> 1295 %% ASN-1 decode of certificate somehow failed 1296 {error, ?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN, {failed_to_decode_certificate, Asn1Reason})}; 1297 error:OtherReason -> 1298 {error, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {unexpected_error, OtherReason})} 1299 end. 1300 1301 1302store_peer_cert(#state{session = Session, 1303 handshake_env = HsEnv} = State, PeerCert, PublicKeyInfo) -> 1304 State#state{session = Session#session{peer_certificate = PeerCert}, 1305 handshake_env = HsEnv#handshake_env{public_key_info = PublicKeyInfo}}. 1306 1307 1308convert_certificate_chain(Certs) -> 1309 Fun = fun(#certificate_entry{data = Data}) -> 1310 {true, Data}; 1311 (_) -> 1312 false 1313 end, 1314 lists:filtermap(Fun, Certs). 1315 1316 1317%% 4.4.1. The Transcript Hash 1318%% 1319%% As an exception to this general rule, when the server responds to a 1320%% ClientHello with a HelloRetryRequest, the value of ClientHello1 is 1321%% replaced with a special synthetic handshake message of handshake type 1322%% "message_hash" containing Hash(ClientHello1). I.e., 1323%% 1324%% Transcript-Hash(ClientHello1, HelloRetryRequest, ... Mn) = 1325%% Hash(message_hash || /* Handshake type */ 1326%% 00 00 Hash.length || /* Handshake message length (bytes) */ 1327%% Hash(ClientHello1) || /* Hash of ClientHello1 */ 1328%% HelloRetryRequest || ... || Mn) 1329%% 1330%% NOTE: Hash.length is used in practice (openssl) and not message length! 1331%% It is most probably a fault in the RFC. 1332replace_ch1_with_message_hash(#state{connection_states = ConnectionStates, 1333 handshake_env = 1334 #handshake_env{ 1335 tls_handshake_history = 1336 {[HRR,CH1|HHistory], LM}} = HSEnv} = State0) -> 1337 #{security_parameters := SecParamsR} = 1338 ssl_record:pending_connection_state(ConnectionStates, read), 1339 #security_parameters{prf_algorithm = HKDFAlgo} = SecParamsR, 1340 MessageHash = message_hash(CH1, HKDFAlgo), 1341 State0#state{handshake_env = 1342 HSEnv#handshake_env{ 1343 tls_handshake_history = 1344 {[HRR,MessageHash|HHistory], LM}}}. 1345 1346 1347message_hash(ClientHello1, HKDFAlgo) -> 1348 [?MESSAGE_HASH, 1349 0,0,ssl_cipher:hash_size(HKDFAlgo), 1350 crypto:hash(HKDFAlgo, ClientHello1)]. 1351 1352 1353calculate_handshake_secrets(PublicKey, PrivateKey, SelectedGroup, PSK, 1354 #state{connection_states = ConnectionStates, 1355 handshake_env = 1356 #handshake_env{ 1357 tls_handshake_history = HHistory}} = State0) -> 1358 #{security_parameters := SecParamsR} = 1359 ssl_record:pending_connection_state(ConnectionStates, read), 1360 #security_parameters{prf_algorithm = HKDFAlgo, 1361 cipher_suite = CipherSuite} = SecParamsR, 1362 EarlySecret = tls_v1:key_schedule(early_secret, HKDFAlgo , {psk, PSK}), 1363 1364 IKM = calculate_shared_secret(PublicKey, PrivateKey, SelectedGroup), 1365 HandshakeSecret = tls_v1:key_schedule(handshake_secret, HKDFAlgo, IKM, EarlySecret), 1366 1367 %% Calculate [sender]_handshake_traffic_secret 1368 {Messages, _} = HHistory, 1369 1370 ClientHSTrafficSecret = 1371 tls_v1:client_handshake_traffic_secret(HKDFAlgo, HandshakeSecret, lists:reverse(Messages)), 1372 ServerHSTrafficSecret = 1373 tls_v1:server_handshake_traffic_secret(HKDFAlgo, HandshakeSecret, lists:reverse(Messages)), 1374 1375 %% Calculate traffic keys 1376 #{cipher := Cipher} = ssl_cipher_format:suite_bin_to_map(CipherSuite), 1377 {ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ClientHSTrafficSecret), 1378 {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ServerHSTrafficSecret), 1379 1380 %% Calculate Finished Keys 1381 ReadFinishedKey = tls_v1:finished_key(ClientHSTrafficSecret, HKDFAlgo), 1382 WriteFinishedKey = tls_v1:finished_key(ServerHSTrafficSecret, HKDFAlgo), 1383 1384 update_pending_connection_states(State0, HandshakeSecret, undefined, 1385 undefined, undefined, 1386 ReadKey, ReadIV, ReadFinishedKey, 1387 WriteKey, WriteIV, WriteFinishedKey). 1388 1389 1390%% Server 1391get_pre_shared_key(undefined, HKDFAlgo) -> 1392 binary:copy(<<0>>, ssl_cipher:hash_size(HKDFAlgo)); 1393get_pre_shared_key({_, PSK}, _) -> 1394 PSK. 1395%% 1396%% Client 1397%% Server initiates a full handshake 1398get_pre_shared_key(_, _, HKDFAlgo, undefined) -> 1399 {ok, binary:copy(<<0>>, ssl_cipher:hash_size(HKDFAlgo))}; 1400%% Session resumption not configured 1401get_pre_shared_key(undefined, _, HKDFAlgo, _) -> 1402 {ok, binary:copy(<<0>>, ssl_cipher:hash_size(HKDFAlgo))}; 1403get_pre_shared_key(_, undefined, HKDFAlgo, _) -> 1404 {ok, binary:copy(<<0>>, ssl_cipher:hash_size(HKDFAlgo))}; 1405%% Session resumption 1406get_pre_shared_key(manual = SessionTickets, UseTicket, HKDFAlgo, SelectedIdentity) -> 1407 TicketData = get_ticket_data(self(), SessionTickets, UseTicket), 1408 case choose_psk(TicketData, SelectedIdentity) of 1409 undefined -> %% full handshake, default PSK 1410 {ok, binary:copy(<<0>>, ssl_cipher:hash_size(HKDFAlgo))}; 1411 illegal_parameter -> 1412 {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)}; 1413 {_, PSK} -> 1414 {ok, PSK} 1415 end; 1416get_pre_shared_key(auto = SessionTickets, UseTicket, HKDFAlgo, SelectedIdentity) -> 1417 TicketData = get_ticket_data(self(), SessionTickets, UseTicket), 1418 case choose_psk(TicketData, SelectedIdentity) of 1419 undefined -> %% full handshake, default PSK 1420 tls_client_ticket_store:unlock_tickets(self(), UseTicket), 1421 {ok, binary:copy(<<0>>, ssl_cipher:hash_size(HKDFAlgo))}; 1422 illegal_parameter -> 1423 tls_client_ticket_store:unlock_tickets(self(), UseTicket), 1424 {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)}; 1425 {Key, PSK} -> 1426 tls_client_ticket_store:remove_tickets([Key]), %% Remove single-use ticket 1427 tls_client_ticket_store:unlock_tickets(self(), UseTicket -- [Key]), 1428 {ok, PSK} 1429 end. 1430 1431 1432choose_psk(undefined, _) -> 1433 undefined; 1434choose_psk([], _) -> 1435 illegal_parameter; 1436choose_psk([{Key, SelectedIdentity, _, PSK, _, _}|_], SelectedIdentity) -> 1437 {Key, PSK}; 1438choose_psk([_|T], SelectedIdentity) -> 1439 choose_psk(T, SelectedIdentity). 1440 1441 1442calculate_traffic_secrets(#state{ 1443 static_env = #static_env{role = Role}, 1444 connection_states = ConnectionStates, 1445 handshake_env = 1446 #handshake_env{ 1447 tls_handshake_history = HHistory}} = State0) -> 1448 #{security_parameters := SecParamsR} = 1449 ssl_record:pending_connection_state(ConnectionStates, read), 1450 #security_parameters{prf_algorithm = HKDFAlgo, 1451 cipher_suite = CipherSuite, 1452 master_secret = HandshakeSecret} = SecParamsR, 1453 1454 MasterSecret = 1455 tls_v1:key_schedule(master_secret, HKDFAlgo, HandshakeSecret), 1456 1457 %% Get the correct list messages for the handshake context. 1458 Messages = get_handshake_context(Role, HHistory), 1459 1460 %% Calculate [sender]_application_traffic_secret_0 1461 ClientAppTrafficSecret0 = 1462 tls_v1:client_application_traffic_secret_0(HKDFAlgo, MasterSecret, lists:reverse(Messages)), 1463 ServerAppTrafficSecret0 = 1464 tls_v1:server_application_traffic_secret_0(HKDFAlgo, MasterSecret, lists:reverse(Messages)), 1465 1466 %% Calculate traffic keys 1467 #{cipher := Cipher} = ssl_cipher_format:suite_bin_to_map(CipherSuite), 1468 {ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ClientAppTrafficSecret0), 1469 {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ServerAppTrafficSecret0), 1470 1471 update_pending_connection_states(State0, MasterSecret, undefined, 1472 ClientAppTrafficSecret0, ServerAppTrafficSecret0, 1473 ReadKey, ReadIV, undefined, 1474 WriteKey, WriteIV, undefined). 1475 1476 1477get_server_private_key(#key_share_server_hello{server_share = ServerShare}) -> 1478 get_private_key(ServerShare). 1479 1480get_private_key(#key_share_entry{ 1481 key_exchange = #'ECPrivateKey'{} = PrivateKey}) -> 1482 PrivateKey; 1483get_private_key(#key_share_entry{ 1484 key_exchange = 1485 {_, PrivateKey}}) -> 1486 PrivateKey. 1487 1488%% X25519, X448 1489calculate_shared_secret(OthersKey, MyKey, Group) 1490 when is_binary(OthersKey) andalso is_binary(MyKey) andalso 1491 (Group =:= x25519 orelse Group =:= x448)-> 1492 crypto:compute_key(ecdh, OthersKey, MyKey, Group); 1493%% FFDHE 1494calculate_shared_secret(OthersKey, MyKey, Group) 1495 when is_binary(OthersKey) andalso is_binary(MyKey) -> 1496 Params = #'DHParameter'{prime = P} = ssl_dh_groups:dh_params(Group), 1497 S = public_key:compute_key(OthersKey, MyKey, Params), 1498 Size = byte_size(binary:encode_unsigned(P)), 1499 ssl_cipher:add_zero_padding(S, Size); 1500%% ECDHE 1501calculate_shared_secret(OthersKey, MyKey = #'ECPrivateKey'{}, _Group) 1502 when is_binary(OthersKey) -> 1503 Point = #'ECPoint'{point = OthersKey}, 1504 public_key:compute_key(Point, MyKey). 1505 1506 1507maybe_calculate_resumption_master_secret(#state{ssl_options = #{session_tickets := disabled}} = State) -> 1508 State; 1509maybe_calculate_resumption_master_secret(#state{ 1510 ssl_options = #{session_tickets := SessionTickets}, 1511 connection_states = ConnectionStates, 1512 handshake_env = 1513 #handshake_env{ 1514 tls_handshake_history = HHistory}} = State) 1515 when SessionTickets =/= disabled -> 1516 #{security_parameters := SecParamsR} = 1517 ssl_record:pending_connection_state(ConnectionStates, read), 1518 #security_parameters{master_secret = MasterSecret, 1519 prf_algorithm = HKDFAlgo} = SecParamsR, 1520 {Messages0, _} = HHistory, 1521 RMS = tls_v1:resumption_master_secret(HKDFAlgo, MasterSecret, lists:reverse(Messages0)), 1522 update_resumption_master_secret(State, RMS). 1523 1524 1525forget_master_secret(#state{connection_states = 1526 #{pending_read := PendingRead, 1527 pending_write := PendingWrite, 1528 current_read := CurrentRead, 1529 current_write := CurrentWrite} = CS} = State) -> 1530 State#state{connection_states = CS#{pending_read => overwrite_master_secret(PendingRead), 1531 pending_write => overwrite_master_secret(PendingWrite), 1532 current_read => overwrite_master_secret(CurrentRead), 1533 current_write => overwrite_master_secret(CurrentWrite)}}. 1534 1535 1536overwrite_master_secret(ConnectionState = #{security_parameters := SecurityParameters0}) -> 1537 SecurityParameters = SecurityParameters0#security_parameters{master_secret = {master_secret, <<0>>}}, 1538 ConnectionState#{security_parameters => SecurityParameters}. 1539 1540 1541update_pending_connection_states(#state{ 1542 static_env = #static_env{role = server}, 1543 connection_states = 1544 CS = #{pending_read := PendingRead0, 1545 pending_write := PendingWrite0}} = State, 1546 HandshakeSecret, ResumptionMasterSecret, 1547 ClientAppTrafficSecret, ServerAppTrafficSecret, 1548 ReadKey, ReadIV, ReadFinishedKey, 1549 WriteKey, WriteIV, WriteFinishedKey) -> 1550 PendingRead = update_connection_state(PendingRead0, HandshakeSecret, ResumptionMasterSecret, 1551 ClientAppTrafficSecret, 1552 ReadKey, ReadIV, ReadFinishedKey), 1553 PendingWrite = update_connection_state(PendingWrite0, HandshakeSecret, ResumptionMasterSecret, 1554 ServerAppTrafficSecret, 1555 WriteKey, WriteIV, WriteFinishedKey), 1556 State#state{connection_states = CS#{pending_read => PendingRead, 1557 pending_write => PendingWrite}}; 1558update_pending_connection_states(#state{ 1559 static_env = #static_env{role = client}, 1560 connection_states = 1561 CS = #{pending_read := PendingRead0, 1562 pending_write := PendingWrite0}} = State, 1563 HandshakeSecret, ResumptionMasterSecret, 1564 ClientAppTrafficSecret, ServerAppTrafficSecret, 1565 ReadKey, ReadIV, ReadFinishedKey, 1566 WriteKey, WriteIV, WriteFinishedKey) -> 1567 PendingRead = update_connection_state(PendingRead0, HandshakeSecret, ResumptionMasterSecret, 1568 ServerAppTrafficSecret, 1569 WriteKey, WriteIV, WriteFinishedKey), 1570 PendingWrite = update_connection_state(PendingWrite0, HandshakeSecret, ResumptionMasterSecret, 1571 ClientAppTrafficSecret, 1572 ReadKey, ReadIV, ReadFinishedKey), 1573 State#state{connection_states = CS#{pending_read => PendingRead, 1574 pending_write => PendingWrite}}. 1575 1576 1577update_connection_state(ConnectionState = #{security_parameters := SecurityParameters0}, 1578 HandshakeSecret, ResumptionMasterSecret, 1579 ApplicationTrafficSecret, Key, IV, FinishedKey) -> 1580 %% Store secret 1581 SecurityParameters = SecurityParameters0#security_parameters{ 1582 master_secret = HandshakeSecret, 1583 resumption_master_secret = ResumptionMasterSecret, 1584 application_traffic_secret = ApplicationTrafficSecret}, 1585 ConnectionState#{security_parameters => SecurityParameters, 1586 cipher_state => cipher_init(Key, IV, FinishedKey)}. 1587 1588 1589update_start_state(State, Map) -> 1590 Cipher = maps:get(cipher, Map, undefined), 1591 KeyShare = maps:get(key_share, Map, undefined), 1592 SessionId = maps:get(session_id, Map, undefined), 1593 Group = maps:get(group, Map, undefined), 1594 SelectedSignAlg = maps:get(sign_alg, Map, undefined), 1595 PeerPublicKey = maps:get(peer_public_key, Map, undefined), 1596 ALPNProtocol = maps:get(alpn, Map, undefined), 1597 update_start_state(State, Cipher, KeyShare, SessionId, 1598 Group, SelectedSignAlg, PeerPublicKey, 1599 ALPNProtocol). 1600%% 1601update_start_state(#state{connection_states = ConnectionStates0, 1602 handshake_env = #handshake_env{} = HsEnv, 1603 connection_env = CEnv, 1604 session = Session} = State, 1605 Cipher, KeyShare, SessionId, 1606 Group, SelectedSignAlg, PeerPublicKey, ALPNProtocol) -> 1607 #{security_parameters := SecParamsR0} = PendingRead = 1608 maps:get(pending_read, ConnectionStates0), 1609 #{security_parameters := SecParamsW0} = PendingWrite = 1610 maps:get(pending_write, ConnectionStates0), 1611 SecParamsR = ssl_cipher:security_parameters_1_3(SecParamsR0, Cipher), 1612 SecParamsW = ssl_cipher:security_parameters_1_3(SecParamsW0, Cipher), 1613 ConnectionStates = 1614 ConnectionStates0#{pending_read => PendingRead#{security_parameters => SecParamsR}, 1615 pending_write => PendingWrite#{security_parameters => SecParamsW}}, 1616 State#state{connection_states = ConnectionStates, 1617 handshake_env = HsEnv#handshake_env{alpn = ALPNProtocol}, 1618 key_share = KeyShare, 1619 session = Session#session{session_id = SessionId, 1620 ecc = Group, 1621 sign_alg = SelectedSignAlg, 1622 dh_public_value = PeerPublicKey, 1623 cipher_suite = Cipher}, 1624 connection_env = CEnv#connection_env{negotiated_version = {3,4}}}. 1625 1626 1627update_resumption_master_secret(#state{connection_states = ConnectionStates0} = State, 1628 ResumptionMasterSecret) -> 1629 #{security_parameters := SecParamsR0} = PendingRead = 1630 maps:get(pending_read, ConnectionStates0), 1631 #{security_parameters := SecParamsW0} = PendingWrite = 1632 maps:get(pending_write, ConnectionStates0), 1633 1634 SecParamsR = SecParamsR0#security_parameters{resumption_master_secret = ResumptionMasterSecret}, 1635 SecParamsW = SecParamsW0#security_parameters{resumption_master_secret = ResumptionMasterSecret}, 1636 ConnectionStates = 1637 ConnectionStates0#{pending_read => PendingRead#{security_parameters => SecParamsR}, 1638 pending_write => PendingWrite#{security_parameters => SecParamsW}}, 1639 State#state{connection_states = ConnectionStates}. 1640 1641 1642cipher_init(Key, IV, FinishedKey) -> 1643 #cipher_state{key = Key, 1644 iv = IV, 1645 finished_key = FinishedKey, 1646 tag_len = 16}. 1647 1648 1649%% Get handshake context for verification of CertificateVerify. 1650%% 1651%% Verify CertificateVerify: 1652%% ClientHello (client) (1) 1653%% ServerHello (server) (2) 1654%% EncryptedExtensions (server) (8) 1655%% CertificateRequest (server) (13) 1656%% Certificate (server) (11) 1657%% CertificateVerify (server) (15) 1658%% Finished (server) (20) 1659%% Certificate (client) (11) 1660%% CertificateVerify (client) (15) - Drop! Not included in calculations! 1661get_handshake_context_cv({[<<15,_/binary>>|Messages], _}) -> 1662 Messages. 1663 1664 1665%% Get handshake context for traffic key calculation. 1666%% 1667%% Client is authenticated with certificate: 1668%% ClientHello (client) (1) 1669%% ServerHello (server) (2) 1670%% EncryptedExtensions (server) (8) 1671%% CertificateRequest (server) (13) 1672%% Certificate (server) (11) 1673%% CertificateVerify (server) (15) 1674%% Finished (server) (20) 1675%% Certificate (client) (11) - Drop! Not included in calculations! 1676%% CertificateVerify (client) (15) - Drop! Not included in calculations! 1677%% Finished (client) (20) - Drop! Not included in calculations! 1678%% 1679%% Client is authenticated but sends empty certificate: 1680%% ClientHello (client) (1) 1681%% ServerHello (server) (2) 1682%% EncryptedExtensions (server) (8) 1683%% CertificateRequest (server) (13) 1684%% Certificate (server) (11) 1685%% CertificateVerify (server) (15) 1686%% Finished (server) (20) 1687%% Certificate (client) (11) - Drop! Not included in calculations! 1688%% Finished (client) (20) - Drop! Not included in calculations! 1689%% 1690%% Client is not authenticated: 1691%% ClientHello (client) (1) 1692%% ServerHello (server) (2) 1693%% EncryptedExtensions (server) (8) 1694%% Certificate (server) (11) 1695%% CertificateVerify (server) (15) 1696%% Finished (server) (20) 1697%% Finished (client) (20) - Drop! Not included in calculations! 1698%% 1699%% Drop all client messages from the front of the iolist using the property that 1700%% incoming messages are binaries. 1701get_handshake_context(server, {Messages, _}) -> 1702 get_handshake_context_server(Messages); 1703get_handshake_context(client, {Messages, _}) -> 1704 get_handshake_context_client(Messages). 1705 1706get_handshake_context_server([H|T]) when is_binary(H) -> 1707 get_handshake_context_server(T); 1708get_handshake_context_server(L) -> 1709 L. 1710 1711 1712get_handshake_context_client([H|T]) when is_list(H) -> 1713 get_handshake_context_client(T); 1714get_handshake_context_client(L) -> 1715 L. 1716 1717 1718%% If the CertificateVerify message is sent by a server, the signature 1719%% algorithm MUST be one offered in the client's "signature_algorithms" 1720%% extension unless no valid certificate chain can be produced without 1721%% unsupported algorithms 1722%% 1723%% If sent by a client, the signature algorithm used in the signature 1724%% MUST be one of those present in the supported_signature_algorithms 1725%% field of the "signature_algorithms" extension in the 1726%% CertificateRequest message. 1727verify_signature_algorithm(#state{ 1728 static_env = #static_env{role = Role}, 1729 ssl_options = #{signature_algs := LocalSignAlgs}} = State0, 1730 #certificate_verify_1_3{algorithm = PeerSignAlg}) -> 1731 case lists:member(PeerSignAlg, LocalSignAlgs) of 1732 true -> 1733 {ok, maybe_update_selected_sign_alg(State0, PeerSignAlg, Role)}; 1734 false -> 1735 State1 = calculate_traffic_secrets(State0), 1736 State = ssl_record:step_encryption_state(State1), 1737 {error, {?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, 1738 "CertificateVerify uses unsupported signature algorithm"), State}} 1739 end. 1740 1741 1742maybe_update_selected_sign_alg(#state{session = Session} = State, SignAlg, client) -> 1743 State#state{session = Session#session{sign_alg = SignAlg}}; 1744maybe_update_selected_sign_alg(State, _, _) -> 1745 State. 1746 1747 1748verify_certificate_verify(#state{ 1749 static_env = #static_env{role = Role}, 1750 connection_states = ConnectionStates, 1751 handshake_env = 1752 #handshake_env{ 1753 public_key_info = PublicKeyInfo, 1754 tls_handshake_history = HHistory}} = State0, 1755 #certificate_verify_1_3{ 1756 algorithm = SignatureScheme, 1757 signature = Signature}) -> 1758 #{security_parameters := SecParamsR} = 1759 ssl_record:pending_connection_state(ConnectionStates, write), 1760 #security_parameters{prf_algorithm = HKDFAlgo} = SecParamsR, 1761 1762 {HashAlgo, _, _} = 1763 ssl_cipher:scheme_to_components(SignatureScheme), 1764 1765 Messages = get_handshake_context_cv(HHistory), 1766 1767 Context = lists:reverse(Messages), 1768 1769 %% Transcript-Hash uses the HKDF hash function defined by the cipher suite. 1770 THash = tls_v1:transcript_hash(Context, HKDFAlgo), 1771 1772 ContextString = peer_context_string(Role), 1773 1774 %% Digital signatures use the hash function defined by the selected signature 1775 %% scheme. 1776 case verify(THash, ContextString, HashAlgo, Signature, PublicKeyInfo) of 1777 {ok, true} -> 1778 {ok, {State0, wait_finished}}; 1779 {ok, false} -> 1780 State1 = calculate_traffic_secrets(State0), 1781 State = ssl_record:step_encryption_state(State1), 1782 {error, {?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, 1783 "Failed to verify CertificateVerify"), State}}; 1784 {error, #alert{} = Alert} -> 1785 State1 = calculate_traffic_secrets(State0), 1786 State = ssl_record:step_encryption_state(State1), 1787 {error, {Alert, State}} 1788 end. 1789 1790 1791context_string(server) -> 1792 <<"TLS 1.3, server CertificateVerify">>; 1793context_string(client) -> 1794 <<"TLS 1.3, client CertificateVerify">>. 1795 1796 1797%% Return context string for verifing peer signature 1798peer_context_string(server) -> 1799 <<"TLS 1.3, client CertificateVerify">>; 1800peer_context_string(client) -> 1801 <<"TLS 1.3, server CertificateVerify">>. 1802 1803 1804%% If there is no overlap between the received 1805%% "supported_groups" and the groups supported by the server, then the 1806%% server MUST abort the handshake with a "handshake_failure" or an 1807%% "insufficient_security" alert. 1808select_common_groups(_, []) -> 1809 {error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_groups)}; 1810select_common_groups(ServerGroups, ClientGroups) -> 1811 Fun = fun(E) -> lists:member(E, ClientGroups) end, 1812 case lists:filter(Fun, ServerGroups) of 1813 [] -> 1814 {error, {insufficient_security, no_suitable_groups}}; 1815 L -> 1816 {ok, L} 1817 end. 1818 1819 1820%% RFC 8446 - 4.2.8. Key Share 1821%% This vector MAY be empty if the client is requesting a 1822%% HelloRetryRequest. Each KeyShareEntry value MUST correspond to a 1823%% group offered in the "supported_groups" extension and MUST appear in 1824%% the same order. However, the values MAY be a non-contiguous subset 1825%% of the "supported_groups" extension and MAY omit the most preferred 1826%% groups. 1827%% 1828%% Clients can offer as many KeyShareEntry values as the number of 1829%% supported groups it is offering, each representing a single set of 1830%% key exchange parameters. 1831%% 1832%% Clients MUST NOT offer multiple KeyShareEntry values 1833%% for the same group. Clients MUST NOT offer any KeyShareEntry values 1834%% for groups not listed in the client's "supported_groups" extension. 1835%% Servers MAY check for violations of these rules and abort the 1836%% handshake with an "illegal_parameter" alert if one is violated. 1837validate_client_key_share(_ ,[]) -> 1838 ok; 1839validate_client_key_share([], _) -> 1840 {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)}; 1841validate_client_key_share([G|ClientGroups], [{_, G, _}|ClientShares]) -> 1842 validate_client_key_share(ClientGroups, ClientShares); 1843validate_client_key_share([_|ClientGroups], [_|_] = ClientShares) -> 1844 validate_client_key_share(ClientGroups, ClientShares). 1845 1846 1847%% Verify that selected group is offered by the client. 1848validate_server_key_share([], _) -> 1849 {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)}; 1850validate_server_key_share([G|_ClientGroups], {_, G, _}) -> 1851 ok; 1852validate_server_key_share([_|ClientGroups], {_, _, _} = ServerKeyShare) -> 1853 validate_server_key_share(ClientGroups, ServerKeyShare). 1854 1855 1856validate_selected_group(SelectedGroup, [SelectedGroup|_]) -> 1857 {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, 1858 "Selected group sent by the server shall not correspond to a group" 1859 " which was provided in the key_share extension")}; 1860validate_selected_group(SelectedGroup, ClientGroups) -> 1861 case lists:member(SelectedGroup, ClientGroups) of 1862 true -> 1863 ok; 1864 false -> 1865 {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER, 1866 "Selected group sent by the server shall correspond to a group" 1867 " which was provided in the supported_groups extension")} 1868 end. 1869 1870 1871get_client_public_key([Group|_] = Groups, ClientShares) -> 1872 get_client_public_key(Groups, ClientShares, Group). 1873%% 1874get_client_public_key(_, [], PreferredGroup) -> 1875 {PreferredGroup, no_suitable_key}; 1876get_client_public_key([], _, PreferredGroup) -> 1877 {PreferredGroup, no_suitable_key}; 1878get_client_public_key([Group|Groups], ClientShares, PreferredGroup) -> 1879 case lists:keysearch(Group, 2, ClientShares) of 1880 {value, {_, _, ClientPublicKey}} -> 1881 {Group, ClientPublicKey}; 1882 false -> 1883 get_client_public_key(Groups, ClientShares, PreferredGroup) 1884 end. 1885 1886get_client_private_key([Group|_] = Groups, ClientShares) -> 1887 get_client_private_key(Groups, ClientShares, Group). 1888%% 1889get_client_private_key(_, [], PreferredGroup) -> 1890 {PreferredGroup, no_suitable_key}; 1891get_client_private_key([], _, PreferredGroup) -> 1892 {PreferredGroup, no_suitable_key}; 1893get_client_private_key([Group|Groups], ClientShares, PreferredGroup) -> 1894 case lists:keysearch(Group, 2, ClientShares) of 1895 {value, {_, _, {_, ClientPrivateKey}}} -> 1896 {Group, ClientPrivateKey}; 1897 {value, {_, _, #'ECPrivateKey'{} = ClientPrivateKey}} -> 1898 {Group, ClientPrivateKey}; 1899 false -> 1900 get_client_private_key(Groups, ClientShares, PreferredGroup) 1901 end. 1902 1903 1904get_server_public_key({key_share_entry, Group, PublicKey}) -> 1905 {Group, PublicKey}. 1906 1907 1908%% RFC 7301 - Application-Layer Protocol Negotiation Extension 1909%% It is expected that a server will have a list of protocols that it 1910%% supports, in preference order, and will only select a protocol if the 1911%% client supports it. In that case, the server SHOULD select the most 1912%% highly preferred protocol that it supports and that is also 1913%% advertised by the client. In the event that the server supports no 1914%% protocols that the client advertises, then the server SHALL respond 1915%% with a fatal "no_application_protocol" alert. 1916handle_alpn(undefined, _) -> 1917 {ok, undefined}; 1918handle_alpn([], _) -> 1919 {error, ?ALERT_REC(?FATAL, ?NO_APPLICATION_PROTOCOL)}; 1920handle_alpn([_|_], undefined) -> 1921 {ok, undefined}; 1922handle_alpn([ServerProtocol|T], ClientProtocols) -> 1923 case lists:member(ServerProtocol, ClientProtocols) of 1924 true -> 1925 {ok, ServerProtocol}; 1926 false -> 1927 handle_alpn(T, ClientProtocols) 1928 end. 1929 1930 1931select_cipher_suite(_, [], _) -> 1932 {error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_cipher)}; 1933%% If honor_cipher_order is set to true, use the server's preference for 1934%% cipher suite selection. 1935select_cipher_suite(true, ClientCiphers, ServerCiphers) -> 1936 select_cipher_suite(false, ServerCiphers, ClientCiphers); 1937select_cipher_suite(false, [Cipher|ClientCiphers], ServerCiphers) -> 1938 case lists:member(Cipher, tls_v1:suites('TLS_v1.3')) andalso 1939 lists:member(Cipher, ServerCiphers) of 1940 true -> 1941 {ok, Cipher}; 1942 false -> 1943 select_cipher_suite(false, ClientCiphers, ServerCiphers) 1944 end. 1945 1946 1947%% RFC 8446 4.1.3 ServerHello 1948%% A client which receives a cipher suite that was not offered MUST abort the 1949%% handshake with an "illegal_parameter" alert. 1950validate_cipher_suite(Cipher, ClientCiphers) -> 1951 case lists:member(Cipher, ClientCiphers) of 1952 true -> 1953 ok; 1954 false -> 1955 {error, ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)} 1956 end. 1957 1958 1959%% RFC 8446 (TLS 1.3) 1960%% TLS 1.3 provides two extensions for indicating which signature 1961%% algorithms may be used in digital signatures. The 1962%% "signature_algorithms_cert" extension applies to signatures in 1963%% certificates and the "signature_algorithms" extension, which 1964%% originally appeared in TLS 1.2, applies to signatures in 1965%% CertificateVerify messages. 1966%% 1967%% If no "signature_algorithms_cert" extension is 1968%% present, then the "signature_algorithms" extension also applies to 1969%% signatures appearing in certificates. 1970 1971%% Check if the signature algorithm of the server certificate is supported 1972%% by the client. 1973check_cert_sign_algo(SignAlgo, SignHash, ClientSignAlgs, undefined) -> 1974 do_check_cert_sign_algo(SignAlgo, SignHash, ClientSignAlgs); 1975check_cert_sign_algo(SignAlgo, SignHash, _, ClientSignAlgsCert) -> 1976 do_check_cert_sign_algo(SignAlgo, SignHash, ClientSignAlgsCert). 1977 1978 1979%% DSA keys are not supported by TLS 1.3 1980select_sign_algo(dsa, _ClientSignAlgs, _ServerSignAlgs) -> 1981 {error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_public_key)}; 1982select_sign_algo(_, [], _) -> 1983 {error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)}; 1984select_sign_algo(PublicKeyAlgo, [C|ClientSignAlgs], ServerSignAlgs) -> 1985 {_, S, _} = ssl_cipher:scheme_to_components(C), 1986 %% RSASSA-PKCS1-v1_5 and Legacy algorithms are not defined for use in signed 1987 %% TLS handshake messages: filter sha-1 and rsa_pkcs1. 1988 %% 1989 %% RSASSA-PSS RSAE algorithms: If the public key is carried in an X.509 1990 %% certificate, it MUST use the rsaEncryption OID. 1991 %% RSASSA-PSS PSS algorithms: If the public key is carried in an X.509 certificate, 1992 %% it MUST use the RSASSA-PSS OID. 1993 case ((PublicKeyAlgo =:= rsa andalso S =:= rsa_pss_rsae) 1994 orelse (PublicKeyAlgo =:= rsa_pss andalso S =:= rsa_pss_pss) 1995 orelse (PublicKeyAlgo =:= ecdsa andalso S =:= ecdsa)) 1996 andalso 1997 lists:member(C, ServerSignAlgs) of 1998 true -> 1999 {ok, C}; 2000 false -> 2001 select_sign_algo(PublicKeyAlgo, ClientSignAlgs, ServerSignAlgs) 2002 end. 2003 2004 2005do_check_cert_sign_algo(_, _, []) -> 2006 {error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_signature_algorithm)}; 2007do_check_cert_sign_algo(SignAlgo, SignHash, [Scheme|T]) -> 2008 {Hash, Sign, _Curve} = ssl_cipher:scheme_to_components(Scheme), 2009 case compare_sign_algos(SignAlgo, SignHash, Sign, Hash) of 2010 true -> 2011 ok; 2012 _Else -> 2013 do_check_cert_sign_algo(SignAlgo, SignHash, T) 2014 end. 2015 2016 2017%% id-RSASSA-PSS (rsa_pss) indicates that the key may only be used for PSS signatures. 2018%% TODO: Uncomment when rsa_pss signatures are supported in certificates 2019%% compare_sign_algos(rsa_pss, Hash, Algo, Hash) 2020%% when Algo =:= rsa_pss_pss -> 2021%% true; 2022%% rsaEncryption (rsa) allows the key to be used for any of the standard encryption or 2023%% signature schemes. 2024compare_sign_algos(rsa, Hash, Algo, Hash) 2025 when Algo =:= rsa_pss_rsae orelse 2026 Algo =:= rsa_pkcs1 -> 2027 true; 2028compare_sign_algos(Algo, Hash, Algo, Hash) -> 2029 true; 2030compare_sign_algos(_, _, _, _) -> 2031 false. 2032 2033 2034get_certificate_params(Cert) -> 2035 {SignAlgo0, _Param, PublicKeyAlgo0} = ssl_handshake:get_cert_params(Cert), 2036 {SignHash0, SignAlgo} = public_key:pkix_sign_types(SignAlgo0), 2037 %% Convert hash to new format 2038 SignHash = case SignHash0 of 2039 sha -> 2040 sha1; 2041 H -> H 2042 end, 2043 PublicKeyAlgo = public_key_algo(PublicKeyAlgo0), 2044 {PublicKeyAlgo, SignAlgo, SignHash}. 2045 2046 2047%% Note: copied from ssl_handshake 2048public_key_algo(?'id-RSASSA-PSS') -> 2049 rsa_pss; 2050public_key_algo(?rsaEncryption) -> 2051 rsa; 2052public_key_algo(?'id-ecPublicKey') -> 2053 ecdsa; 2054public_key_algo(?'id-dsa') -> 2055 dsa. 2056 2057get_signature_scheme_list(undefined) -> 2058 undefined; 2059get_signature_scheme_list(#signature_algorithms_cert{ 2060 signature_scheme_list = ClientSignatureSchemes}) -> 2061 ClientSignatureSchemes; 2062get_signature_scheme_list(#signature_algorithms{ 2063 signature_scheme_list = ClientSignatureSchemes}) -> 2064 %% Filter unassigned and legacy elements 2065 lists:filter(fun (E) -> is_atom(E) andalso E =/= unassigned end, 2066 ClientSignatureSchemes). 2067 2068get_supported_groups(#supported_groups{supported_groups = Groups}) -> 2069 Groups. 2070 2071get_key_shares(#key_share_client_hello{client_shares = ClientShares}) -> 2072 ClientShares; 2073get_key_shares(#key_share_server_hello{server_share = ServerShare}) -> 2074 ServerShare. 2075 2076get_selected_identity(undefined) -> 2077 undefined; 2078get_selected_identity(#pre_shared_key_server_hello{selected_identity = SelectedIdentity}) -> 2079 SelectedIdentity. 2080 2081get_offered_psks(Extensions) -> 2082 PSK = maps:get(pre_shared_key, Extensions, undefined), 2083 case PSK of 2084 undefined -> 2085 undefined; 2086 #pre_shared_key_client_hello{offered_psks = OfferedPSKs} -> 2087 OfferedPSKs 2088 end. 2089 2090 2091%% Prior to accepting PSK key establishment, the server MUST validate 2092%% the corresponding binder value (see Section 4.2.11.2 below). If this 2093%% value is not present or does not validate, the server MUST abort the 2094%% handshake. Servers SHOULD NOT attempt to validate multiple binders; 2095%% rather, they SHOULD select a single PSK and validate solely the 2096%% binder that corresponds to that PSK. 2097%% 2098%% If no acceptable PSKs are found, the server SHOULD perform a non-PSK 2099%% handshake if possible. 2100handle_pre_shared_key(_, undefined, _) -> 2101 {ok, undefined}; 2102handle_pre_shared_key(#state{ssl_options = #{session_tickets := disabled}}, _, _) -> 2103 {ok, undefined}; 2104handle_pre_shared_key(#state{ssl_options = #{session_tickets := Tickets}, 2105 handshake_env = #handshake_env{tls_handshake_history = {HHistory, _}}, 2106 static_env = #static_env{trackers = Trackers}}, 2107 OfferedPreSharedKeys, Cipher) when Tickets =/= disabled -> 2108 Tracker = proplists:get_value(session_tickets_tracker, Trackers), 2109 #{prf := CipherHash} = ssl_cipher_format:suite_bin_to_map(Cipher), 2110 tls_server_session_ticket:use(Tracker, OfferedPreSharedKeys, CipherHash, HHistory). 2111 2112get_selected_group(#key_share_hello_retry_request{selected_group = SelectedGroup}) -> 2113 SelectedGroup. 2114 2115get_alpn(ALPNProtocol0) -> 2116 case ssl_handshake:decode_alpn(ALPNProtocol0) of 2117 undefined -> 2118 undefined; 2119 [ALPNProtocol] -> 2120 ALPNProtocol 2121 end. 2122 2123maybe() -> 2124 Ref = erlang:make_ref(), 2125 Ok = fun(ok) -> ok; 2126 ({ok,R}) -> R; 2127 ({error,Reason}) -> 2128 throw({Ref,Reason}) 2129 end, 2130 {Ref,Ok}. 2131 2132 2133%% If the handshake includes a HelloRetryRequest, the initial 2134%% ClientHello and HelloRetryRequest are included in the transcript 2135%% along with the new ClientHello. For instance, if the client sends 2136%% ClientHello1, its binder will be computed over: 2137%% 2138%% Transcript-Hash(Truncate(ClientHello1)) 2139%% 2140%% Where Truncate() removes the binders list from the ClientHello. 2141%% 2142%% If the server responds with a HelloRetryRequest and the client then 2143%% sends ClientHello2, its binder will be computed over: 2144%% 2145%% Transcript-Hash(ClientHello1, 2146%% HelloRetryRequest, 2147%% Truncate(ClientHello2)) 2148%% 2149%% The full ClientHello1/ClientHello2 is included in all other handshake 2150%% hash computations. Note that in the first flight, 2151%% Truncate(ClientHello1) is hashed directly, but in the second flight, 2152%% ClientHello1 is hashed and then reinjected as a "message_hash" 2153%% message, as described in Section 4.4.1. 2154maybe_add_binders(Hello, undefined, _) -> 2155 Hello; 2156maybe_add_binders(Hello0, TicketData, Version) when Version =:= {3,4} -> 2157 HelloBin0 = tls_handshake:encode_handshake(Hello0, Version), 2158 HelloBin1 = iolist_to_binary(HelloBin0), 2159 Truncated = truncate_client_hello(HelloBin1), 2160 Binders = create_binders([Truncated], TicketData), 2161 update_binders(Hello0, Binders); 2162maybe_add_binders(Hello, _, Version) when Version =< {3,3} -> 2163 Hello. 2164%% 2165%% HelloRetryRequest 2166maybe_add_binders(Hello, _, undefined, _) -> 2167 Hello; 2168maybe_add_binders(Hello0, {[HRR,MessageHash|_], _}, TicketData, Version) when Version =:= {3,4} -> 2169 HelloBin0 = tls_handshake:encode_handshake(Hello0, Version), 2170 HelloBin1 = iolist_to_binary(HelloBin0), 2171 Truncated = truncate_client_hello(HelloBin1), 2172 Binders = create_binders([MessageHash,HRR,Truncated], TicketData), 2173 update_binders(Hello0, Binders); 2174maybe_add_binders(Hello, _, _, Version) when Version =< {3,3} -> 2175 Hello. 2176 2177 2178create_binders(Context, TicketData) -> 2179 create_binders(Context, TicketData, []). 2180%% 2181create_binders(_, [], Acc) -> 2182 lists:reverse(Acc); 2183create_binders(Context, [{_, _, _, PSK, _, HKDF}|T], Acc) -> 2184 FinishedKey = calculate_finished_key(PSK, HKDF), 2185 Binder = calculate_binder(FinishedKey, HKDF, Context), 2186 create_binders(Context, T, [Binder|Acc]). 2187 2188 2189%% Removes the binders list from the ClientHello. 2190%% opaque PskBinderEntry<32..255>; 2191%% 2192%% struct { 2193%% PskIdentity identities<7..2^16-1>; 2194%% PskBinderEntry binders<33..2^16-1>; 2195%% } OfferedPsks; 2196truncate_client_hello(HelloBin0) -> 2197 <<?BYTE(Type), ?UINT24(_Length), Body/binary>> = HelloBin0, 2198 CH0 = #client_hello{ 2199 extensions = #{pre_shared_key := PSK0} = Extensions0} = 2200 tls_handshake:decode_handshake({3,4}, Type, Body), 2201 #pre_shared_key_client_hello{offered_psks = OfferedPsks0} = PSK0, 2202 OfferedPsks = OfferedPsks0#offered_psks{binders = []}, 2203 PSK = PSK0#pre_shared_key_client_hello{offered_psks = OfferedPsks}, 2204 Extensions = Extensions0#{pre_shared_key => PSK}, 2205 CH = CH0#client_hello{extensions = Extensions}, 2206 2207 %% Decoding a ClientHello from an another TLS implementation can contain 2208 %% unsupported extensions and thus executing decoding and encoding on 2209 %% the input can result in a different handshake binary. 2210 %% The original length of the binders can still be determined by 2211 %% re-encoding the original ClientHello and using its size as reference 2212 %% when we substract the size of the truncated binary. 2213 TruncatedSize = iolist_size(tls_handshake:encode_handshake(CH, {3,4})), 2214 RefSize = iolist_size(tls_handshake:encode_handshake(CH0, {3,4})), 2215 BindersSize = RefSize - TruncatedSize, 2216 2217 %% Return the truncated ClientHello by cutting of the binders from the original 2218 %% ClientHello binary. 2219 {Truncated, _} = split_binary(HelloBin0, size(HelloBin0) - BindersSize - 2), 2220 Truncated. 2221 2222 2223%% The PskBinderEntry is computed in the same way as the Finished 2224%% message (Section 4.4.4) but with the BaseKey being the binder_key 2225%% derived via the key schedule from the corresponding PSK which is 2226%% being offered (see Section 7.1). 2227calculate_finished_key(PSK, HKDFAlgo) -> 2228 EarlySecret = tls_v1:key_schedule(early_secret, HKDFAlgo , {psk, PSK}), 2229 PRK = tls_v1:resumption_binder_key(HKDFAlgo, EarlySecret), 2230 tls_v1:finished_key(PRK, HKDFAlgo). 2231 2232 2233calculate_binder(BinderKey, HKDF, Truncated) -> 2234 tls_v1:finished_verify_data(BinderKey, HKDF, [Truncated]). 2235 2236 2237update_binders(#client_hello{extensions = 2238 #{pre_shared_key := PreSharedKey0} = Extensions0} = Hello, Binders) -> 2239 #pre_shared_key_client_hello{ 2240 offered_psks = 2241 #offered_psks{identities = Identities}} = PreSharedKey0, 2242 2243 PreSharedKey = 2244 #pre_shared_key_client_hello{ 2245 offered_psks = 2246 #offered_psks{identities = Identities, 2247 binders = Binders}}, 2248 2249 Extensions = Extensions0#{pre_shared_key => PreSharedKey}, 2250 Hello#client_hello{extensions = Extensions}. 2251 2252%% Configure a suitable session ticket 2253maybe_automatic_session_resumption(#state{ 2254 ssl_options = #{versions := [Version|_], 2255 ciphers := UserSuites, 2256 session_tickets := SessionTickets} = SslOpts0 2257 } = State0) 2258 when Version >= {3,4} andalso 2259 SessionTickets =:= auto -> 2260 AvailableCipherSuites = ssl_handshake:available_suites(UserSuites, Version), 2261 HashAlgos = cipher_hash_algos(AvailableCipherSuites), 2262 UseTicket = tls_client_ticket_store:find_ticket(self(), HashAlgos), 2263 tls_client_ticket_store:lock_tickets(self(), [UseTicket]), 2264 State = State0#state{ssl_options = SslOpts0#{use_ticket => [UseTicket]}}, 2265 {[UseTicket], State}; 2266maybe_automatic_session_resumption(#state{ 2267 ssl_options = #{use_ticket := UseTicket} 2268 } = State) -> 2269 {UseTicket, State}. 2270 2271 2272cipher_hash_algos(Ciphers) -> 2273 Fun = fun(Cipher) -> 2274 #{prf := Hash} = ssl_cipher_format:suite_bin_to_map(Cipher), 2275 Hash 2276 end, 2277 lists:map(Fun, Ciphers). 2278 2279 2280get_ticket_data(_, undefined, _) -> 2281 undefined; 2282get_ticket_data(_, _, undefined) -> 2283 undefined; 2284get_ticket_data(_, manual, UseTicket) -> 2285 process_user_tickets(UseTicket); 2286get_ticket_data(Pid, auto, UseTicket) -> 2287 tls_client_ticket_store:get_tickets(Pid, UseTicket). 2288 2289 2290process_user_tickets(UseTicket) -> 2291 process_user_tickets(UseTicket, [], 0). 2292%% 2293process_user_tickets([], Acc, _) -> 2294 lists:reverse(Acc); 2295process_user_tickets([H|T], Acc, N) -> 2296 #{hkdf := HKDF, 2297 sni := _SNI, 2298 psk := PSK, 2299 timestamp := Timestamp, 2300 ticket := NewSessionTicket} = erlang:binary_to_term(H), 2301 #new_session_ticket{ 2302 ticket_lifetime = _LifeTime, 2303 ticket_age_add = AgeAdd, 2304 ticket_nonce = Nonce, 2305 ticket = Ticket, 2306 extensions = _Extensions 2307 } = NewSessionTicket, 2308 TicketAge = erlang:system_time(seconds) - Timestamp, 2309 ObfuscatedTicketAge = obfuscate_ticket_age(TicketAge, AgeAdd), 2310 Identity = #psk_identity{ 2311 identity = Ticket, 2312 obfuscated_ticket_age = ObfuscatedTicketAge}, 2313 process_user_tickets(T, [{undefined, N, Identity, PSK, Nonce, HKDF}|Acc], N + 1). 2314 2315 2316%% The "obfuscated_ticket_age" 2317%% field of each PskIdentity contains an obfuscated version of the 2318%% ticket age formed by taking the age in milliseconds and adding the 2319%% "ticket_age_add" value that was included with the ticket 2320%% (see Section 4.6.1), modulo 2^32. 2321obfuscate_ticket_age(TicketAge, AgeAdd) -> 2322 (TicketAge + AgeAdd) rem round(math:pow(2,32)). 2323