From c45076cbbcb954434234dc7b33fee68692768cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Mon, 22 Jul 2019 11:25:46 +0200 Subject: ssl: Implement pre_shared_key extension Implement encode/decode of pre_shared_key. --- lib/ssl/src/ssl_handshake.erl | 78 ++++++++++++++++++++++++++++++++++++++- lib/ssl/src/tls_handshake_1_3.hrl | 15 +++++++- 2 files changed, 90 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 07c7f10f2b..0585aebcb2 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -715,7 +715,19 @@ encode_extensions([#psk_key_exchange_modes{ke_modes = KEModes0} | Rest], Acc) -> KEModesLen = byte_size(KEModes), ExtLen = KEModesLen + 1, encode_extensions(Rest, <>). + ?UINT16(ExtLen), ?BYTE(KEModesLen), KEModes/binary, Acc/binary>>); +encode_extensions([#pre_shared_key_client_hello{ + offered_psks = #offered_psks{ + identities = Identities0, + binders = Binders0} = PSKs} | Rest], Acc) -> + Identities = encode_psk_identities(Identities0), + Binders = encode_psk_binders(Binders0), + Len = byte_size(Identities) + byte_size(Binders), + encode_extensions(Rest, <>); +encode_extensions([#pre_shared_key_server_hello{selected_identity = Identity} | Rest], Acc) -> + encode_extensions(Rest, <>). encode_client_protocol_negotiation(undefined, _) -> @@ -2110,6 +2122,30 @@ encode_psk_key_exchange_modes([psk_dhe_ke|T], Acc) -> encode_psk_key_exchange_modes(T, <>). +encode_psk_identities(Identities) -> + encode_psk_identities(Identities, <<>>). +%% +encode_psk_identities([], Acc) -> + Len = byte_size(Acc), + <>; +encode_psk_identities([#psk_identity{ + identity = Identity, + obfuscated_ticket_age = Age}|T], Acc) -> + IdLen = byte_size(Identity), + encode_psk_identities(T, <>). + + +encode_psk_binders(Binders) -> + encode_psk_binders(Binders, <<>>). +%% +encode_psk_binders([], Acc) -> + Len = byte_size(Acc), + <>; +encode_psk_binders([Binder|T], Acc) -> + Len = byte_size(Binder), + encode_psk_binders(T, <>). + + hello_extensions_list(HelloExtensions) -> [Ext || {_, Ext} <- maps:to_list(HelloExtensions), Ext =/= undefined]. @@ -2470,6 +2506,26 @@ decode_extensions(<>, + Version, MessageType = client_hello, Acc) -> + <> = ExtData, + decode_extensions(Rest, Version, MessageType, + Acc#{pre_shared_key => + #pre_shared_key_client_hello{ + offered_psks = #offered_psks{ + identities = decode_psk_identities(Identities), + binders = decode_psk_binders(Binders)}}}); + +decode_extensions(<>, + Version, MessageType = server_hello, Acc) -> + <> = ExtData, + decode_extensions(Rest, Version, MessageType, + Acc#{pre_shared_key => + #pre_shared_key_server_hello{ + selected_identity = Identity}}); + %% Ignore data following the ClientHello (i.e., %% extensions) if not understood. decode_extensions(<>, Version, MessageType, Acc) -> @@ -2540,6 +2596,26 @@ decode_psk_key_exchange_modes(<>, Acc) -> decode_psk_key_exchange_modes(Rest, [psk_dhe_ke|Acc]). +decode_psk_identities(Identities) -> + decode_psk_identities(Identities, []). +%% +decode_psk_identities(<<>>, Acc) -> + lists:reverse(Acc); +decode_psk_identities(<>, Acc) -> + decode_psk_identities(Rest, [#psk_identity{ + identity = Identity, + obfuscated_ticket_age = Age}|Acc]). + + +decode_psk_binders(Binders) -> + decode_psk_binders(Binders, []). +%% +decode_psk_binders(<<>>, Acc) -> + lists:reverse(Acc); +decode_psk_binders(<>, Acc) -> + decode_psk_binders(Rest, [Binder|Acc]). + + %% encode/decode stream of certificate data to/from list of certificate data certs_to_list(ASN1Certs) -> certs_to_list(ASN1Certs, []). diff --git a/lib/ssl/src/tls_handshake_1_3.hrl b/lib/ssl/src/tls_handshake_1_3.hrl index 78756c69db..eb85f216c8 100644 --- a/lib/ssl/src/tls_handshake_1_3.hrl +++ b/lib/ssl/src/tls_handshake_1_3.hrl @@ -105,9 +105,20 @@ binders % PskBinderEntry binders<33..2^16-1>; opaque PskBinderEntry<32..255> }). --record(pre_shared_key, +%% struct { +%% select (Handshake.msg_type) { +%% case client_hello: OfferedPsks; +%% case server_hello: uint16 selected_identity; +%% }; +%% } PreSharedKeyExtension; +-record(pre_shared_key_client_hello, { - data % OfferedPsks (client_hello) | uint16 selected_identity (server_hello) + offered_psks + }). + +-record(pre_shared_key_server_hello, + { + selected_identity }). %% RFC 8446 B.3.1.2. -- cgit v1.2.3