aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
authorPéter Dimitrov <[email protected]>2018-11-02 10:09:18 +0100
committerGitHub <[email protected]>2018-11-02 10:09:18 +0100
commit9c33f00f78724ce0f68fef1dfc6ab4810d8c45f1 (patch)
treeefa9805ed682fe566c0bd2fe810bf5aadbe6f7d7 /lib/ssl
parent070aa4d433764f1a6f3397843db58b54f26acd7e (diff)
parent29b555abdebc7ce2097679286ca94b176aa493b9 (diff)
downloadotp-9c33f00f78724ce0f68fef1dfc6ab4810d8c45f1.tar.gz
otp-9c33f00f78724ce0f68fef1dfc6ab4810d8c45f1.tar.bz2
otp-9c33f00f78724ce0f68fef1dfc6ab4810d8c45f1.zip
Merge pull request #2003 from peterdmv/ssl/tls1.3-statem-skeleton/OTP-15310
Implement TLS 1.3 state machine skeleton
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/Makefile5
-rw-r--r--lib/ssl/src/ssl.app.src2
-rw-r--r--lib/ssl/src/ssl.erl31
-rw-r--r--lib/ssl/src/ssl_dh_groups.erl443
-rw-r--r--lib/ssl/src/ssl_handshake.erl326
-rw-r--r--lib/ssl/src/ssl_handshake.hrl23
-rw-r--r--lib/ssl/src/ssl_internal.hrl1
-rw-r--r--lib/ssl/src/tls_connection.erl147
-rw-r--r--lib/ssl/src/tls_connection_1_3.erl159
-rw-r--r--lib/ssl/src/tls_handshake.erl21
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl49
-rw-r--r--lib/ssl/src/tls_v1.erl47
-rw-r--r--lib/ssl/test/property_test/ssl_eqc_handshake.erl443
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl6
14 files changed, 1425 insertions, 278 deletions
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index d4cb5350d1..c7dee81c71 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -65,6 +65,7 @@ MODULES= \
ssl_cipher_format \
ssl_srp_primes \
tls_connection \
+ tls_connection_1_3 \
dtls_connection \
tls_sender\
ssl_config \
@@ -89,7 +90,8 @@ MODULES= \
ssl_v3 \
tls_v1 \
dtls_v1 \
- ssl_logger
+ ssl_logger \
+ ssl_dh_groups
INTERNAL_HRL_FILES = \
ssl_alert.hrl ssl_cipher.hrl \
@@ -170,6 +172,7 @@ $(EBIN)/ssl_certificate.$(EMULATOR): ssl_internal.hrl ssl_alert.hrl ssl_handshak
$(EBIN)/ssl_certificate_db.$(EMULATOR): ssl_internal.hrl ../../public_key/include/public_key.hrl ../../kernel/include/file.hrl
$(EBIN)/ssl_cipher.$(EMULATOR): ssl_internal.hrl ssl_record.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
$(EBIN)/tls_connection.$(EMULATOR): ssl_internal.hrl tls_connection.hrl tls_record.hrl ssl_cipher.hrl tls_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
+$(EBIN)/tls_connection_1_3.$(EMULATOR): ssl_internal.hrl tls_connection.hrl
$(EBIN)/dtls_connection.$(EMULATOR): ssl_internal.hrl dtls_connection.hrl dtls_record.hrl ssl_cipher.hrl dtls_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
$(EBIN)/tls_handshake.$(EMULATOR): ssl_internal.hrl tls_record.hrl ssl_cipher.hrl tls_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
$(EBIN)/tls_handshake.$(EMULATOR): ssl_internal.hrl ssl_connection.hrl ssl_record.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index 0d92c7b447..e7a4d73ec4 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -4,6 +4,7 @@
{modules, [
%% TLS/SSL
tls_connection,
+ tls_connection_1_3,
tls_handshake,
tls_handshake_1_3,
tls_record,
@@ -13,6 +14,7 @@
ssl_v3,
tls_connection_sup,
tls_sender,
+ ssl_dh_groups,
%% DTLS
dtls_connection,
dtls_handshake,
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 3319aadd68..524f06d52e 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -51,7 +51,7 @@
%% SSL/TLS protocol handling
-export([cipher_suites/0, cipher_suites/1, cipher_suites/2, filter_cipher_suites/2,
prepend_cipher_suites/2, append_cipher_suites/2,
- eccs/0, eccs/1, versions/0,
+ eccs/0, eccs/1, versions/0, groups/0,
format_error/1, renegotiate/1, prf/5, negotiated_protocol/1,
connection_information/1, connection_information/2]).
%% Misc
@@ -578,6 +578,13 @@ eccs_filter_supported(Curves) ->
Curves).
%%--------------------------------------------------------------------
+-spec groups() -> tls_v1:supported_groups().
+%% Description: returns all supported groups (TLS 1.3 and later)
+%%--------------------------------------------------------------------
+groups() ->
+ tls_v1:groups(4).
+
+%%--------------------------------------------------------------------
-spec getopts(#sslsocket{}, [gen_tcp:option_name()]) ->
{ok, [gen_tcp:option()]} | {error, reason()}.
%%
@@ -980,6 +987,9 @@ handle_options(Opts0, Role, Host) ->
HighestVersion),
eccs = handle_eccs_option(proplists:get_value(eccs, Opts, eccs()),
HighestVersion),
+ supported_groups = handle_supported_groups_option(
+ proplists:get_value(supported_groups, Opts, groups()),
+ HighestVersion),
signature_algs =
handle_hashsigns_option(
proplists:get_value(
@@ -1058,7 +1068,8 @@ handle_options(Opts0, Role, Host) ->
client_preferred_next_protocols, log_alert, log_level,
server_name_indication, honor_cipher_order, padding_check, crl_check, crl_cache,
fallback, signature_algs, signature_algs_cert, eccs, honor_ecc_order,
- beast_mitigation, max_handshake_size, handshake, customize_hostname_check],
+ beast_mitigation, max_handshake_size, handshake, customize_hostname_check,
+ supported_groups],
SockOpts = lists:foldl(fun(Key, PropList) ->
proplists:delete(Key, PropList)
end, Opts, SslOptions),
@@ -1492,6 +1503,16 @@ handle_eccs_option(Value, Version) when is_list(Value) ->
error:_ -> throw({error, {options, {eccs, Value}}})
end.
+handle_supported_groups_option(Value, Version) when is_list(Value) ->
+ {_Major, Minor} = tls_version(Version),
+ try tls_v1:groups(Minor, Value) of
+ Groups -> #supported_groups{supported_groups = Groups}
+ catch
+ exit:_ -> throw({error, {options, {supported_groups, Value}}});
+ error:_ -> throw({error, {options, {supported_groups, Value}}})
+ end.
+
+
unexpected_format(Error) ->
lists:flatten(io_lib:format("Unexpected error: ~p", [Error])).
@@ -1653,6 +1674,12 @@ new_ssl_options([{eccs, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
handle_eccs_option(Value, RecordCB:highest_protocol_version())
},
RecordCB);
+new_ssl_options([{supported_groups, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
+ new_ssl_options(Rest,
+ Opts#ssl_options{supported_groups =
+ handle_supported_groups_option(Value, RecordCB:highest_protocol_version())
+ },
+ RecordCB);
new_ssl_options([{signature_algs, Value} | Rest], #ssl_options{} = Opts, RecordCB) ->
new_ssl_options(Rest,
Opts#ssl_options{signature_algs =
diff --git a/lib/ssl/src/ssl_dh_groups.erl b/lib/ssl/src/ssl_dh_groups.erl
new file mode 100644
index 0000000000..36c97ed13e
--- /dev/null
+++ b/lib/ssl/src/ssl_dh_groups.erl
@@ -0,0 +1,443 @@
+%%
+%% %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%
+%%
+
+-module(ssl_dh_groups).
+
+-export([modp2048_generator/0, modp2048_prime/0,
+ ffdhe2048_generator/0, ffdhe2048_prime/0,
+ ffdhe3072_generator/0, ffdhe3072_prime/0,
+ ffdhe4096_generator/0, ffdhe4096_prime/0,
+ ffdhe6144_generator/0, ffdhe6144_prime/0,
+ ffdhe8192_generator/0, ffdhe8192_prime/0]).
+
+%% RFC3526 - 2048-bit MODP Group
+%% This group is assigned id 14.
+%%
+%% This prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
+%%
+%% Its hexadecimal value is:
+%%
+%% FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+%% 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+%% EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+%% E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+%% EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
+%% C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
+%% 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
+%% 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
+%% E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
+%% DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
+%% 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF
+%%
+%% The generator is: 2.
+modp2048_generator() ->
+ 2.
+
+modp2048_prime() ->
+ P = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
+ "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
+ "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
+ "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
+ "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
+ "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
+ "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
+ "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
+ "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF",
+ list_to_integer(P, 16).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% RFC8446 - TLS 1.3
+%%% RFC7919 - Negotiated FFDHE for TLS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% ffdhe2048
+%% ---------
+%% The 2048-bit group has registry value 256 and is calculated from the
+%% following formula:
+%%
+%% The modulus is:
+%%
+%% p = 2^2048 - 2^1984 + {[2^1918 * e] + 560316 } * 2^64 - 1
+%%
+%% The hexadecimal representation of p is:
+%%
+%% FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
+%% D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
+%% 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
+%% 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
+%% 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
+%% 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
+%% B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
+%% 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
+%% 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
+%% 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
+%% 886B4238 61285C97 FFFFFFFF FFFFFFFF
+%%
+%% The generator is: g = 2
+%%
+%% The group size is: q = (p-1)/2
+%%
+%% The estimated symmetric-equivalent strength of this group is 103
+%% bits.
+ffdhe2048_generator() ->
+ 2.
+
+ffdhe2048_prime() ->
+ P = "FFFFFFFF" "FFFFFFFF" "ADF85458" "A2BB4A9A" "AFDC5620" "273D3CF1"
+ "D8B9C583" "CE2D3695" "A9E13641" "146433FB" "CC939DCE" "249B3EF9"
+ "7D2FE363" "630C75D8" "F681B202" "AEC4617A" "D3DF1ED5" "D5FD6561"
+ "2433F51F" "5F066ED0" "85636555" "3DED1AF3" "B557135E" "7F57C935"
+ "984F0C70" "E0E68B77" "E2A689DA" "F3EFE872" "1DF158A1" "36ADE735"
+ "30ACCA4F" "483A797A" "BC0AB182" "B324FB61" "D108A94B" "B2C8E3FB"
+ "B96ADAB7" "60D7F468" "1D4F42A3" "DE394DF4" "AE56EDE7" "6372BB19"
+ "0B07A7C8" "EE0A6D70" "9E02FCE1" "CDF7E2EC" "C03404CD" "28342F61"
+ "9172FE9C" "E98583FF" "8E4F1232" "EEF28183" "C3FE3B1B" "4C6FAD73"
+ "3BB5FCBC" "2EC22005" "C58EF183" "7D1683B2" "C6F34A26" "C1B2EFFA"
+ "886B4238" "61285C97" "FFFFFFFF" "FFFFFFFF",
+ list_to_integer(P, 16).
+
+
+%% ffdhe3072
+%% ---------
+%% The 3072-bit prime has registry value 257 and is calculated from the
+%% following formula:
+%%
+%% The modulus is:
+%%
+%% p = 2^3072 - 2^3008 + {[2^2942 * e] + 2625351} * 2^64 - 1
+%%
+%% The hexadecimal representation of p is:
+%%
+%% FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
+%% D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
+%% 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
+%% 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
+%% 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
+%% 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
+%% B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
+%% 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
+%% 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
+%% 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
+%% 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
+%% 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
+%% AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
+%% 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
+%% ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
+%% 3C1B20EE 3FD59D7C 25E41D2B 66C62E37 FFFFFFFF FFFFFFFF
+%%
+%% The generator is: g = 2
+%%
+%% The group size is: q = (p-1)/2
+%%
+%% The estimated symmetric-equivalent strength of this group is 125
+%% bits.
+ffdhe3072_generator() ->
+ 2.
+
+ffdhe3072_prime() ->
+ P = "FFFFFFFF" "FFFFFFFF" "ADF85458" "A2BB4A9A" "AFDC5620" "273D3CF1"
+ "D8B9C583" "CE2D3695" "A9E13641" "146433FB" "CC939DCE" "249B3EF9"
+ "7D2FE363" "630C75D8" "F681B202" "AEC4617A" "D3DF1ED5" "D5FD6561"
+ "2433F51F" "5F066ED0" "85636555" "3DED1AF3" "B557135E" "7F57C935"
+ "984F0C70" "E0E68B77" "E2A689DA" "F3EFE872" "1DF158A1" "36ADE735"
+ "30ACCA4F" "483A797A" "BC0AB182" "B324FB61" "D108A94B" "B2C8E3FB"
+ "B96ADAB7" "60D7F468" "1D4F42A3" "DE394DF4" "AE56EDE7" "6372BB19"
+ "0B07A7C8" "EE0A6D70" "9E02FCE1" "CDF7E2EC" "C03404CD" "28342F61"
+ "9172FE9C" "E98583FF" "8E4F1232" "EEF28183" "C3FE3B1B" "4C6FAD73"
+ "3BB5FCBC" "2EC22005" "C58EF183" "7D1683B2" "C6F34A26" "C1B2EFFA"
+ "886B4238" "611FCFDC" "DE355B3B" "6519035B" "BC34F4DE" "F99C0238"
+ "61B46FC9" "D6E6C907" "7AD91D26" "91F7F7EE" "598CB0FA" "C186D91C"
+ "AEFE1309" "85139270" "B4130C93" "BC437944" "F4FD4452" "E2D74DD3"
+ "64F2E21E" "71F54BFF" "5CAE82AB" "9C9DF69E" "E86D2BC5" "22363A0D"
+ "ABC52197" "9B0DEADA" "1DBF9A42" "D5C4484E" "0ABCD06B" "FA53DDEF"
+ "3C1B20EE" "3FD59D7C" "25E41D2B" "66C62E37" "FFFFFFFF" "FFFFFFFF",
+ list_to_integer(P, 16).
+
+
+%% ffdhe4096
+%% ---------
+%% The 4096-bit group has registry value 258 and is calculated from the
+%% following formula:
+%%
+%% The modulus is:
+%%
+%% p = 2^4096 - 2^4032 + {[2^3966 * e] + 5736041} * 2^64 - 1
+%%
+%% The hexadecimal representation of p is:
+%%
+%% FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
+%% D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
+%% 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
+%% 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
+%% 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
+%% 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
+%% B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
+%% 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
+%% 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
+%% 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
+%% 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
+%% 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
+%% AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
+%% 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
+%% ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
+%% 3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB
+%% 7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004
+%% 87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832
+%% A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A
+%% 1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF
+%% 8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E655F6A
+%% FFFFFFFF FFFFFFFF
+%%
+%% The generator is: g = 2
+%%
+%% The group size is: q = (p-1)/2
+%%
+%% The estimated symmetric-equivalent strength of this group is 150
+%% bits.
+ffdhe4096_generator() ->
+ 2.
+
+ffdhe4096_prime() ->
+ P = "FFFFFFFF" "FFFFFFFF" "ADF85458" "A2BB4A9A" "AFDC5620" "273D3CF1"
+ "D8B9C583" "CE2D3695" "A9E13641" "146433FB" "CC939DCE" "249B3EF9"
+ "7D2FE363" "630C75D8" "F681B202" "AEC4617A" "D3DF1ED5" "D5FD6561"
+ "2433F51F" "5F066ED0" "85636555" "3DED1AF3" "B557135E" "7F57C935"
+ "984F0C70" "E0E68B77" "E2A689DA" "F3EFE872" "1DF158A1" "36ADE735"
+ "30ACCA4F" "483A797A" "BC0AB182" "B324FB61" "D108A94B" "B2C8E3FB"
+ "B96ADAB7" "60D7F468" "1D4F42A3" "DE394DF4" "AE56EDE7" "6372BB19"
+ "0B07A7C8" "EE0A6D70" "9E02FCE1" "CDF7E2EC" "C03404CD" "28342F61"
+ "9172FE9C" "E98583FF" "8E4F1232" "EEF28183" "C3FE3B1B" "4C6FAD73"
+ "3BB5FCBC" "2EC22005" "C58EF183" "7D1683B2" "C6F34A26" "C1B2EFFA"
+ "886B4238" "611FCFDC" "DE355B3B" "6519035B" "BC34F4DE" "F99C0238"
+ "61B46FC9" "D6E6C907" "7AD91D26" "91F7F7EE" "598CB0FA" "C186D91C"
+ "AEFE1309" "85139270" "B4130C93" "BC437944" "F4FD4452" "E2D74DD3"
+ "64F2E21E" "71F54BFF" "5CAE82AB" "9C9DF69E" "E86D2BC5" "22363A0D"
+ "ABC52197" "9B0DEADA" "1DBF9A42" "D5C4484E" "0ABCD06B" "FA53DDEF"
+ "3C1B20EE" "3FD59D7C" "25E41D2B" "669E1EF1" "6E6F52C3" "164DF4FB"
+ "7930E9E4" "E58857B6" "AC7D5F42" "D69F6D18" "7763CF1D" "55034004"
+ "87F55BA5" "7E31CC7A" "7135C886" "EFB4318A" "ED6A1E01" "2D9E6832"
+ "A907600A" "918130C4" "6DC778F9" "71AD0038" "092999A3" "33CB8B7A"
+ "1A1DB93D" "7140003C" "2A4ECEA9" "F98D0ACC" "0A8291CD" "CEC97DCF"
+ "8EC9B55A" "7F88A46B" "4DB5A851" "F44182E1" "C68A007E" "5E655F6A"
+ "FFFFFFFF" "FFFFFFFF",
+ list_to_integer(P, 16).
+
+
+%% ffdhe6144
+%% ---------
+%% The 6144-bit group has registry value 259 and is calculated from the
+%% following formula:
+%%
+%% The modulus is:
+%%
+%% p = 2^6144 - 2^6080 + {[2^6014 * e] + 15705020} * 2^64 - 1
+%%
+%% The hexadecimal representation of p is:
+%%
+%% FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
+%% D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
+%% 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
+%% 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
+%% 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
+%% 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
+%% B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
+%% 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
+%% 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
+%% 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
+%% 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
+%% 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
+%% AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
+%% 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
+%% ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
+%% 3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB
+%% 7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004
+%% 87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832
+%% A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A
+%% 1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF
+%% 8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902
+%% 0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6
+%% 3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A
+%% CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477
+%% A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3
+%% 0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4
+%% 763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6
+%% B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C
+%% D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A
+%% E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04
+%% 5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1
+%% A41D570D 7938DAD4 A40E329C D0E40E65 FFFFFFFF FFFFFFFF
+%%
+%% The generator is: g = 2
+%%
+%% The group size is: q = (p-1)/2
+%%
+%% The estimated symmetric-equivalent strength of this group is 175
+%% bits.
+ffdhe6144_generator() ->
+ 2.
+
+ffdhe6144_prime() ->
+ P = "FFFFFFFF" "FFFFFFFF" "ADF85458" "A2BB4A9A" "AFDC5620" "273D3CF1"
+ "D8B9C583" "CE2D3695" "A9E13641" "146433FB" "CC939DCE" "249B3EF9"
+ "7D2FE363" "630C75D8" "F681B202" "AEC4617A" "D3DF1ED5" "D5FD6561"
+ "2433F51F" "5F066ED0" "85636555" "3DED1AF3" "B557135E" "7F57C935"
+ "984F0C70" "E0E68B77" "E2A689DA" "F3EFE872" "1DF158A1" "36ADE735"
+ "30ACCA4F" "483A797A" "BC0AB182" "B324FB61" "D108A94B" "B2C8E3FB"
+ "B96ADAB7" "60D7F468" "1D4F42A3" "DE394DF4" "AE56EDE7" "6372BB19"
+ "0B07A7C8" "EE0A6D70" "9E02FCE1" "CDF7E2EC" "C03404CD" "28342F61"
+ "9172FE9C" "E98583FF" "8E4F1232" "EEF28183" "C3FE3B1B" "4C6FAD73"
+ "3BB5FCBC" "2EC22005" "C58EF183" "7D1683B2" "C6F34A26" "C1B2EFFA"
+ "886B4238" "611FCFDC" "DE355B3B" "6519035B" "BC34F4DE" "F99C0238"
+ "61B46FC9" "D6E6C907" "7AD91D26" "91F7F7EE" "598CB0FA" "C186D91C"
+ "AEFE1309" "85139270" "B4130C93" "BC437944" "F4FD4452" "E2D74DD3"
+ "64F2E21E" "71F54BFF" "5CAE82AB" "9C9DF69E" "E86D2BC5" "22363A0D"
+ "ABC52197" "9B0DEADA" "1DBF9A42" "D5C4484E" "0ABCD06B" "FA53DDEF"
+ "3C1B20EE" "3FD59D7C" "25E41D2B" "669E1EF1" "6E6F52C3" "164DF4FB"
+ "7930E9E4" "E58857B6" "AC7D5F42" "D69F6D18" "7763CF1D" "55034004"
+ "87F55BA5" "7E31CC7A" "7135C886" "EFB4318A" "ED6A1E01" "2D9E6832"
+ "A907600A" "918130C4" "6DC778F9" "71AD0038" "092999A3" "33CB8B7A"
+ "1A1DB93D" "7140003C" "2A4ECEA9" "F98D0ACC" "0A8291CD" "CEC97DCF"
+ "8EC9B55A" "7F88A46B" "4DB5A851" "F44182E1" "C68A007E" "5E0DD902"
+ "0BFD64B6" "45036C7A" "4E677D2C" "38532A3A" "23BA4442" "CAF53EA6"
+ "3BB45432" "9B7624C8" "917BDD64" "B1C0FD4C" "B38E8C33" "4C701C3A"
+ "CDAD0657" "FCCFEC71" "9B1F5C3E" "4E46041F" "388147FB" "4CFDB477"
+ "A52471F7" "A9A96910" "B855322E" "DB6340D8" "A00EF092" "350511E3"
+ "0ABEC1FF" "F9E3A26E" "7FB29F8C" "183023C3" "587E38DA" "0077D9B4"
+ "763E4E4B" "94B2BBC1" "94C6651E" "77CAF992" "EEAAC023" "2A281BF6"
+ "B3A739C1" "22611682" "0AE8DB58" "47A67CBE" "F9C9091B" "462D538C"
+ "D72B0374" "6AE77F5E" "62292C31" "1562A846" "505DC82D" "B854338A"
+ "E49F5235" "C95B9117" "8CCF2DD5" "CACEF403" "EC9D1810" "C6272B04"
+ "5B3B71F9" "DC6B80D6" "3FDD4A8E" "9ADB1E69" "62A69526" "D43161C1"
+ "A41D570D" "7938DAD4" "A40E329C" "D0E40E65" "FFFFFFFF" "FFFFFFFF",
+ list_to_integer(P, 16).
+
+
+%% ffdhe8192
+%% ---------
+%% The 8192-bit group has registry value 260 and is calculated from the
+%% following formula:
+%%
+%% The modulus is:
+%%
+%% p = 2^8192 - 2^8128 + {[2^8062 * e] + 10965728} * 2^64 - 1
+%%
+%% The hexadecimal representation of p is:
+%%
+%% FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
+%% D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
+%% 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
+%% 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
+%% 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
+%% 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
+%% B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
+%% 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
+%% 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
+%% 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
+%% 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
+%% 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
+%% AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
+%% 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
+%% ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
+%% 3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB
+%% 7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004
+%% 87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832
+%% A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A
+%% 1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF
+%% 8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902
+%% 0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6
+%% 3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A
+%% CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477
+%% A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3
+%% 0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4
+%% 763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6
+%% B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C
+%% D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A
+%% E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04
+%% 5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1
+%% A41D570D 7938DAD4 A40E329C CFF46AAA 36AD004C F600C838
+%% 1E425A31 D951AE64 FDB23FCE C9509D43 687FEB69 EDD1CC5E
+%% 0B8CC3BD F64B10EF 86B63142 A3AB8829 555B2F74 7C932665
+%% CB2C0F1C C01BD702 29388839 D2AF05E4 54504AC7 8B758282
+%% 2846C0BA 35C35F5C 59160CC0 46FD8251 541FC68C 9C86B022
+%% BB709987 6A460E74 51A8A931 09703FEE 1C217E6C 3826E52C
+%% 51AA691E 0E423CFC 99E9E316 50C1217B 624816CD AD9A95F9
+%% D5B80194 88D9C0A0 A1FE3075 A577E231 83F81D4A 3F2FA457
+%% 1EFC8CE0 BA8A4FE8 B6855DFE 72B0A66E DED2FBAB FBE58A30
+%% FAFABE1C 5D71A87E 2F741EF8 C1FE86FE A6BBFDE5 30677F0D
+%% 97D11D49 F7A8443D 0822E506 A9F4614E 011E2A94 838FF88C
+%% D68C8BB7 C5C6424C FFFFFFFF FFFFFFFF
+%%
+%% The generator is: g = 2
+%%
+%% The group size is: q = (p-1)/2
+%%
+%% The estimated symmetric-equivalent strength of this group is 192
+%% bits.
+ffdhe8192_generator() ->
+ 2.
+
+ffdhe8192_prime() ->
+ P = "FFFFFFFF" "FFFFFFFF" "ADF85458" "A2BB4A9A" "AFDC5620" "273D3CF1"
+ "D8B9C583" "CE2D3695" "A9E13641" "146433FB" "CC939DCE" "249B3EF9"
+ "7D2FE363" "630C75D8" "F681B202" "AEC4617A" "D3DF1ED5" "D5FD6561"
+ "2433F51F" "5F066ED0" "85636555" "3DED1AF3" "B557135E" "7F57C935"
+ "984F0C70" "E0E68B77" "E2A689DA" "F3EFE872" "1DF158A1" "36ADE735"
+ "30ACCA4F" "483A797A" "BC0AB182" "B324FB61" "D108A94B" "B2C8E3FB"
+ "B96ADAB7" "60D7F468" "1D4F42A3" "DE394DF4" "AE56EDE7" "6372BB19"
+ "0B07A7C8" "EE0A6D70" "9E02FCE1" "CDF7E2EC" "C03404CD" "28342F61"
+ "9172FE9C" "E98583FF" "8E4F1232" "EEF28183" "C3FE3B1B" "4C6FAD73"
+ "3BB5FCBC" "2EC22005" "C58EF183" "7D1683B2" "C6F34A26" "C1B2EFFA"
+ "886B4238" "611FCFDC" "DE355B3B" "6519035B" "BC34F4DE" "F99C0238"
+ "61B46FC9" "D6E6C907" "7AD91D26" "91F7F7EE" "598CB0FA" "C186D91C"
+ "AEFE1309" "85139270" "B4130C93" "BC437944" "F4FD4452" "E2D74DD3"
+ "64F2E21E" "71F54BFF" "5CAE82AB" "9C9DF69E" "E86D2BC5" "22363A0D"
+ "ABC52197" "9B0DEADA" "1DBF9A42" "D5C4484E" "0ABCD06B" "FA53DDEF"
+ "3C1B20EE" "3FD59D7C" "25E41D2B" "669E1EF1" "6E6F52C3" "164DF4FB"
+ "7930E9E4" "E58857B6" "AC7D5F42" "D69F6D18" "7763CF1D" "55034004"
+ "87F55BA5" "7E31CC7A" "7135C886" "EFB4318A" "ED6A1E01" "2D9E6832"
+ "A907600A" "918130C4" "6DC778F9" "71AD0038" "092999A3" "33CB8B7A"
+ "1A1DB93D" "7140003C" "2A4ECEA9" "F98D0ACC" "0A8291CD" "CEC97DCF"
+ "8EC9B55A" "7F88A46B" "4DB5A851" "F44182E1" "C68A007E" "5E0DD902"
+ "0BFD64B6" "45036C7A" "4E677D2C" "38532A3A" "23BA4442" "CAF53EA6"
+ "3BB45432" "9B7624C8" "917BDD64" "B1C0FD4C" "B38E8C33" "4C701C3A"
+ "CDAD0657" "FCCFEC71" "9B1F5C3E" "4E46041F" "388147FB" "4CFDB477"
+ "A52471F7" "A9A96910" "B855322E" "DB6340D8" "A00EF092" "350511E3"
+ "0ABEC1FF" "F9E3A26E" "7FB29F8C" "183023C3" "587E38DA" "0077D9B4"
+ "763E4E4B" "94B2BBC1" "94C6651E" "77CAF992" "EEAAC023" "2A281BF6"
+ "B3A739C1" "22611682" "0AE8DB58" "47A67CBE" "F9C9091B" "462D538C"
+ "D72B0374" "6AE77F5E" "62292C31" "1562A846" "505DC82D" "B854338A"
+ "E49F5235" "C95B9117" "8CCF2DD5" "CACEF403" "EC9D1810" "C6272B04"
+ "5B3B71F9" "DC6B80D6" "3FDD4A8E" "9ADB1E69" "62A69526" "D43161C1"
+ "A41D570D" "7938DAD4" "A40E329C" "CFF46AAA" "36AD004C" "F600C838"
+ "1E425A31" "D951AE64" "FDB23FCE" "C9509D43" "687FEB69" "EDD1CC5E"
+ "0B8CC3BD" "F64B10EF" "86B63142" "A3AB8829" "555B2F74" "7C932665"
+ "CB2C0F1C" "C01BD702" "29388839" "D2AF05E4" "54504AC7" "8B758282"
+ "2846C0BA" "35C35F5C" "59160CC0" "46FD8251" "541FC68C" "9C86B022"
+ "BB709987" "6A460E74" "51A8A931" "09703FEE" "1C217E6C" "3826E52C"
+ "51AA691E" "0E423CFC" "99E9E316" "50C1217B" "624816CD" "AD9A95F9"
+ "D5B80194" "88D9C0A0" "A1FE3075" "A577E231" "83F81D4A" "3F2FA457"
+ "1EFC8CE0" "BA8A4FE8" "B6855DFE" "72B0A66E" "DED2FBAB" "FBE58A30"
+ "FAFABE1C" "5D71A87E" "2F741EF8" "C1FE86FE" "A6BBFDE5" "30677F0D"
+ "97D11D49" "F7A8443D" "0822E506" "A9F4614E" "011E2A94" "838FF88C"
+ "D68C8BB7" "C5C6424C" "FFFFFFFF" "FFFFFFFF",
+ list_to_integer(P, 16).
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 1e57dfd710..da2e92a76b 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -60,7 +60,7 @@
-export([encode_handshake/2, encode_hello_extensions/1, encode_extensions/1, encode_extensions/2,
encode_client_protocol_negotiation/2, encode_protocols_advertised_on_server/1]).
%% Decode
--export([decode_handshake/3, decode_vector/1, decode_hello_extensions/3, decode_extensions/1,
+-export([decode_handshake/3, decode_vector/1, decode_hello_extensions/3, decode_extensions/2,
decode_server_key/3, decode_client_key/3,
decode_suites/2
]).
@@ -75,7 +75,7 @@
handle_client_hello_extensions/9, %% Returns server hello extensions
handle_server_hello_extensions/9, select_curve/2, select_curve/3,
select_hashsign/4, select_hashsign/5,
- select_hashsign_algs/3
+ select_hashsign_algs/3, empty_extensions/2
]).
%%====================================================================
@@ -620,6 +620,14 @@ encode_extensions([#elliptic_curves{elliptic_curve_list = EllipticCurves} | Rest
Len = ListLen + 2,
encode_extensions(Rest, <<?UINT16(?ELLIPTIC_CURVES_EXT),
?UINT16(Len), ?UINT16(ListLen), EllipticCurveList/binary, Acc/binary>>);
+encode_extensions([#supported_groups{supported_groups = SupportedGroups} | Rest], Acc) ->
+
+ SupportedGroupList = << <<(tls_v1:group_to_enum(X)):16>> || X <- SupportedGroups>>,
+ ListLen = byte_size(SupportedGroupList),
+ Len = ListLen + 2,
+ encode_extensions(Rest, <<?UINT16(?ELLIPTIC_CURVES_EXT),
+ ?UINT16(Len), ?UINT16(ListLen),
+ SupportedGroupList/binary, Acc/binary>>);
encode_extensions([#ec_point_formats{ec_point_format_list = ECPointFormats} | Rest], Acc) ->
ECPointFormatList = list_to_binary(ECPointFormats),
ListLen = byte_size(ECPointFormatList),
@@ -638,7 +646,15 @@ encode_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Rest], Ac
Len = ListLen + 2,
encode_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT),
?UINT16(Len), ?UINT16(ListLen), SignAlgoList/binary, Acc/binary>>);
-encode_extensions([#signature_scheme_list{
+encode_extensions([#signature_algorithms{
+ signature_scheme_list = SignatureSchemes} | Rest], Acc) ->
+ SignSchemeList = << <<(ssl_cipher:signature_scheme(SignatureScheme)):16 >> ||
+ SignatureScheme <- SignatureSchemes >>,
+ ListLen = byte_size(SignSchemeList),
+ Len = ListLen + 2,
+ encode_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT),
+ ?UINT16(Len), ?UINT16(ListLen), SignSchemeList/binary, Acc/binary>>);
+encode_extensions([#signature_algorithms_cert{
signature_scheme_list = SignatureSchemes} | Rest], Acc) ->
SignSchemeList = << <<(ssl_cipher:signature_scheme(SignatureScheme)):16 >> ||
SignatureScheme <- SignatureSchemes >>,
@@ -703,7 +719,7 @@ decode_handshake(Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32
session_id = Session_ID,
cipher_suite = Cipher_suite,
compression_method = Comp_method,
- extensions = empty_hello_extensions(Version, server)};
+ extensions = empty_extensions(Version, server_hello)};
decode_handshake(Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
?BYTE(SID_length), Session_ID:SID_length/binary,
@@ -772,15 +788,20 @@ decode_vector(<<?UINT16(Len), Vector:Len/binary>>) ->
%% Description: Decodes TLS hello extensions
%%--------------------------------------------------------------------
decode_hello_extensions(Extensions, Version, Role) ->
- decode_extensions(Extensions, empty_hello_extensions(Version, Role)).
+ MessageType =
+ case Role of
+ client -> client_hello;
+ server -> server_hello
+ end,
+ decode_extensions(Extensions, Version, empty_extensions(Version, MessageType)).
%%--------------------------------------------------------------------
--spec decode_extensions(binary()) -> map().
+-spec decode_extensions(binary(),tuple()) -> map().
%%
%% Description: Decodes TLS hello extensions
%%--------------------------------------------------------------------
-decode_extensions(Extensions) ->
- decode_extensions(Extensions, empty_extensions()).
+decode_extensions(Extensions, Version) ->
+ decode_extensions(Extensions, Version, empty_extensions()).
%%--------------------------------------------------------------------
-spec decode_server_key(binary(), ssl_cipher_format:key_algo(), ssl_record:ssl_version()) ->
@@ -983,48 +1004,72 @@ premaster_secret(EncSecret, #'RSAPrivateKey'{} = RSAPrivateKey) ->
%%====================================================================
%% Extensions handling
%%====================================================================
-client_hello_extensions(Version, CipherSuites,
- #ssl_options{signature_algs = SupportedHashSigns,
- signature_algs_cert = SignatureSchemes,
- eccs = SupportedECCs,
- versions = Versions} = SslOpts, ConnectionStates, Renegotiation) ->
- {EcPointFormats, EllipticCurves} =
- case advertises_ec_ciphers(lists:map(fun ssl_cipher_format:suite_definition/1, CipherSuites)) of
- true ->
- client_ecc_extensions(SupportedECCs);
- false ->
- {undefined, undefined}
- end,
+client_hello_extensions(Version, CipherSuites, SslOpts, ConnectionStates, Renegotiation) ->
+ HelloExtensions0 = add_tls12_extensions(Version, SslOpts, ConnectionStates, Renegotiation),
+ HelloExtensions1 = add_common_extensions(Version, HelloExtensions0, CipherSuites, SslOpts),
+ maybe_add_tls13_extensions(Version, HelloExtensions1, SslOpts).
+
+
+add_tls12_extensions(Version,
+ #ssl_options{signature_algs = SupportedHashSigns} = SslOpts,
+ ConnectionStates,
+ Renegotiation) ->
SRP = srp_user(SslOpts),
+ #{renegotiation_info => renegotiation_info(tls_record, client,
+ ConnectionStates, Renegotiation),
+ srp => SRP,
+ signature_algs => available_signature_algs(SupportedHashSigns, Version),
+ alpn => encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation),
+ next_protocol_negotiation =>
+ encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector,
+ Renegotiation),
+ sni => sni(SslOpts#ssl_options.server_name_indication)
+ }.
- HelloExtensions = #{renegotiation_info => renegotiation_info(tls_record, client,
- ConnectionStates, Renegotiation),
- srp => SRP,
- signature_algs => available_signature_algs(SupportedHashSigns, Version),
- ec_point_formats => EcPointFormats,
- elliptic_curves => EllipticCurves,
- alpn => encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation),
- next_protocol_negotiation =>
- encode_client_protocol_negotiation(SslOpts#ssl_options.next_protocol_selector,
- Renegotiation),
- sni => sni(SslOpts#ssl_options.server_name_indication)
- },
-
- %% Add "supported_versions" extension if TLS 1.3
- case Version of
- {3,4} ->
- HelloExtensions#{client_hello_versions =>
- #client_hello_versions{versions = Versions},
- signature_algs_cert =>
- signature_scheme_list(SignatureSchemes)};
- _Else ->
- HelloExtensions
- end.
-signature_scheme_list(undefined) ->
+add_common_extensions({3,4},
+ HelloExtensions,
+ _CipherSuites,
+ #ssl_options{eccs = SupportedECCs,
+ supported_groups = Groups}) ->
+ {EcPointFormats, _} =
+ client_ecc_extensions(SupportedECCs),
+ HelloExtensions#{ec_point_formats => EcPointFormats,
+ elliptic_curves => Groups};
+
+add_common_extensions(_Version,
+ HelloExtensions,
+ CipherSuites,
+ #ssl_options{eccs = SupportedECCs}) ->
+
+ {EcPointFormats, EllipticCurves} =
+ case advertises_ec_ciphers(
+ lists:map(fun ssl_cipher_format:suite_definition/1,
+ CipherSuites)) of
+ true ->
+ client_ecc_extensions(SupportedECCs);
+ false ->
+ {undefined, undefined}
+ end,
+ HelloExtensions#{ec_point_formats => EcPointFormats,
+ elliptic_curves => EllipticCurves}.
+
+
+maybe_add_tls13_extensions({3,4},
+ HelloExtensions,
+ #ssl_options{signature_algs_cert = SignatureSchemes,
+ versions = SupportedVersions}) ->
+ HelloExtensions#{client_hello_versions =>
+ #client_hello_versions{versions = SupportedVersions},
+ signature_algs_cert =>
+ signature_algs_cert(SignatureSchemes)};
+maybe_add_tls13_extensions(_, HelloExtensions, _) ->
+ HelloExtensions.
+
+signature_algs_cert(undefined) ->
undefined;
-signature_scheme_list(SignatureSchemes) ->
- #signature_scheme_list{signature_scheme_list = SignatureSchemes}.
+signature_algs_cert(SignatureSchemes) ->
+ #signature_algorithms_cert{signature_scheme_list = SignatureSchemes}.
handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites,
Exts, Version,
@@ -1039,7 +1084,7 @@ handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites,
ClientCipherSuites, Compression,
ConnectionStates0, Renegotiation, SecureRenegotation),
- Empty = empty_hello_extensions(Version, client),
+ Empty = empty_extensions(Version, server_hello),
ServerHelloExtensions = Empty#{renegotiation_info => renegotiation_info(RecordCB, server,
ConnectionStates, Renegotiation),
ec_point_formats => server_ecc_extension(Version, maps:get(ec_point_formats, Exts, undefined))
@@ -1247,7 +1292,7 @@ get_cert_params(Cert) ->
get_signature_scheme(undefined) ->
undefined;
-get_signature_scheme(#signature_scheme_list{
+get_signature_scheme(#signature_algorithms_cert{
signature_scheme_list = ClientSignatureSchemes}) ->
ClientSignatureSchemes.
@@ -1299,6 +1344,8 @@ extension_value(#ec_point_formats{ec_point_format_list = List}) ->
List;
extension_value(#elliptic_curves{elliptic_curve_list = List}) ->
List;
+extension_value(#supported_groups{supported_groups = SupportedGroups}) ->
+ SupportedGroups;
extension_value(#hash_sign_algos{hash_sign_algos = Algos}) ->
Algos;
extension_value(#alpn{extension_data = Data}) ->
@@ -2036,16 +2083,19 @@ dec_server_key_signature(Params, <<?UINT16(Len), Signature:Len/binary>>, _) ->
dec_server_key_signature(_, _, _) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE, failed_to_decrypt_server_key_sign)).
-decode_extensions(<<>>, Acc) ->
+decode_extensions(<<>>, _Version, Acc) ->
Acc;
-decode_extensions(<<?UINT16(?ALPN_EXT), ?UINT16(ExtLen), ?UINT16(Len), ExtensionData:Len/binary, Rest/binary>>, Acc)
- when Len + 2 =:= ExtLen ->
+decode_extensions(<<?UINT16(?ALPN_EXT), ?UINT16(ExtLen), ?UINT16(Len),
+ ExtensionData:Len/binary, Rest/binary>>, Version, Acc)
+ when Len + 2 =:= ExtLen ->
ALPN = #alpn{extension_data = ExtensionData},
- decode_extensions(Rest, Acc#{alpn => ALPN});
-decode_extensions(<<?UINT16(?NEXTPROTONEG_EXT), ?UINT16(Len), ExtensionData:Len/binary, Rest/binary>>, Acc) ->
+ decode_extensions(Rest, Version, Acc#{alpn => ALPN});
+decode_extensions(<<?UINT16(?NEXTPROTONEG_EXT), ?UINT16(Len),
+ ExtensionData:Len/binary, Rest/binary>>, Version, Acc) ->
NextP = #next_protocol_negotiation{extension_data = ExtensionData},
- decode_extensions(Rest, Acc#{next_protocol_negotiation => NextP});
-decode_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), Info:Len/binary, Rest/binary>>, Acc) ->
+ decode_extensions(Rest, Version, Acc#{next_protocol_negotiation => NextP});
+decode_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len),
+ Info:Len/binary, Rest/binary>>, Version, Acc) ->
RenegotiateInfo = case Len of
1 -> % Initial handshake
Info; % should be <<0>> will be matched in handle_renegotiation_info
@@ -2054,35 +2104,50 @@ decode_extensions(<<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), Info:Len/binary,
<<?BYTE(VerifyLen), VerifyInfo/binary>> = Info,
VerifyInfo
end,
- decode_extensions(Rest, Acc#{renegotiation_info =>
- #renegotiation_info{renegotiated_connection =
- RenegotiateInfo}});
+ decode_extensions(Rest, Version, Acc#{renegotiation_info =>
+ #renegotiation_info{renegotiated_connection =
+ RenegotiateInfo}});
-decode_extensions(<<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen), SRP:SRPLen/binary, Rest/binary>>, Acc)
+decode_extensions(<<?UINT16(?SRP_EXT), ?UINT16(Len), ?BYTE(SRPLen),
+ SRP:SRPLen/binary, Rest/binary>>, Version, Acc)
when Len == SRPLen + 2 ->
- decode_extensions(Rest, Acc#{srp => #srp{username = SRP}});
+ decode_extensions(Rest, Version, Acc#{srp => #srp{username = SRP}});
decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
- ExtData:Len/binary, Rest/binary>>, Acc) ->
+ ExtData:Len/binary, Rest/binary>>, Version, Acc)
+ when Version < {3,4} ->
SignAlgoListLen = Len - 2,
<<?UINT16(SignAlgoListLen), SignAlgoList/binary>> = ExtData,
HashSignAlgos = [{ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)} ||
<<?BYTE(Hash), ?BYTE(Sign)>> <= SignAlgoList],
- decode_extensions(Rest, Acc#{signature_algs =>
- #hash_sign_algos{hash_sign_algos = HashSignAlgos}});
+ decode_extensions(Rest, Version, Acc#{signature_algs =>
+ #hash_sign_algos{hash_sign_algos =
+ HashSignAlgos}});
+
+decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>, Version, Acc)
+ when Version =:= {3,4} ->
+ SignSchemeListLen = Len - 2,
+ <<?UINT16(SignSchemeListLen), SignSchemeList/binary>> = ExtData,
+ SignSchemes = [ssl_cipher:signature_scheme(SignScheme) ||
+ <<?UINT16(SignScheme)>> <= SignSchemeList],
+ decode_extensions(Rest, Version, Acc#{signature_algs =>
+ #signature_algorithms{
+ signature_scheme_list = SignSchemes}});
decode_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_CERT_EXT), ?UINT16(Len),
- ExtData:Len/binary, Rest/binary>>, Acc) ->
+ ExtData:Len/binary, Rest/binary>>, Version, Acc) ->
SignSchemeListLen = Len - 2,
<<?UINT16(SignSchemeListLen), SignSchemeList/binary>> = ExtData,
SignSchemes = [ssl_cipher:signature_scheme(SignScheme) ||
<<?UINT16(SignScheme)>> <= SignSchemeList],
- decode_extensions(Rest, Acc#{signature_algs_cert =>
- #signature_scheme_list{
- signature_scheme_list = SignSchemes}});
+ decode_extensions(Rest, Version, Acc#{signature_algs_cert =>
+ #signature_algorithms_cert{
+ signature_scheme_list = SignSchemes}});
decode_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len),
- ExtData:Len/binary, Rest/binary>>, Acc) ->
+ ExtData:Len/binary, Rest/binary>>, Version, Acc)
+ when Version < {3,4} ->
<<?UINT16(_), EllipticCurveList/binary>> = ExtData,
%% Ignore unknown curves
Pick = fun(Enum) ->
@@ -2094,42 +2159,66 @@ decode_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len),
end
end,
EllipticCurves = lists:filtermap(Pick, [ECC || <<ECC:16>> <= EllipticCurveList]),
- decode_extensions(Rest, Acc#{elliptic_curves =>
- #elliptic_curves{elliptic_curve_list =
- EllipticCurves}});
+ decode_extensions(Rest, Version, Acc#{elliptic_curves =>
+ #elliptic_curves{elliptic_curve_list =
+ EllipticCurves}});
+
+
+decode_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>, Version, Acc)
+ when Version =:= {3,4} ->
+ <<?UINT16(_), GroupList/binary>> = ExtData,
+ %% Ignore unknown curves
+ Pick = fun(Enum) ->
+ case tls_v1:enum_to_group(Enum) of
+ undefined ->
+ false;
+ Group ->
+ {true, Group}
+ end
+ end,
+ SupportedGroups = lists:filtermap(Pick, [Group || <<Group:16>> <= GroupList]),
+ decode_extensions(Rest, Version, Acc#{elliptic_curves =>
+ #supported_groups{supported_groups =
+ SupportedGroups}});
+
decode_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len),
- ExtData:Len/binary, Rest/binary>>, Acc) ->
+ ExtData:Len/binary, Rest/binary>>, Version, Acc) ->
<<?BYTE(_), ECPointFormatList/binary>> = ExtData,
ECPointFormats = binary_to_list(ECPointFormatList),
- decode_extensions(Rest, Acc#{ec_point_formats =>
- #ec_point_formats{ec_point_format_list =
- ECPointFormats}});
+ decode_extensions(Rest, Version, Acc#{ec_point_formats =>
+ #ec_point_formats{ec_point_format_list =
+ ECPointFormats}});
-decode_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len), Rest/binary>>, Acc) when Len == 0 ->
- decode_extensions(Rest, Acc#{sni => #sni{hostname = ""}}); %% Server may send an empy SNI
+decode_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len),
+ Rest/binary>>, Version, Acc) when Len == 0 ->
+ decode_extensions(Rest, Version, Acc#{sni => #sni{hostname = ""}}); %% Server may send an empy SNI
decode_extensions(<<?UINT16(?SNI_EXT), ?UINT16(Len),
- ExtData:Len/binary, Rest/binary>>, Acc) ->
+ ExtData:Len/binary, Rest/binary>>, Version, Acc) ->
<<?UINT16(_), NameList/binary>> = ExtData,
- decode_extensions(Rest, Acc#{sni => dec_sni(NameList)});
+ decode_extensions(Rest, Version, Acc#{sni => dec_sni(NameList)});
decode_extensions(<<?UINT16(?SUPPORTED_VERSIONS_EXT), ?UINT16(Len),
- ExtData:Len/binary, Rest/binary>>, Acc) when Len > 2 ->
+ ExtData:Len/binary, Rest/binary>>, Version, Acc) when Len > 2 ->
<<?UINT16(_),Versions/binary>> = ExtData,
- decode_extensions(Rest, Acc#{client_hello_versions =>
- #client_hello_versions{versions = decode_versions(Versions)}});
+ decode_extensions(Rest, Version, Acc#{client_hello_versions =>
+ #client_hello_versions{
+ versions = decode_versions(Versions)}});
decode_extensions(<<?UINT16(?SUPPORTED_VERSIONS_EXT), ?UINT16(Len),
- ?UINT16(Version), Rest/binary>>, Acc) when Len =:= 2, Version =:= 16#0304 ->
- decode_extensions(Rest, Acc#{server_hello_selected_version =>
- #server_hello_selected_version{selected_version = {3,4}}});
+ ?UINT16(SelectedVersion), Rest/binary>>, Version, Acc)
+ when Len =:= 2, SelectedVersion =:= 16#0304 ->
+ decode_extensions(Rest, Version, Acc#{server_hello_selected_version =>
+ #server_hello_selected_version{selected_version =
+ {3,4}}});
%% Ignore data following the ClientHello (i.e.,
%% extensions) if not understood.
-decode_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Acc) ->
- decode_extensions(Rest, Acc);
+decode_extensions(<<?UINT16(_), ?UINT16(Len), _Unknown:Len/binary, Rest/binary>>, Version, Acc) ->
+ decode_extensions(Rest, Version, Acc);
%% This theoretically should not happen if the protocol is followed, but if it does it is ignored.
-decode_extensions(_, Acc) ->
+decode_extensions(_, _, Acc) ->
Acc.
dec_hashsign(<<?BYTE(HashAlgo), ?BYTE(SignAlgo)>>) ->
@@ -2520,6 +2609,11 @@ client_ecc_extensions(SupportedECCs) ->
CryptoSupport = proplists:get_value(public_keys, crypto:supports()),
case proplists:get_bool(ecdh, CryptoSupport) of
true ->
+ %% RFC 8422 - 5.1. Client Hello Extensions
+ %% Clients SHOULD send both the Supported Elliptic Curves Extension and the
+ %% Supported Point Formats Extension. If the Supported Point Formats
+ %% Extension is indeed sent, it MUST contain the value 0 (uncompressed)
+ %% as one of the items in the list of point formats.
EcPointFormats = #ec_point_formats{ec_point_format_list = [?ECPOINT_UNCOMPRESSED]},
EllipticCurves = SupportedECCs,
{EcPointFormats, EllipticCurves};
@@ -2687,27 +2781,37 @@ cert_curve(Cert, ECCCurve0, CipherSuite) ->
{ECCCurve0, CipherSuite}
end.
-empty_hello_extensions({3, 4}, server) ->
- #{server_hello_selected_version => undefined,
- key_share => undefined,
- pre_shared_key => undefined,
- sni => undefined
- };
-empty_hello_extensions({3, 4}, client) ->
- #{client_hello_versions => undefined,
- signature_algs => undefined,
- signature_algs_cert => undefined,
+empty_extensions() ->
+ #{}.
+
+empty_extensions({3,4}, client_hello) ->
+ #{
sni => undefined,
+ %% max_fragment_length => undefined,
+ %% status_request => undefined,
+ elliptic_curves => undefined,
+ signature_algs => undefined,
+ %% use_srtp => undefined,
+ %% heartbeat => undefined,
alpn => undefined,
+ %% signed_cert_timestamp => undefined,
+ %% client_cert_type => undefined,
+ %% server_cert_type => undefined,
+ %% padding => undefined,
key_share => undefined,
- pre_shared_key => undefined
+ pre_shared_key => undefined,
+ %% psk_key_exhange_modes => undefined,
+ %% early_data => undefined,
+ %% cookie => undefined,
+ client_hello_versions => undefined,
+ %% cert_authorities => undefined,
+ %% post_handshake_auth => undefined,
+ signature_algs_cert => undefined
};
-empty_hello_extensions({3, 3}, client) ->
- Ext = empty_hello_extensions({3,2}, client),
- Ext#{client_hello_versions => undefined,
- signature_algs => undefined,
- signature_algs_cert => undefined};
-empty_hello_extensions(_, client) ->
+empty_extensions({3, 3}, client_hello) ->
+ Ext = empty_extensions({3,2}, client_hello),
+ Ext#{signature_algs => undefined};
+empty_extensions(_, client_hello) ->
#{renegotiation_info => undefined,
alpn => undefined,
next_protocol_negotiation => undefined,
@@ -2715,11 +2819,13 @@ empty_hello_extensions(_, client) ->
ec_point_formats => undefined,
elliptic_curves => undefined,
sni => undefined};
-empty_hello_extensions(_, server) ->
+empty_extensions({3,4}, server_hello) ->
+ #{server_hello_selected_version => undefined,
+ key_share => undefined,
+ pre_shared_key => undefined
+ };
+empty_extensions(_, server_hello) ->
#{renegotiation_info => undefined,
alpn => undefined,
next_protocol_negotiation => undefined,
- ec_point_formats => undefined,
- sni => undefined}.
-empty_extensions() ->
- #{}.
+ ec_point_formats => undefined}.
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index b14bc21862..1fd143a641 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -52,9 +52,8 @@
-define(NUM_OF_SESSION_ID_BYTES, 32). % TSL 1.1 & SSL 3
-define(NUM_OF_PREMASTERSECRET_BYTES, 48).
--define(DEFAULT_DIFFIE_HELLMAN_GENERATOR, 2).
--define(DEFAULT_DIFFIE_HELLMAN_PRIME,
- 16#FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF).
+-define(DEFAULT_DIFFIE_HELLMAN_GENERATOR, ssl_dh_groups:modp2048_generator()).
+-define(DEFAULT_DIFFIE_HELLMAN_PRIME, ssl_dh_groups:modp2048_prime()).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Handsake protocol - RFC 4346 section 7.4
@@ -316,9 +315,9 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(SIGNATURE_ALGORITHMS_EXT, 13).
--record(hash_sign_algos, {
- hash_sign_algos
- }).
+-record(hash_sign_algos, {hash_sign_algos}).
+%% RFC 8446 (TLS 1.3)
+-record(signature_algorithms, {signature_scheme_list}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% RFC 7301 Application-Layer Protocol Negotiation
@@ -341,9 +340,8 @@
-record(next_protocol, {selected_protocol}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% ECC Extensions RFC 8422 section 4 and 5 (RFC 7919 not supported)
+%% ECC Extensions RFC 8422 section 4 and 5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-define(ELLIPTIC_CURVES_EXT, 10).
-define(EC_POINT_FORMATS_EXT, 11).
@@ -351,11 +349,18 @@
elliptic_curve_list
}).
+%% RFC 8446 (TLS 1.3) renamed the "elliptic_curve" extension.
+-record(supported_groups, {
+ supported_groups
+ }).
+
-record(ec_point_formats, {
ec_point_format_list
}).
-define(ECPOINT_UNCOMPRESSED, 0).
+%% Defined in RFC 4492, deprecated by RFC 8422
+%% RFC 8422 compliant implementations MUST not support the two formats below
-define(ECPOINT_ANSIX962_COMPRESSED_PRIME, 1).
-define(ECPOINT_ANSIX962_COMPRESSED_CHAR2, 2).
@@ -431,6 +436,6 @@
-define(SIGNATURE_ALGORITHMS_CERT_EXT, 50).
--record(signature_scheme_list, {signature_scheme_list}).
+-record(signature_algorithms_cert, {signature_scheme_list}).
-endif. % -ifdef(ssl_handshake).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 5a18f6aa99..48798799f7 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -170,6 +170,7 @@
signature_algs,
signature_algs_cert,
eccs,
+ supported_groups, %% RFC 8422, RFC 8446
honor_ecc_order :: boolean(),
max_handshake_size :: integer(),
handshake,
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index af59dda442..298758ea38 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -69,6 +69,22 @@
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
hello/3, user_hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
connection/3]).
+%% TLS 1.3 state functions (server)
+-export([start/3, %% common state with client
+ negotiated/3,
+ recvd_ch/3,
+ wait_cert/3, %% common state with client
+ wait_cv/3, %% common state with client
+ wait_eoed/3,
+ wait_finished/3, %% common state with client
+ wait_flight2/3,
+ connected/3 %% common state with client
+ ]).
+%% TLS 1.3 state functions (client)
+-export([wait_cert_cr/3,
+ wait_ee/3,
+ wait_sh/3
+ ]).
%% gen_statem callbacks
-export([callback_mode/0, terminate/3, code_change/4, format_status/2]).
@@ -560,7 +576,7 @@ hello(internal, #client_hello{client_version = ClientVersion} = Hello,
State#state{negotiated_version
= ClientVersion});
{Version, {Type, Session},
- ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
+ ConnectionStates, Protocol0, ServerHelloExt, HashSign} when Version < {3,4} ->
Protocol = case Protocol0 of
undefined -> CurrentProtocol;
_ -> Protocol0
@@ -571,7 +587,23 @@ hello(internal, #client_hello{client_version = ClientVersion} = Hello,
hashsign_algorithm = HashSign,
client_hello_version = ClientVersion,
session = Session,
- negotiated_protocol = Protocol})
+ negotiated_protocol = Protocol});
+ %% TLS 1.3
+ {Version, {Type, Session},
+ ConnectionStates, Protocol0, ServerHelloExt, HashSign} ->
+ Protocol = case Protocol0 of
+ undefined -> CurrentProtocol;
+ _ -> Protocol0
+ end,
+ tls_connection_1_3:gen_handshake(?FUNCTION_NAME,
+ internal,
+ {common_client_hello, Type, ServerHelloExt},
+ State#state{connection_states = ConnectionStates,
+ negotiated_version = Version,
+ hashsign_algorithm = HashSign,
+ client_hello_version = ClientVersion,
+ session = Session,
+ negotiated_protocol = Protocol})
end;
hello(internal, #server_hello{} = Hello,
#state{connection_states = ConnectionStates0,
@@ -683,6 +715,117 @@ connection(Type, Event, State) ->
downgrade(Type, Event, State) ->
ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
+%%--------------------------------------------------------------------
+%% TLS 1.3 state functions
+%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+-spec start(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+start(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+start(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec negotiated(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+negotiated(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+negotiated(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec recvd_ch(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+recvd_ch(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+recvd_ch(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_cert(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_cert(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_cert(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_cv(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_cv(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_cv(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_eoed(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_eoed(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_eoed(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_finished(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_finished(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_finished(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_flight2(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_flight2(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_flight2(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec connected(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+connected(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+connected(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_cert_cr(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_cert_cr(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_cert_cr(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_ee(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_ee(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_ee(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
+%%--------------------------------------------------------------------
+-spec wait_sh(gen_statem:event_type(), term(), #state{}) ->
+ gen_statem:state_function_result().
+%%--------------------------------------------------------------------
+wait_sh(info, Event, State) ->
+ gen_info(Event, ?FUNCTION_NAME, State);
+wait_sh(Type, Event, State) ->
+ gen_handshake(?FUNCTION_NAME, Type, Event, State).
+
%--------------------------------------------------------------------
%% gen_statem callbacks
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/tls_connection_1_3.erl b/lib/ssl/src/tls_connection_1_3.erl
new file mode 100644
index 0000000000..c8732e7847
--- /dev/null
+++ b/lib/ssl/src/tls_connection_1_3.erl
@@ -0,0 +1,159 @@
+%%
+%% %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: TODO
+%%----------------------------------------------------------------------
+
+%% RFC 8446
+%% A.1. Client
+%%
+%% START <----+
+%% Send ClientHello | | Recv HelloRetryRequest
+%% [K_send = early data] | |
+%% v |
+%% / WAIT_SH ----+
+%% | | Recv ServerHello
+%% | | K_recv = handshake
+%% Can | V
+%% send | WAIT_EE
+%% early | | Recv EncryptedExtensions
+%% data | +--------+--------+
+%% | Using | | Using certificate
+%% | PSK | v
+%% | | WAIT_CERT_CR
+%% | | Recv | | Recv CertificateRequest
+%% | | Certificate | v
+%% | | | WAIT_CERT
+%% | | | | Recv Certificate
+%% | | v v
+%% | | WAIT_CV
+%% | | | Recv CertificateVerify
+%% | +> WAIT_FINISHED <+
+%% | | Recv Finished
+%% \ | [Send EndOfEarlyData]
+%% | K_send = handshake
+%% | [Send Certificate [+ CertificateVerify]]
+%% Can send | Send Finished
+%% app data --> | K_send = K_recv = application
+%% after here v
+%% CONNECTED
+%%
+%% A.2. Server
+%%
+%% START <-----+
+%% Recv ClientHello | | Send HelloRetryRequest
+%% v |
+%% RECVD_CH ----+
+%% | Select parameters
+%% v
+%% NEGOTIATED
+%% | Send ServerHello
+%% | K_send = handshake
+%% | Send EncryptedExtensions
+%% | [Send CertificateRequest]
+%% Can send | [Send Certificate + CertificateVerify]
+%% app data | Send Finished
+%% after --> | K_send = application
+%% here +--------+--------+
+%% No 0-RTT | | 0-RTT
+%% | |
+%% K_recv = handshake | | K_recv = early data
+%% [Skip decrypt errors] | +------> WAIT_EOED -+
+%% | | Recv | | Recv EndOfEarlyData
+%% | | early data | | K_recv = handshake
+%% | +------------+ |
+%% | |
+%% +> WAIT_FLIGHT2 <--------+
+%% |
+%% +--------+--------+
+%% No auth | | Client auth
+%% | |
+%% | v
+%% | WAIT_CERT
+%% | Recv | | Recv Certificate
+%% | empty | v
+%% | Certificate | WAIT_CV
+%% | | | Recv
+%% | v | CertificateVerify
+%% +-> WAIT_FINISHED <---+
+%% | Recv Finished
+%% | K_recv = application
+%% v
+%% CONNECTED
+
+-module(tls_connection_1_3).
+
+-include("ssl_alert.hrl").
+-include("ssl_connection.hrl").
+
+-export([hello/4]).
+-export([gen_handshake/4]).
+
+hello(internal, {common_client_hello, Type, ServerHelloExt}, State, Connection) ->
+ do_server_hello(Type, ServerHelloExt, State, Connection).
+
+do_server_hello(Type, #{next_protocol_negotiation := _NextProtocols} =
+ _ServerHelloExt,
+ #state{negotiated_version = _Version,
+ session = #session{session_id = _SessId},
+ connection_states = _ConnectionStates0,
+ ssl_options = #ssl_options{versions = [_HighestVersion|_]}}
+ = State0, _Connection) when is_atom(Type) ->
+%% NEGOTIATED
+%% | Send ServerHello
+%% | K_send = handshake
+%% | Send EncryptedExtensions
+%% | [Send CertificateRequest]
+%% Can send | [Send Certificate + CertificateVerify]
+%% app data | Send Finished
+%% after --> | K_send = application
+%% here +--------+--------+
+%% No 0-RTT | | 0-RTT
+%% | |
+%% K_recv = handshake | | K_recv = early data
+%% [Skip decrypt errors] | +------> WAIT_EOED -+
+%% | | Recv | | Recv EndOfEarlyData
+%% | | early data | | K_recv = handshake
+%% | +------------+ |
+%% | |
+%% +> WAIT_FLIGHT2 <--------+
+ %% Will be called implicitly
+ %% {Record, State} = Connection:next_record(State2#state{session = Session}),
+ %% Connection:next_event(wait_flight2, Record, State, Actions),
+ %% OR
+ %% Connection:next_event(WAIT_EOED, Record, State, Actions)
+ {next_state, wait_flight2, State0, []}.
+ %% TODO: Add new states to tls_connection!
+ %% State0.
+
+
+gen_handshake(StateName, Type, Event,
+ #state{negotiated_version = Version} = State) ->
+ try tls_connection_1_3:StateName(Type, Event, State, ?MODULE) of
+ Result ->
+ Result
+ catch
+ _:_ ->
+ ssl_connection:handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
+ malformed_handshake_data),
+ Version, StateName, State)
+ end.
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index b39a7732e7..37f13fcbac 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -260,6 +260,8 @@ get_tls_handshake(Version, Data, Buffer, Options) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+handle_client_hello(Version = {3,4}, ClientHello, SslOpts, Info, Renegotiation) ->
+ tls_handshake_1_3:handle_client_hello(Version, ClientHello, SslOpts, Info, Renegotiation);
handle_client_hello(Version,
#client_hello{session_id = SugesstedId,
cipher_suites = CipherSuites,
@@ -341,26 +343,19 @@ handle_server_hello_extensions(Version, SessionId, Random, CipherSuite,
do_hello(undefined, _Versions, _CipherSuites, _Hello, _SslOpts, _Info, _Renegotiation) ->
?ALERT_REC(?FATAL, ?PROTOCOL_VERSION);
do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation) ->
- case tls_record:is_higher({3,4}, Version) of
- true -> %% TLS 1.2 and older
- case ssl_cipher:is_fallback(CipherSuites) of
+ case ssl_cipher:is_fallback(CipherSuites) of
+ true ->
+ Highest = tls_record:highest_protocol_version(Versions),
+ case tls_record:is_higher(Highest, Version) of
true ->
- Highest = tls_record:highest_protocol_version(Versions),
- case tls_record:is_higher(Highest, Version) of
- true ->
- ?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK);
- false ->
- handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
- end;
+ ?ALERT_REC(?FATAL, ?INAPPROPRIATE_FALLBACK);
false ->
handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
end;
false ->
- %% Implement TLS 1.3 statem ???
- ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
+ handle_client_hello(Version, Hello, SslOpts, Info, Renegotiation)
end.
-
%%--------------------------------------------------------------------
enc_handshake(#hello_request{}, {3, N}) when N < 4 ->
{?HELLO_REQUEST, <<>>};
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 199054b43b..104017b67c 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -33,6 +33,9 @@
%% Encode
-export([encode_handshake/1, decode_handshake/2]).
+%% Handshake
+-export([handle_client_hello/5]).
+
encode_handshake(#certificate_request_1_3{
certificate_request_context = Context,
extensions = Exts})->
@@ -147,7 +150,51 @@ decode_cert_entries(<<?UINT24(DSize), Data:DSize/binary, ?UINT16(Esize), BinExts
encode_extensions(Exts)->
ssl_handshake:encode_extensions(extensions_list(Exts)).
decode_extensions(Exts) ->
- ssl_handshake:decode_extensions(Exts).
+ ssl_handshake:decode_extensions(Exts, {3,4}).
extensions_list(HelloExtensions) ->
[Ext || {_, Ext} <- maps:to_list(HelloExtensions)].
+
+
+handle_client_hello(Version,
+ #client_hello{session_id = SugesstedId,
+ cipher_suites = CipherSuites,
+ compression_methods = Compressions,
+ random = Random,
+ extensions = HelloExt},
+ #ssl_options{versions = Versions,
+ signature_algs = SupportedHashSigns,
+ eccs = SupportedECCs,
+ honor_ecc_order = ECCOrder} = SslOpts,
+ {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _},
+ Renegotiation) ->
+ case tls_record:is_acceptable_version(Version, Versions) of
+ true ->
+ %% Get supported_groups
+ %% SupportedGroups = maps:get(elliptic_curves, HelloExt, undefined),
+ %% Get KeyShareClientHello
+
+ %% Validate supported_groups + KeyShareClientHello
+ %% IF valid THEN
+ %% IF supported_groups IS empty send HelloRetryRequest
+ %% ELSE continue
+ %% ELSE
+ %% send Alert
+ %% ClientHashSigns = maps:get(signature_algs, HelloExt, undefined),
+ %% ClientSignatureSchemes = maps:get(signature_algs_cert, HelloExt, undefined),
+
+ %% Implement session handling.
+
+ %% Select curve
+
+ %% Sessions cannot be resumed by ClientHello
+
+ %% Select cipher_suite
+ %% Select hash_sign
+
+ %% Handle extensions
+ ok;
+ false ->
+ ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION)
+ end.
+
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index 7d28962d2d..e7218c8c8a 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -33,7 +33,8 @@
setup_keys/8, suites/1, prf/5,
ecc_curves/1, ecc_curves/2, oid_to_enum/1, enum_to_oid/1,
default_signature_algs/1, signature_algs/2,
- default_signature_schemes/1, signature_schemes/2]).
+ default_signature_schemes/1, signature_schemes/2,
+ groups/1, groups/2, group_to_enum/1, enum_to_group/1]).
-type named_curve() :: sect571r1 | sect571k1 | secp521r1 | brainpoolP512r1 |
sect409k1 | sect409r1 | brainpoolP384r1 | secp384r1 |
@@ -42,7 +43,10 @@
sect193r1 | sect193r2 | secp192k1 | secp192r1 | sect163k1 |
sect163r1 | sect163r2 | secp160k1 | secp160r1 | secp160r2.
-type curves() :: [named_curve()].
--export_type([curves/0, named_curve/0]).
+-type group() :: secp256r1 | secp384r1 | secp521r1 | ffdhe2048 |
+ ffdhe3072 | ffdhe4096 | ffdhe6144 | ffdhe8192.
+-type supported_groups() :: [group()].
+-export_type([curves/0, named_curve/0, group/0, supported_groups/0]).
%%====================================================================
%% Internal application API
@@ -468,6 +472,7 @@ ecc_curves(all) ->
sect239k1,sect233k1,sect233r1,secp224k1,secp224r1,
sect193r1,sect193r2,secp192k1,secp192r1,sect163k1,
sect163r1,sect163r2,secp160k1,secp160r1,secp160r2];
+
ecc_curves(Minor) ->
TLSCurves = ecc_curves(all),
ecc_curves(Minor, TLSCurves).
@@ -482,6 +487,44 @@ ecc_curves(_Minor, TLSCurves) ->
end
end, [], TLSCurves).
+-spec groups(4 | all) -> [group()].
+groups(all) ->
+ [secp256r1,
+ secp384r1,
+ secp521r1,
+ ffdhe2048,
+ ffdhe3072,
+ ffdhe4096,
+ ffdhe6144,
+ ffdhe8192];
+groups(Minor) ->
+ TLSGroups = groups(all),
+ groups(Minor, TLSGroups).
+%%
+-spec groups(4, [group()]) -> [group()].
+groups(_Minor, TLSGroups) ->
+ %% TODO: Adding FFDHE groups to crypto?
+ CryptoGroups = crypto:ec_curves() ++ [ffdhe2048,ffdhe3072,ffdhe4096,ffdhe6144,ffdhe8192],
+ lists:filter(fun(Group) -> proplists:get_bool(Group, CryptoGroups) end, TLSGroups).
+
+group_to_enum(secp256r1) -> 23;
+group_to_enum(secp384r1) -> 24;
+group_to_enum(secp521r1) -> 25;
+group_to_enum(ffdhe2048) -> 256;
+group_to_enum(ffdhe3072) -> 257;
+group_to_enum(ffdhe4096) -> 258;
+group_to_enum(ffdhe6144) -> 259;
+group_to_enum(ffdhe8192) -> 260.
+
+enum_to_group(23) -> secp256r1;
+enum_to_group(24) -> secp384r1;
+enum_to_group(25) -> secp521r1;
+enum_to_group(256) -> ffdhe2048;
+enum_to_group(257) -> ffdhe3072;
+enum_to_group(258) -> ffdhe4096;
+enum_to_group(259) -> ffdhe6144;
+enum_to_group(260) -> ffdhe8192;
+enum_to_group(_) -> undefined.
%% ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005)
oid_to_enum(?sect163k1) -> 1;
diff --git a/lib/ssl/test/property_test/ssl_eqc_handshake.erl b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
index 99c6554f15..8b3b81aaf1 100644
--- a/lib/ssl/test/property_test/ssl_eqc_handshake.erl
+++ b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
@@ -85,17 +85,14 @@ prop_tls_hs_encode_decode() ->
).
%%--------------------------------------------------------------------
-%% Message Generators --------------------------------------------------
+%% Message Generators -----------------------------------------------
%%--------------------------------------------------------------------
-tls_version() ->
- oneof([?'TLS_v1.3', ?'TLS_v1.2', ?'TLS_v1.1', ?'TLS_v1', ?'SSL_v3']).
-
tls_msg(?'TLS_v1.3'= Version) ->
oneof([client_hello(Version),
server_hello(Version),
%%new_session_ticket()
- #end_of_early_data{},
+ #end_of_early_data{},
encrypted_extensions(),
certificate_1_3(),
%%certificate_request_1_3,
@@ -104,7 +101,8 @@ tls_msg(?'TLS_v1.3'= Version) ->
key_update()
]);
tls_msg(Version) ->
- oneof([#hello_request{},
+ oneof([
+ #hello_request{},
client_hello(Version),
server_hello(Version),
certificate(),
@@ -116,6 +114,9 @@ tls_msg(Version) ->
finished()
]).
+%%
+%% Shared messages
+%%
client_hello(?'TLS_v1.3' = Version) ->
#client_hello{session_id = session_id(),
client_version = ?'TLS_v1.2',
@@ -150,10 +151,6 @@ server_hello(Version) ->
extensions = server_hello_extensions(Version)
}.
-encrypted_extensions() ->
- ?LET(Exts, extensions(?'TLS_v1.3'),
- #encrypted_extensions{extensions = Exts}).
-
certificate() ->
#certificate{
asn1_certificates = certificate_chain()
@@ -166,17 +163,35 @@ certificate_1_3() ->
entries = certificate_entries(Certs, [])
}).
-key_update() ->
- #key_update{request_update = request_update()}.
-
finished() ->
?LET(Size, digest_size(),
#finished{verify_data = crypto:strong_rand_bytes(Size)}).
+%%
+%% TLS 1.0-1.2 messages
+%%
+
+
+
+%%
+%% TLS 1.3 messages
+%%
+
+encrypted_extensions() ->
+ ?LET(Exts, extensions(?'TLS_v1.3', encrypted_extensions),
+ #encrypted_extensions{extensions = Exts}).
+
+
+key_update() ->
+ #key_update{request_update = request_update()}.
+
+
%%--------------------------------------------------------------------
%% Messge Data Generators -------------------------------------------
%%--------------------------------------------------------------------
+tls_version() ->
+ oneof([?'TLS_v1.3', ?'TLS_v1.2', ?'TLS_v1.1', ?'TLS_v1', ?'SSL_v3']).
cipher_suite(Version) ->
oneof(cipher_suites(Version)).
@@ -200,52 +215,14 @@ server_random(_) ->
crypto:strong_rand_bytes(32).
-client_hello_extensions(?'TLS_v1.3' = Version) ->
- ?LET({Versions, Ext}, {supported_versions(Version), c_hello_extensions(Version)},
- maps:merge(Ext, #{client_hello_versions => client_hello_versions(Versions)})
- );
-client_hello_extensions(?'TLS_v1.2' = Version) ->
- ?LET({Versions, Exts}, {supported_versions(Version), c_hello_extensions(Version)},
- maps:merge(Exts, #{client_hello_versions => client_hello_versions(Versions)})
- );
client_hello_extensions(Version) ->
- ?LET(Exts,
- c_hello_extensions(Version),
- maps:merge(empty_hello_extensions(Version, client), Exts)).
-
-server_hello_extensions(?'TLS_v1.3' = Version) ->
- ?LET(Exts,
- s_hello_extensions(Version),
- maps:merge(Exts, #{server_hello_selected_version => server_hello_selected_version(Version)}));
-server_hello_extensions(Version) ->
- ?LET(Exts,
- s_hello_extensions(Version),
- Exts).
-
-c_hello_extensions(?'TLS_v1.3'= Version) ->
- ?LET({KeyShare, PreShare}, {key_share_client_hello(),
- pre_shared_keyextension()},
- maps:merge(empty_hello_extensions(Version, client),
- #{key_share => KeyShare,
- pre_shared_key => PreShare
- })
- );
-c_hello_extensions(Version) ->
- ?LET(Exts, extensions(Version),
- maps:merge(empty_hello_extensions(Version, client),
+ ?LET(Exts, extensions(Version, client_hello),
+ maps:merge(ssl_handshake:empty_extensions(Version, client_hello),
Exts)).
-s_hello_extensions(?'TLS_v1.3'= Version) ->
- ?LET({KeyShare, PreShare}, {key_share_server_hello(),
- pre_shared_keyextension()},
- maps:merge(empty_hello_extensions(Version, server),
- #{key_share => KeyShare,
- pre_shared_key => PreShare
- })
- );
-s_hello_extensions(Version) ->
- ?LET(Exts, extensions(Version),
- maps:merge(empty_hello_extensions(Version, server),
+server_hello_extensions(Version) ->
+ ?LET(Exts, extensions(Version, server_hello),
+ maps:merge(ssl_handshake:empty_extensions(Version, server_hello),
Exts)).
key_share_client_hello() ->
@@ -260,83 +237,260 @@ pre_shared_keyextension() ->
oneof([undefined]).
%%oneof([#pre_shared_keyextension{},undefined]).
-extensions(?'TLS_v1.3') ->
- ?LET({Ext_1_3, Exts}, {extensions_1_3(), extensions(?'TLS_v1.2')}, maps:merge(Ext_1_3, Exts));
-extensions(?'SSL_v3') ->
+%% +--------------------------------------------------+-------------+
+%% | Extension | TLS 1.3 |
+%% +--------------------------------------------------+-------------+
+%% | server_name [RFC6066] | CH, EE |
+%% | | |
+%% | max_fragment_length [RFC6066] | CH, EE |
+%% | | |
+%% | status_request [RFC6066] | CH, CR, CT |
+%% | | |
+%% | supported_groups [RFC7919] | CH, EE |
+%% | | |
+%% | signature_algorithms (RFC 8446) | CH, CR |
+%% | | |
+%% | use_srtp [RFC5764] | CH, EE |
+%% | | |
+%% | heartbeat [RFC6520] | CH, EE |
+%% | | |
+%% | application_layer_protocol_negotiation [RFC7301] | CH, EE |
+%% | | |
+%% | signed_certificate_timestamp [RFC6962] | CH, CR, CT |
+%% | | |
+%% | client_certificate_type [RFC7250] | CH, EE |
+%% | | |
+%% | server_certificate_type [RFC7250] | CH, EE |
+%% | | |
+%% | padding [RFC7685] | CH |
+%% | | |
+%% | key_share (RFC 8446) | CH, SH, HRR |
+%% | | |
+%% | pre_shared_key (RFC 8446) | CH, SH |
+%% | | |
+%% | psk_key_exchange_modes (RFC 8446) | CH |
+%% | | |
+%% | early_data (RFC 8446) | CH, EE, NST |
+%% | | |
+%% | cookie (RFC 8446) | CH, HRR |
+%% | | |
+%% | supported_versions (RFC 8446) | CH, SH, HRR |
+%% | | |
+%% | certificate_authorities (RFC 8446) | CH, CR |
+%% | | |
+%% | oid_filters (RFC 8446) | CR |
+%% | | |
+%% | post_handshake_auth (RFC 8446) | CH |
+%% | | |
+%% | signature_algorithms_cert (RFC 8446) | CH, CR |
+%% +--------------------------------------------------+-------------+
+extensions(?'TLS_v1.3' = Version, client_hello) ->
+ ?LET({
+ ServerName,
+ %% MaxFragmentLength,
+ %% StatusRequest,
+ SupportedGroups,
+ SignatureAlgorithms,
+ %% UseSrtp,
+ %% Heartbeat,
+ ALPN,
+ %% SignedCertTimestamp,
+ %% ClientCertiticateType,
+ %% ServerCertificateType,
+ %% Padding,
+ %% KeyShare,
+ %% PreSharedKey,
+ %% PSKKeyExchangeModes,
+ %% EarlyData,
+ %% Cookie,
+ SupportedVersions,
+ %% CertAuthorities,
+ %% PostHandshakeAuth,
+ SignatureAlgorithmsCert
+ },
+ {
+ oneof([server_name(), undefined]),
+ %% oneof([max_fragment_length(), undefined]),
+ %% oneof([status_request(), undefined]),
+ oneof([supported_groups(Version), undefined]),
+ oneof([signature_algs(Version), undefined]),
+ %% oneof([use_srtp(), undefined]),
+ %% oneof([heartbeat(), undefined]),
+ oneof([alpn(), undefined]),
+ %% oneof([signed_cert_timestamp(), undefined]),
+ %% oneof([client_cert_type(), undefined]),
+ %% oneof([server_cert_type(), undefined]),
+ %% oneof([padding(), undefined]),
+ %% oneof([key_share(), undefined]),
+ %% oneof([pre_shared_key(), undefined]),
+ %% oneof([psk_key_exchange_modes(), undefined]),
+ %% oneof([early_data(), undefined]),
+ %% oneof([cookie(), undefined]),
+ oneof([client_hello_versions(Version), undefined]),
+ %% oneof([cert_authorities(), undefined]),
+ %% oneof([post_handshake_auth(), undefined]),
+ oneof([signature_algs_cert(), undefined])
+ },
+ maps:filter(fun(_, undefined) ->
+ false;
+ (_,_) ->
+ true
+ end,
+ #{
+ sni => ServerName,
+ %% max_fragment_length => MaxFragmentLength,
+ %% status_request => StatusRequest,
+ elliptic_curves => SupportedGroups,
+ signature_algs => SignatureAlgorithms,
+ %% use_srtp => UseSrtp,
+ %% heartbeat => Heartbeat,
+ alpn => ALPN,
+ %% signed_cert_timestamp => SignedCertTimestamp,
+ %% client_cert_type => ClientCertificateType,
+ %% server_cert_type => ServerCertificateType,
+ %% padding => Padding,
+ %% key_share => KeyShare,
+ %% pre_shared_key => PreSharedKey,
+ %% psk_key_exhange_modes => PSKKeyExchangeModes,
+ %% early_data => EarlyData,
+ %% cookie => Cookie,
+ client_hello_versions => SupportedVersions,
+ %% cert_authorities => CertAuthorities,
+ %% post_handshake_auth => PostHandshakeAuth,
+ signature_algs_cert => SignatureAlgorithmsCert
+ }));
+extensions(?'SSL_v3', client_hello) ->
#{};
-extensions(Version) ->
- ?LET({SNI, ECPoitF, ECCurves, ALPN, NextP, SRP},
- {oneof([sni(), undefined]),
- oneof([ec_poit_formats(), undefined]),
+extensions(Version, client_hello) ->
+ ?LET({
+ SNI,
+ ECPoitF,
+ ECCurves,
+ ALPN,
+ NextP,
+ SRP
+ %% RenegotiationInfo
+ },
+ {
+ oneof([sni(), undefined]),
+ oneof([ec_point_formats(), undefined]),
oneof([elliptic_curves(Version), undefined]),
oneof([alpn(), undefined]),
oneof([next_protocol_negotiation(), undefined]),
- oneof([srp(), undefined])},
+ oneof([srp(), undefined])
+ %% oneof([renegotiation_info(), undefined])
+ },
maps:filter(fun(_, undefined) ->
false;
(_,_) ->
true
end,
- #{sni => SNI,
+ #{
+ sni => SNI,
ec_point_formats => ECPoitF,
elliptic_curves => ECCurves,
alpn => ALPN,
next_protocol_negotiation => NextP,
- srp => SRP})).
-
-extensions_1_3() ->
- %% ?LET(Entry, key_share_entry(),
- %% maps:filter(fun(_, undefined) ->
- %% false;
- %% (_,_) ->
- %% true
- %% end, #{key_share_entry => Entry})).
- ?LET({HashSign, SigAlgCert}, {oneof([hash_sign_algos(?'TLS_v1.2')]), oneof([signature_scheme_list()])},
- #{signature_algs => HashSign,
- signature_algs_cert => SigAlgCert}).
-
-empty_hello_extensions({3, 4}, server) ->
- #{server_hello_selected_version => undefined,
- key_share => undefined,
- pre_shared_key => undefined,
- sni => undefined
- };
-empty_hello_extensions({3, 4}, client) ->
- #{client_hello_versions => undefined,
- signature_algs => undefined,
- signature_algs_cert => undefined,
- sni => undefined,
- alpn => undefined,
- key_share => undefined,
- pre_shared_key => undefined
- };
-empty_hello_extensions({3, 3}, client) ->
- Ext = empty_hello_extensions({3,2}, client),
- Ext#{client_hello_versions => undefined,
- signature_algs => undefined,
- signature_algs_cert => undefined};
-empty_hello_extensions(_, client) ->
- #{renegotiation_info => undefined,
- alpn => undefined,
- next_protocol_negotiation => undefined,
- srp => undefined,
- ec_point_formats => undefined,
- elliptic_curves => undefined,
- sni => undefined};
-empty_hello_extensions(_, server) ->
- #{renegotiation_info => undefined,
- alpn => undefined,
- next_protocol_negotiation => undefined,
- ec_point_formats => undefined,
- sni => undefined}.
+ srp => SRP
+ %% renegotiation_info => RenegotiationInfo
+ }));
+extensions(?'TLS_v1.3' = Version, server_hello) ->
+ ?LET({
+ %% KeyShare,
+ %% PreSharedKeys,
+ SupportedVersions
+ },
+ {
+ %% oneof([key_share(), undefined]),
+ %% oneof([pre_shared_keys(), undefined]),
+ oneof([server_hello_selected_version(), undefined])
+ },
+ maps:filter(fun(_, undefined) ->
+ false;
+ (_,_) ->
+ true
+ end,
+ #{
+ %% key_share => KeyShare,
+ %% pre_shared_keys => PreSharedKeys,
+ server_hello_selected_version => SupportedVersions
+ }));
+extensions(Version, server_hello) ->
+ ?LET({
+ ECPoitF,
+ ALPN,
+ NextP
+ %% RenegotiationInfo,
+ },
+ {
+ oneof([ec_point_formats(), undefined]),
+ oneof([alpn(), undefined]),
+ oneof([next_protocol_negotiation(), undefined])
+ %% oneof([renegotiation_info(), undefined]),
+ },
+ maps:filter(fun(_, undefined) ->
+ false;
+ (_,_) ->
+ true
+ end,
+ #{
+ ec_point_formats => ECPoitF,
+ alpn => ALPN,
+ next_protocol_negotiation => NextP
+ %% renegotiation_info => RenegotiationInfo
+ }));
+extensions(?'TLS_v1.3' = Version, encrypted_extensions) ->
+ ?LET({
+ ServerName,
+ %% MaxFragmentLength,
+ SupportedGroups,
+ %% UseSrtp,
+ %% Heartbeat,
+ ALPN
+ %% ClientCertiticateType,
+ %% ServerCertificateType,
+ %% EarlyData
+ },
+ {
+ oneof([server_name(), undefined]),
+ %% oneof([max_fragment_length(), undefined]),
+ oneof([supported_groups(Version), undefined]),
+ %% oneof([use_srtp(), undefined]),
+ %% oneof([heartbeat(), undefined]),
+ oneof([alpn(), undefined])
+ %% oneof([client_cert_type(), undefined]),
+ %% oneof([server_cert_type(), undefined]),
+ %% oneof([early_data(), undefined])
+ },
+ maps:filter(fun(_, undefined) ->
+ false;
+ (_,_) ->
+ true
+ end,
+ #{
+ sni => ServerName,
+ %% max_fragment_length => MaxFragmentLength,
+ elliptic_curves => SupportedGroups,
+ %% use_srtp => UseSrtp,
+ %% heartbeat => Heartbeat,
+ alpn => ALPN
+ %% client_cert_type => ClientCertificateType,
+ %% server_cert_type => ServerCertificateType,
+ %% early_data => EarlyData
+ })).
+
+server_name() ->
+ ?LET(ServerName, sni(),
+ ServerName).
+ %% sni().
signature_algs_cert() ->
- ?LET(Algs, signature_scheme_list(),
- Algs).
+ ?LET(List, sig_scheme_list(),
+ #signature_algorithms_cert{signature_scheme_list = List}).
-signature_scheme_list() ->
+signature_algorithms() ->
?LET(List, sig_scheme_list(),
- #signature_scheme_list{signature_scheme_list = List}).
+ #signature_algorithms{signature_scheme_list = List}).
sig_scheme_list() ->
oneof([[rsa_pkcs1_sha256],
@@ -357,16 +511,23 @@ sig_scheme_list() ->
ecdsa_sha1]
]).
-supported_versions(?'TLS_v1.3') ->
- oneof([[{3,4}],
- [{3,3},{3,4}],
- [{3,4},{3,3},{3,2},{3,1},{3,0}]
- ]);
-supported_versions(_) ->
- oneof([[{3,3}],
- [{3,3},{3,2}],
- [{3,3},{3,2},{3,1},{3,0}]
- ]).
+client_hello_versions(?'TLS_v1.3') ->
+ ?LET(SupportedVersions,
+ oneof([[{3,4}],
+ [{3,3},{3,4}],
+ [{3,4},{3,3},{3,2},{3,1},{3,0}]
+ ]),
+ #client_hello_versions{versions = SupportedVersions});
+client_hello_versions(_) ->
+ ?LET(SupportedVersions,
+ oneof([[{3,3}],
+ [{3,3},{3,2}],
+ [{3,3},{3,2},{3,1},{3,0}]
+ ]),
+ #client_hello_versions{versions = SupportedVersions}).
+
+server_hello_selected_version() ->
+ #server_hello_selected_version{selected_version = {3,4}}.
request_update() ->
oneof([?UPDATE_NOT_REQUESTED, ?UPDATE_REQUESTED]).
@@ -431,13 +592,25 @@ certificate_types(?'TLS_v1.2') ->
certificate_types(_) ->
iolist_to_binary([<<?BYTE(?ECDSA_SIGN)>>, <<?BYTE(?RSA_SIGN)>>, <<?BYTE(?DSS_SIGN)>>]).
+
+
+signature_algs({3,4}) ->
+ ?LET(Algs, signature_algorithms(),
+ Algs);
+signature_algs({3,3} = Version) ->
+ #hash_sign_algos{hash_sign_algos = hash_alg_list(Version)};
+signature_algs(Version) when Version < {3,3} ->
+ undefined.
+
+
+
hashsign_algorithms({_, N} = Version) when N >= 3 ->
#hash_sign_algos{hash_sign_algos = hash_alg_list(Version)};
hashsign_algorithms(_) ->
undefined.
hash_alg_list(Version) ->
- ?LET(NumOf, choose(0,15),
+ ?LET(NumOf, choose(1,15),
?LET(List, [hash_alg(Version) || _ <- lists:seq(1,NumOf)],
lists:usort(List)
)).
@@ -481,27 +654,27 @@ key_share_entry() ->
undefined.
%%#key_share_entry{}.
-client_hello_versions(Versions) ->
- #client_hello_versions{versions = Versions}.
-
server_hello_selected_version(Version) ->
#server_hello_selected_version{selected_version = Version}.
sni() ->
#sni{hostname = net_adm:localhost()}.
-ec_poit_formats() ->
+ec_point_formats() ->
#ec_point_formats{ec_point_format_list = ec_point_format_list()}.
ec_point_format_list() ->
[?ECPOINT_UNCOMPRESSED].
-elliptic_curves({_, Minor}) ->
+elliptic_curves({_, Minor}) when Minor < 4 ->
Curves = tls_v1:ecc_curves(Minor),
#elliptic_curves{elliptic_curve_list = Curves}.
-hash_sign_algos(Version) ->
- #hash_sign_algos{hash_sign_algos = hash_alg_list(Version)}.
+%% RFC 8446 (TLS 1.3) renamed the "elliptic_curve" extension.
+supported_groups({_, Minor}) when Minor >= 4 ->
+ SupportedGroups = tls_v1:groups(Minor),
+ #supported_groups{supported_groups = SupportedGroups}.
+
alpn() ->
?LET(ExtD, alpn_protocols(), #alpn{extension_data = ExtD}).
@@ -520,7 +693,7 @@ renegotiation_info() ->
#renegotiation_info{renegotiated_connection = 0}.
gen_name() ->
- ?LET(Size, choose(0,10), gen_string(Size)).
+ ?LET(Size, choose(1,10), gen_string(Size)).
gen_char() ->
choose($a,$z).
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 861fecc554..c35ee6cb57 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -112,7 +112,7 @@ decode_hello_handshake(_Config) ->
decode_single_hello_extension_correctly(_Config) ->
Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
- Extensions = ssl_handshake:decode_extensions(Renegotiation),
+ Extensions = ssl_handshake:decode_extensions(Renegotiation, {3,3}),
#{renegotiation_info := #renegotiation_info{renegotiated_connection = <<0>>}} = Extensions.
decode_supported_elliptic_curves_hello_extension_correctly(_Config) ->
@@ -200,7 +200,7 @@ signature_algorithms(Config) ->
hash_sign_algos = [{sha512, rsa},
{sha, dsa},
{sha, rsa}]},
- Schemes0 = #signature_scheme_list{
+ Schemes0 = #signature_algorithms_cert{
signature_scheme_list = [rsa_pkcs1_sha1,
ecdsa_sha1]},
{sha512, rsa} = ssl_handshake:select_hashsign(
@@ -216,7 +216,7 @@ signature_algorithms(Config) ->
Cert, ecdhe_rsa,
tls_v1:default_signature_algs({3,3}),
{3,3}),
- Schemes1 = #signature_scheme_list{
+ Schemes1 = #signature_algorithms_cert{
signature_scheme_list = [rsa_pkcs1_sha256,
ecdsa_sha1]},
%% Signature not supported