%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2007-2018. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% %%---------------------------------------------------------------------- %% Purpose: Help funtions for handling the TLS 1.3 (specific parts of) %%% TLS handshake protocol %%---------------------------------------------------------------------- -module(tls_handshake_1_3). -include("tls_handshake_1_3.hrl"). -include("ssl_alert.hrl"). -include("ssl_internal.hrl"). -include_lib("public_key/include/public_key.hrl"). %% Encode -export([encode_handshake/1, decode_handshake/2]). encode_handshake(#certificate_request_1_3{ certificate_request_context = Context, extensions = Exts})-> EncContext = encode_cert_req_context(Context), BinExts = encode_extensions(Exts), {?CERTIFICATE_REQUEST, <>}; encode_handshake(#certificate_1_3{ certificate_request_context = Context, entries = Entries}) -> EncContext = encode_cert_req_context(Context), EncEntries = encode_cert_entries(Entries), {?CERTIFICATE, <>}; encode_handshake(#encrypted_extensions{extensions = Exts})-> {?ENCRYPTED_EXTENSIONS, encode_extensions(Exts)}; encode_handshake(#new_session_ticket{ ticket_lifetime = LifeTime, ticket_age_add = Age, ticket_nonce = Nonce, ticket = Ticket, extensions = Exts}) -> TicketSize = byte_size(Ticket), BinExts = encode_extensions(Exts), {?NEW_SESSION_TICKET, <>}; encode_handshake(#end_of_early_data{}) -> {?END_OF_EARLY_DATA, <<>>}; encode_handshake(#key_update{request_update = Update}) -> {?KEY_UPDATE, <>}; encode_handshake(HandshakeMsg) -> ssl_handshake:encode_handshake(HandshakeMsg, {3,4}). decode_handshake(?CERTIFICATE_REQUEST, <>) -> Exts = decode_extensions(EncExts), #certificate_request_1_3{ certificate_request_context = <<>>, extensions = Exts}; decode_handshake(?CERTIFICATE_REQUEST, <>) -> Exts = decode_extensions(EncExts), #certificate_request_1_3{ certificate_request_context = Context, extensions = Exts}; decode_handshake(?CERTIFICATE, <>) -> CertList = decode_cert_entries(Certs), #certificate_1_3{ certificate_request_context = <<>>, entries = CertList }; decode_handshake(?CERTIFICATE, <>) -> CertList = decode_cert_entries(Certs), #certificate_1_3{ certificate_request_context = Context, entries = CertList }; decode_handshake(?ENCRYPTED_EXTENSIONS, EncExts) -> #encrypted_extensions{ extensions = decode_extensions(EncExts) }; decode_handshake(?NEW_SESSION_TICKET, <>) -> Exts = decode_extensions(BinExts), #new_session_ticket{ticket_lifetime = LifeTime, ticket_age_add = Age, ticket_nonce = Nonce, ticket = Ticket, extensions = Exts}; decode_handshake(?END_OF_EARLY_DATA, _) -> #end_of_early_data{}; decode_handshake(?KEY_UPDATE, <>) -> #key_update{request_update = Update}; decode_handshake(Tag, HandshakeMsg) -> ssl_handshake:decode_handshake({3,4}, Tag, HandshakeMsg). %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- encode_cert_req_context(<<>>) -> <>; encode_cert_req_context(Bin) -> Size = byte_size(Bin), <>. encode_cert_entries(Entries) -> CertEntryList = encode_cert_entries(Entries, []), Size = byte_size(CertEntryList), <>. encode_cert_entries([], Acc) -> iolist_to_binary(lists:reverse(Acc)); encode_cert_entries([#certificate_entry{data = Data, extensions = Exts} | Rest], Acc) -> BinExts = encode_extensions(Exts), Size = byte_size(Data), encode_cert_entries(Rest, [<> | Acc]). decode_cert_entries(Entries) -> decode_cert_entries(Entries, []). decode_cert_entries(<<>>, Acc) -> lists:reverse(Acc); decode_cert_entries(<>, Acc) -> Exts = decode_extensions(BinExts), decode_cert_entries(Rest, [#certificate_entry{data = Data, extensions = Exts} | Acc]). encode_extensions(Exts)-> ssl_handshake:encode_hello_extensions(Exts). decode_extensions(Exts) -> ssl_handshake:decode_hello_extensions(Exts).