@@ -1474,21 +1474,35 @@ add_selected_version(Extensions) ->
14741474 Extensions #{server_hello_selected_version => SupportedVersions }.
14751475
14761476kse_remove_private_key (# key_share_entry {
1477- group = Group ,
1478- key_exchange =
1479- # 'ECPrivateKey' {publicKey = PublicKey }}) ->
1477+ group = Group ,
1478+ key_exchange =
1479+ # 'ECPrivateKey' {publicKey = PublicKey }}) ->
14801480 # key_share_entry {
14811481 group = Group ,
14821482 key_exchange = PublicKey };
14831483kse_remove_private_key (# key_share_entry {
1484- group = Group ,
1485- key_exchange =
1486- {PublicKey , _ }}) ->
1484+ group = Group ,
1485+ key_exchange =
1486+ {# 'ECPrivateKey' {publicKey = PublicKey1 },
1487+ {PublicKey2 , _ }}}) ->
1488+ # key_share_entry {
1489+ group = Group ,
1490+ key_exchange = <<PublicKey1 /binary , PublicKey2 /binary >>};
1491+ kse_remove_private_key (# key_share_entry {
1492+ group = Group ,
1493+ key_exchange =
1494+ {{PublicKey1 , _ }, {PublicKey2 , _ }}}) ->
1495+ # key_share_entry {
1496+ group = Group ,
1497+ key_exchange = <<PublicKey1 /binary , PublicKey2 /binary >>};
1498+ kse_remove_private_key (# key_share_entry {
1499+ group = Group ,
1500+ key_exchange =
1501+ {PublicKey , _ }}) ->
14871502 # key_share_entry {
14881503 group = Group ,
14891504 key_exchange = PublicKey }.
14901505
1491-
14921506signature_algs_ext (undefined ) ->
14931507 undefined ;
14941508signature_algs_ext (SignatureSchemes0 ) ->
@@ -2665,7 +2679,6 @@ encode_versions(Versions) ->
26652679
26662680encode_client_shares (ClientShares ) ->
26672681 << << (encode_key_share_entry (KeyShareEntry0 ))/binary >> || KeyShareEntry0 <- ClientShares >>.
2668-
26692682encode_key_share_entry (# key_share_entry {group = Group ,
26702683 key_exchange = KeyExchange }) ->
26712684 Len = byte_size (KeyExchange ),
@@ -3075,14 +3088,15 @@ decode_extensions(<<?UINT16(?KEY_SHARE_EXT), ?UINT16(Len),
30753088decode_extensions (<<? UINT16 (? KEY_SHARE_EXT ), ? UINT16 (Len ),
30763089 ExtData :Len /binary , Rest /binary >>,
30773090 Version , MessageType = server_hello , Acc ) ->
3078- <<? UINT16 (Group ),? UINT16 (KeyLen ),KeyExchange :KeyLen /binary >> = ExtData ,
3079- assert_unique_extension (key_share , Acc ),
3091+ <<? UINT16 (EnumGroup ),? UINT16 (KeyLen ),KeyExchange0 :KeyLen /binary >> = ExtData ,
3092+ Group = tls_v1 :enum_to_group (EnumGroup ),
3093+ KeyExchange = maybe_dec_server_hybrid_share (Group , KeyExchange0 ),
30803094 decode_extensions (Rest , Version , MessageType ,
30813095 Acc #{key_share =>
30823096 # key_share_server_hello {
30833097 server_share =
30843098 # key_share_entry {
3085- group = tls_v1 : enum_to_group ( Group ) ,
3099+ group = Group ,
30863100 key_exchange = KeyExchange }}});
30873101
30883102decode_extensions (<<? UINT16 (? KEY_SHARE_EXT ), ? UINT16 (Len ),
@@ -3239,8 +3253,53 @@ dec_hashsign(Value) ->
32393253 [HashSign ] = decode_sign_alg (? TLS_1_2 , Value ),
32403254 HashSign .
32413255
3256+ maybe_dec_server_hybrid_share (x25519mlkem768 , <<MLKem :1088 /binary , X25519 :32 /binary >>) ->
3257+ % % Concatenation of an ML-KEM ciphertext returned from
3258+ % % encapsulation to the client's encapsulation key The size of the
3259+ % % server share is 1120 bytes (1088 bytes for the ML-KEM part and
3260+ % % 32 bytes for X25519).
3261+ % % Note exception algorithm should be in reveres order of name due to legacy reason
3262+ {MLKem , X25519 };
3263+ maybe_dec_server_hybrid_share (secp256r1mlkem768 , <<Secp256r1 :65 /binary , MLKem :1088 /binary >>) ->
3264+ % % Concatenation of the server's ephemeral secp256r1 share encoded
3265+ % % in the same way as the client share and an ML-KEM The size of
3266+ % % the server share is 1153 bytes (1088 bytes for the ML-KEM part
3267+ % % and 65 bytes for secp256r1).
3268+ {Secp256r1 , MLKem };
3269+ maybe_dec_server_hybrid_share (secp384r1mlkem1024 , <<Secp384r1 :97 /binary , MLKem :1568 /binary >>) ->
3270+ % % Concatenation of the server's ephemeral secp384r1 share encoded
3271+ % % in the same way as the client share and an ML-KEM ciphertext
3272+ % % returned from encapsulation to the client's encapsulation key
3273+ % % The size of the server share is 1665 bytes (1568 bytes for the
3274+ % % ML-KEM part and 97 bytes for secp384r1)
3275+ {Secp384r1 , MLKem };
3276+ maybe_dec_server_hybrid_share (_ , Share ) ->
3277+ % % Not hybrid
3278+ Share .
3279+
3280+ maybe_dec_client_hybrid_share (x25519mlkem768 , <<MLKem :1184 /binary , X25519 :32 /binary >>) ->
3281+ % % Concatenation of the client's ML-KEM-768 encapsulation key and
3282+ % % the client's X25519 ephemeral share. The size of the client share
3283+ % % is 1216 bytes (1184 bytes for the ML-KEM part and 32 bytes for
3284+ % % X25519).
3285+ % % Note exception algorithm should be in reveres order of name due to legacy reason
3286+ {MLKem , X25519 };
3287+ maybe_dec_client_hybrid_share (secp256r1mlkem768 , <<Secp256r1 :65 /binary , MLKem :1184 /binary >>) ->
3288+ % % Concatenation of the secp256r1 ephemeral share and ML-KEM-768
3289+ % % encapsulation key The size of the client share is 1249 bytes (65
3290+ % % bytes for the secp256r1 part and 1184 bytes for ML-KEM). Ignore
3291+ % % unknown names (only host_name is supported)
3292+ {Secp256r1 , MLKem };
3293+ maybe_dec_client_hybrid_share (secp384r1mlkem1024 , <<Secp384r1 :97 /binary , MLKem :1568 /binary >>) ->
3294+ % % Concatenation of the secp384r1 ephemeral share and the
3295+ % % ML-KEM-1024 encapsulation key. The size of the client share
3296+ % % is 1665 bytes (97 bytes for the secp384r1 and the 1568 for the
3297+ % % ML-KEM).
3298+ {Secp384r1 , MLKem };
3299+ maybe_dec_client_hybrid_share (_ , Share ) ->
3300+ % % Not hybrid
3301+ Share .
32423302
3243- % % Ignore unknown names (only host_name is supported)
32443303dec_sni (<<? BYTE (? SNI_NAMETYPE_HOST_NAME ), ? UINT16 (Len ),
32453304 HostName :Len /binary , _ /binary >>) ->
32463305 # sni {hostname = binary_to_list (HostName )};
@@ -3266,12 +3325,13 @@ decode_client_shares(ClientShares) ->
32663325% %
32673326decode_client_shares (<<>>, Acc ) ->
32683327 lists :reverse (Acc );
3269- decode_client_shares (<<? UINT16 (Group0 ),? UINT16 (Len ),KeyExchange :Len /binary ,Rest /binary >>, Acc ) ->
3328+ decode_client_shares (<<? UINT16 (Group0 ),? UINT16 (Len ),KeyExchange0 :Len /binary ,Rest /binary >>, Acc ) ->
32703329 case tls_v1 :enum_to_group (Group0 ) of
32713330 undefined ->
32723331 % % Ignore key_share with unknown group
32733332 decode_client_shares (Rest , Acc );
32743333 Group ->
3334+ KeyExchange = maybe_dec_client_hybrid_share (Group , KeyExchange0 ),
32753335 decode_client_shares (Rest , [# key_share_entry {
32763336 group = Group ,
32773337 key_exchange = KeyExchange
0 commit comments