Skip to content

Commit ea56ac0

Browse files
committed
OTP-19825
* ingela/ssl/psk-bugs: ssl: Add hybrid PQA support ssl: pre_shared_key shall be last client hello extension ssl: Improve interoperability
2 parents cbb8f94 + 1712a6f commit ea56ac0

File tree

5 files changed

+37
-28
lines changed

5 files changed

+37
-28
lines changed

lib/ssl/src/ssl_handshake.erl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ certificate_verify(Signature, PublicKeyInfo, Version,
433433
end.
434434
%%--------------------------------------------------------------------
435435
-spec verify_signature(ssl_record:ssl_version(), binary(), {term(), term()}, binary(),
436-
public_key_info()) -> true | false.
436+
public_key_info()) -> true | false.
437437
%%
438438
%% Description: Checks that a public_key signature is valid.
439439
%%--------------------------------------------------------------------
@@ -2701,9 +2701,13 @@ encode_psk_binders(Binders) ->
27012701
Len = byte_size(Result),
27022702
<<?UINT16(Len), Result/binary>>.
27032703

2704-
27052704
hello_extensions_list(HelloExtensions) ->
2706-
[Ext || {_, Ext} <- maps:to_list(HelloExtensions), Ext =/= undefined].
2705+
case maps:take(pre_shared_key, HelloExtensions) of
2706+
{#pre_shared_key_client_hello{} = PSK, Rest} ->
2707+
[Ext || {_, Ext} <- maps:to_list(Rest), Ext =/= undefined] ++ [PSK];
2708+
_ ->
2709+
[Ext || {_, Ext} <- maps:to_list(HelloExtensions), Ext =/= undefined]
2710+
end.
27072711

27082712
%%-------------Decode handshakes---------------------------------
27092713
dec_server_key(<<?UINT16(PLen), P:PLen/binary,
@@ -3127,7 +3131,9 @@ decode_extensions(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len),
31273131
#pre_shared_key_client_hello{
31283132
offered_psks = #offered_psks{
31293133
identities = decode_psk_identities(Identities),
3130-
binders = decode_psk_binders(Binders)}}});
3134+
binders = decode_psk_binders(Binders)},
3135+
binder_length = BLen + 2}}
3136+
);
31313137
decode_extensions(<<?UINT16(?PRE_SHARED_KEY_EXT), ?UINT16(Len),
31323138
ExtData:Len/binary, Rest/binary>>,
31333139
Version, MessageType = server_hello, Acc) ->

lib/ssl/src/tls_client_connection_1_3.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ do_handle_exlusive_1_3_hello_or_hello_retry_request(
647647
connection_states = ConnectionStates0
648648
} = State0) ->
649649
{Ref,Maybe} = tls_gen_connection_1_3:do_maybe(),
650-
try
650+
try
651651
ClientGroups =
652652
Maybe(tls_handshake_1_3:get_supported_groups(ClientGroups0)),
653653
Cookie = maps:get(cookie, Extensions, undefined),

lib/ssl/src/tls_handshake_1_3.erl

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,28 +1832,11 @@ create_binders(Context, [#ticket_data{
18321832
%% } OfferedPsks;
18331833
truncate_client_hello(HelloBin0) ->
18341834
<<?BYTE(Type), ?UINT24(_Length), Body/binary>> = HelloBin0,
1835-
CH0 = #client_hello{
1836-
extensions = #{pre_shared_key := PSK0} = Extensions0} =
1835+
#client_hello{
1836+
extensions = #{pre_shared_key := PSK0}} =
18371837
tls_handshake:decode_handshake(?TLS_1_3, Type, Body),
1838-
#pre_shared_key_client_hello{offered_psks = OfferedPsks0} = PSK0,
1839-
OfferedPsks = OfferedPsks0#offered_psks{binders = []},
1840-
PSK = PSK0#pre_shared_key_client_hello{offered_psks = OfferedPsks},
1841-
Extensions = Extensions0#{pre_shared_key => PSK},
1842-
CH = CH0#client_hello{extensions = Extensions},
1843-
1844-
%% Decoding a ClientHello from an another TLS implementation can contain
1845-
%% unsupported extensions and thus executing decoding and encoding on
1846-
%% the input can result in a different handshake binary.
1847-
%% The original length of the binders can still be determined by
1848-
%% re-encoding the original ClientHello and using its size as reference
1849-
%% when we subtract the size of the truncated binary.
1850-
TruncatedSize = iolist_size(tls_handshake:encode_handshake(CH, ?TLS_1_3)),
1851-
RefSize = iolist_size(tls_handshake:encode_handshake(CH0, ?TLS_1_3)),
1852-
BindersSize = RefSize - TruncatedSize,
1853-
1854-
%% Return the truncated ClientHello by cutting of the binders from the original
1855-
%% ClientHello binary.
1856-
{Truncated, _} = split_binary(HelloBin0, byte_size(HelloBin0) - BindersSize - 2),
1838+
#pre_shared_key_client_hello{binder_length = BinderLen} = PSK0,
1839+
{Truncated, _} = split_binary(HelloBin0, byte_size(HelloBin0) - BinderLen),
18571840
Truncated.
18581841

18591842
maybe_add_early_data_indication(#client_hello{

lib/ssl/src/tls_handshake_1_3.hrl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@
117117
%% } PreSharedKeyExtension;
118118
-record(pre_shared_key_client_hello,
119119
{
120-
offered_psks
120+
offered_psks,
121+
binder_length
121122
}).
122123

123124
-record(pre_shared_key_server_hello,

lib/ssl/test/property_test/ssl_eqc_handshake.erl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ elliptic_curves(Version) when ?TLS_LT(Version, ?TLS_1_3) ->
689689

690690
%% RFC 8446 (TLS 1.3) renamed the "elliptic_curve" extension.
691691
supported_groups(Version) when ?TLS_GTE(Version, ?TLS_1_3) ->
692-
SupportedGroups = tls_v1:groups(),
692+
SupportedGroups = tls_v1:groups(),
693693
#supported_groups{supported_groups = SupportedGroups}.
694694

695695

@@ -773,11 +773,30 @@ generate_public_key(Group) when
773773
Group =:= mlkem1024 ->
774774
{PublicKey, _} = crypto:generate_key(Group, []),
775775
PublicKey;
776+
generate_public_key(x25519mlkem768 = Group) ->
777+
{Curve, MLKem} = hybrid_algs(Group),
778+
P2 = generate_public_key(Curve),
779+
{P1,_} = crypto:generate_key(MLKem, []),
780+
<<P1/binary, P2/binary>>;
781+
generate_public_key(Group) when
782+
Group =:= secp256r1mlkem768 orelse
783+
Group =:= secp384r1mlkem1024 ->
784+
{Curve, MLKem} = hybrid_algs(Group),
785+
P1 = generate_public_key(Curve),
786+
{P2, _} = crypto:generate_key(MLKem, []),
787+
<<P1/binary, P2/binary>>;
776788
generate_public_key(Group) ->
777789
{PublicKey, _} =
778790
public_key:generate_key(ssl_dh_groups:dh_params(Group)),
779791
PublicKey.
780792

793+
hybrid_algs(x25519mlkem768)->
794+
{x25519, mlkem768};
795+
hybrid_algs(secp256r1mlkem768) ->
796+
{secp256r1, mlkem768};
797+
hybrid_algs(secp384r1mlkem1024) ->
798+
{secp384r1, mlkem1024}.
799+
781800
groups() ->
782801
Max = length(ssl:groups()),
783802
?LET(Size, choose(1,Max), group_list(Size)).

0 commit comments

Comments
 (0)