diff options
author | Péter Dimitrov <[email protected]> | 2019-07-22 11:25:46 +0200 |
---|---|---|
committer | Péter Dimitrov <[email protected]> | 2019-07-25 14:49:16 +0200 |
commit | c45076cbbcb954434234dc7b33fee68692768cc5 (patch) | |
tree | 6afcf31ed151dcac5a787d044ccaadb3d0364a9f | |
parent | 1dbba57853b7b093bf7e770f29eefa958d04b131 (diff) | |
download | otp-c45076cbbcb954434234dc7b33fee68692768cc5.tar.gz otp-c45076cbbcb954434234dc7b33fee68692768cc5.tar.bz2 otp-c45076cbbcb954434234dc7b33fee68692768cc5.zip |
ssl: Implement pre_shared_key extension
Implement encode/decode of pre_shared_key.
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 78 | ||||
-rw-r--r-- | lib/ssl/src/tls_handshake_1_3.hrl | 15 |
2 files changed, 90 insertions, 3 deletions
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(?PSK_KEY_EXCHANGE_MODES_EXT), - ?UINT16(ExtLen), ?BYTE(KEModesLen), KEModes/binary, Acc/binary>>). + ?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, <<?UINT16(?PRE_SHARED_KEY_EXT), + ?UINT16(Len), Identities/binary, Binders/binary, Acc/binary>>); +encode_extensions([#pre_shared_key_server_hello{selected_identity = Identity} | Rest], Acc) -> + encode_extensions(Rest, <<?UINT16(?PRE_SHARED_KEY_EXT), + ?UINT16(2), ?UINT16(Identity), Acc/binary>>). 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, <<?BYTE(?PSK_DHE_KE),Acc/binary>>). +encode_psk_identities(Identities) -> + encode_psk_identities(Identities, <<>>). +%% +encode_psk_identities([], Acc) -> + Len = byte_size(Acc), + <<?UINT16(Len), Acc/binary>>; +encode_psk_identities([#psk_identity{ + identity = Identity, + obfuscated_ticket_age = Age}|T], Acc) -> + IdLen = byte_size(Identity), + encode_psk_identities(T, <<Acc/binary,?UINT16(IdLen),Identity/binary,Age/binary>>). + + +encode_psk_binders(Binders) -> + encode_psk_binders(Binders, <<>>). +%% +encode_psk_binders([], Acc) -> + Len = byte_size(Acc), + <<?UINT16(Len), Acc/binary>>; +encode_psk_binders([Binder|T], Acc) -> + Len = byte_size(Binder), + encode_psk_binders(T, <<Acc/binary,?BYTE(Len),Binder/binary>>). + + hello_extensions_list(HelloExtensions) -> [Ext || {_, Ext} <- maps:to_list(HelloExtensions), Ext =/= undefined]. @@ -2470,6 +2506,26 @@ decode_extensions(<<?UINT16(?PSK_KEY_EXCHANGE_MODES_EXT), ?UINT16(Len), #psk_key_exchange_modes{ ke_modes = decode_psk_key_exchange_modes(KEModes)}}); +decode_extensions(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len), + ExtData:Len/binary, Rest/binary>>, + Version, MessageType = client_hello, Acc) -> + <<?UINT16(IdLen),Identities:IdLen/binary,?UINT16(BLen),Binders:BLen/binary>> = 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(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len), + ExtData:Len/binary, Rest/binary>>, + Version, MessageType = server_hello, Acc) -> + <<?UINT16(Identity)>> = 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(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Version, MessageType, Acc) -> @@ -2540,6 +2596,26 @@ decode_psk_key_exchange_modes(<<?BYTE(?PSK_DHE_KE), Rest/binary>>, 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(<<?UINT16(Len), Identity:Len/binary, Age:4/binary, Rest/binary>>, 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(<<?BYTE(Len), Binder:Len/binary, Rest/binary>>, 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. |