From 7d294eaafc62af4acf4206e76c4fea7a84f2d410 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 3 Mar 2020 10:26:55 +0100 Subject: public_key: Add support for key exchange with Edward curves --- lib/public_key/asn1/PKIX1Algorithms88.asn1 | 8 ++++++++ lib/public_key/src/pubkey_cert_records.erl | 8 ++++++-- lib/public_key/src/public_key.erl | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/public_key/asn1/PKIX1Algorithms88.asn1 b/lib/public_key/asn1/PKIX1Algorithms88.asn1 index 6cc6745af6..207ab005a9 100644 --- a/lib/public_key/asn1/PKIX1Algorithms88.asn1 +++ b/lib/public_key/asn1/PKIX1Algorithms88.asn1 @@ -283,4 +283,12 @@ sect571k1 OBJECT IDENTIFIER ::= { ellipticCurve 38 } sect571r1 OBJECT IDENTIFIER ::= { ellipticCurve 39 } + + id-edwards-curve-algs OBJECT IDENTIFIER ::= { 1 3 101 } + + id-X25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 110 } + id-X448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 111 } + id-Ed25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 112 } + id-Ed448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 113 } + END diff --git a/lib/public_key/src/pubkey_cert_records.erl b/lib/public_key/src/pubkey_cert_records.erl index 6a80874df8..1c79f904f3 100644 --- a/lib/public_key/src/pubkey_cert_records.erl +++ b/lib/public_key/src/pubkey_cert_records.erl @@ -113,7 +113,8 @@ supportedPublicKeyAlgorithms(?'id-keyExchangeAlgorithm') -> 'KEA-PublicKey'; supportedPublicKeyAlgorithms(?'id-ecPublicKey') -> 'ECPoint'. supportedCurvesTypes(?'characteristic-two-field') -> characteristic_two_field; -supportedCurvesTypes(?'prime-field') -> prime_field. +supportedCurvesTypes(?'prime-field') -> prime_field; +supportedCurvesTypes(?'id-edwards-curve-algs') -> edwards_curve. namedCurves(?'sect571r1') -> sect571r1; namedCurves(?'sect571k1') -> sect571k1; @@ -148,6 +149,8 @@ namedCurves(?'sect163r1') -> sect163r1; namedCurves(?'sect163k1') -> sect163k1; namedCurves(?'secp256r1') -> secp256r1; namedCurves(?'secp192r1') -> secp192r1; +namedCurves(?'id-X25519') -> x25519; +namedCurves(?'id-X448') -> x448; namedCurves(?'brainpoolP160r1') -> brainpoolP160r1; namedCurves(?'brainpoolP160t1') -> brainpoolP160t1; namedCurves(?'brainpoolP192r1') -> brainpoolP192r1; @@ -162,7 +165,6 @@ namedCurves(?'brainpoolP384r1') -> brainpoolP384r1; namedCurves(?'brainpoolP384t1') -> brainpoolP384t1; namedCurves(?'brainpoolP512r1') -> brainpoolP512r1; namedCurves(?'brainpoolP512t1') -> brainpoolP512t1; - namedCurves(sect571r1) -> ?'sect571r1'; namedCurves(sect571k1) -> ?'sect571k1'; namedCurves(sect409r1) -> ?'sect409r1'; @@ -196,6 +198,8 @@ namedCurves(sect163r1) -> ?'sect163r1'; namedCurves(sect163k1) -> ?'sect163k1'; namedCurves(secp256r1) -> ?'secp256r1'; namedCurves(secp192r1) -> ?'secp192r1'; +namedCurves(x25519) -> ?'id-X25519'; +namedCurves(x448) -> ?'id-X448'; namedCurves(brainpoolP160r1) -> ?'brainpoolP160r1'; namedCurves(brainpoolP160t1) -> ?'brainpoolP160t1'; namedCurves(brainpoolP192r1) -> ?'brainpoolP192r1'; diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 47266c514c..ce5151750d 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -1536,6 +1536,10 @@ ec_curve_spec({ecParameters, ECParams}) -> ec_curve_spec(ECParams); ec_curve_spec({namedCurve, OID}) when is_tuple(OID), is_integer(element(1,OID)) -> ec_curve_spec({namedCurve, pubkey_cert_records:namedCurves(OID)}); +ec_curve_spec({namedCurve, x25519 = Name}) -> + Name; +ec_curve_spec({namedCurve, x448 = Name}) -> + Name; ec_curve_spec({namedCurve, Name}) when is_atom(Name) -> crypto:ec_curve(Name). -- cgit v1.2.1 From f7fe3ee24c3fefc94a2688d4e1dcbb068c7b7eb0 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 3 Mar 2020 10:28:12 +0100 Subject: ssl: Add support for key exchange with Edwards curves and RSASSA-PSS in TLS-1.2 --- lib/ssl/src/ssl.app.src | 2 +- lib/ssl/src/ssl_handshake.erl | 20 ++++++++++++++++++++ lib/ssl/src/tls_v1.erl | 6 +++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src index c45e6bcf9a..63ccaabd74 100644 --- a/lib/ssl/src/ssl.app.src +++ b/lib/ssl/src/ssl.app.src @@ -74,5 +74,5 @@ {applications, [crypto, public_key, kernel, stdlib]}, {env, []}, {mod, {ssl_app, []}}, - {runtime_dependencies, ["stdlib-3.5","public_key-1.5","kernel-6.0", + {runtime_dependencies, ["stdlib-3.5","public_key-@OTP-16528@","kernel-6.0", "erts-10.0","crypto-4.2", "inets-5.10.7"]}]}. diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 8e53be72ed..3b33af95d0 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -402,6 +402,12 @@ certificate_verify(Signature, PublicKeyInfo, Version, %%-------------------------------------------------------------------- verify_signature(_Version, _Hash, {_HashAlgo, anon}, _Signature, _) -> true; +verify_signature({3, Minor}, Hash, {HashAlgo, rsa_pss_rsae}, Signature, {?rsaEncryption, PubKey, _PubKeyParams}) + when Minor >= 3 -> + public_key:verify({digest, Hash}, HashAlgo, Signature, PubKey, + [{rsa_padding, rsa_pkcs1_pss_padding}, + {rsa_pss_saltlen, -1}, + {rsa_mgf1_md, HashAlgo}]); verify_signature({3, Minor}, Hash, {HashAlgo, rsa}, Signature, {?rsaEncryption, PubKey, _PubKeyParams}) when Minor >= 3 -> public_key:verify({digest, Hash}, HashAlgo, Signature, PubKey); @@ -2356,6 +2362,20 @@ dec_server_key_params(Len, Keys, Version) -> <> = Keys, dec_server_key_signature(Params, Signature, Version). +dec_server_key_signature(Params, <>, {Major, Minor}) + when Major == 3, Minor >= 3 -> + <> = <>, + Scheme = ssl_cipher:signature_scheme(Scheme0), + {Hash, Sign, _} = ssl_cipher:scheme_to_components(Scheme), + {Params, {Hash, Sign}, <<>>}; +dec_server_key_signature(Params, <>, {Major, Minor}) + when Major == 3, Minor >= 3 -> + <> = <>, + Scheme = ssl_cipher:signature_scheme(Scheme0), + {Hash, Sign, _} = ssl_cipher:scheme_to_components(Scheme), + {Params, {Hash, Sign}, Signature}; dec_server_key_signature(Params, <>, {Major, Minor}) when Major == 3, Minor >= 3 -> diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl index 381793c65d..38594151d9 100644 --- a/lib/ssl/src/tls_v1.erl +++ b/lib/ssl/src/tls_v1.erl @@ -884,7 +884,9 @@ oid_to_enum(?secp384r1) -> 24; oid_to_enum(?secp521r1) -> 25; oid_to_enum(?brainpoolP256r1) -> 26; oid_to_enum(?brainpoolP384r1) -> 27; -oid_to_enum(?brainpoolP512r1) -> 28. +oid_to_enum(?brainpoolP512r1) -> 28; +oid_to_enum(?'id-X25519') -> 29; +oid_to_enum(?'id-X448') -> 30. enum_to_oid(1) -> ?sect163k1; enum_to_oid(2) -> ?sect163r1; @@ -914,5 +916,7 @@ enum_to_oid(25) -> ?secp521r1; enum_to_oid(26) -> ?brainpoolP256r1; enum_to_oid(27) -> ?brainpoolP384r1; enum_to_oid(28) -> ?brainpoolP512r1; +enum_to_oid(29) -> ?'id-X25519'; +enum_to_oid(30) -> ?'id-X448'; enum_to_oid(_) -> undefined. -- cgit v1.2.1 From fa7c7409f42aa8577e56a81efb68044d8a13f873 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 4 Mar 2020 10:16:56 +0100 Subject: ssl: Add TLS-1.3 group to ssl_cipher_suite_SUITE Also fix bug discoverd with the new tests, that is handling of algorithm AES_CCM was missing in tls_sender. --- lib/ssl/src/tls_sender.erl | 4 +- lib/ssl/test/ssl_cipher_suite_SUITE.erl | 95 ++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl index 951d4302e9..790746658e 100644 --- a/lib/ssl/src/tls_sender.erl +++ b/lib/ssl/src/tls_sender.erl @@ -540,7 +540,9 @@ key_update_at(Version, #{security_parameters := ?AES_GCM -> KeyUpdateAt; ?CHACHA20_POLY1305 -> - seq_num_wrap + seq_num_wrap; + ?AES_CCM -> + KeyUpdateAt end; key_update_at(_, _, KeyUpdateAt) -> KeyUpdateAt. diff --git a/lib/ssl/test/ssl_cipher_suite_SUITE.erl b/lib/ssl/test/ssl_cipher_suite_SUITE.erl index e598d662e9..855533cc3d 100644 --- a/lib/ssl/test/ssl_cipher_suite_SUITE.erl +++ b/lib/ssl/test/ssl_cipher_suite_SUITE.erl @@ -32,6 +32,7 @@ %%-------------------------------------------------------------------- all() -> [ + {group, 'tlsv1.3'}, {group, 'tlsv1.2'}, {group, 'tlsv1.1'}, {group, 'tlsv1'}, @@ -42,6 +43,7 @@ all() -> groups() -> [ + {'tlsv1.3', [], tls_1_3_kex()}, {'tlsv1.2', [], kex()}, {'tlsv1.1', [], kex()}, {'tlsv1', [], kex()}, @@ -60,6 +62,7 @@ groups() -> ecdhe_rsa_aes_256_gcm, ecdhe_rsa_chacha20_poly1305 ]}, + {ecdhe_1_3_rsa_cert, [], tls_1_3_cipher_suites()}, {ecdhe_ecdsa, [],[ecdhe_ecdsa_rc4_128, ecdhe_ecdsa_3des_ede_cbc, ecdhe_ecdsa_aes_128_cbc, @@ -127,6 +130,17 @@ groups() -> ]} ]. + +tls_1_3_kex() -> + [{group, ecdhe_1_3_rsa_cert}]. + +tls_1_3_cipher_suites() -> + [aes_256_gcm_sha384, + aes_128_gcm_sha256, + chacha20_poly1305_sha256, + aes_128_ccm_sha256 + ]. + kex() -> rsa() ++ ecdsa() ++ dss() ++ anonymous(). @@ -186,7 +200,13 @@ end_per_suite(_Config) -> ssl:stop(), application:stop(crypto). - +init_per_group(GroupName, Config) when GroupName == ecdhe_1_3_rsa_cert -> + case proplists:get_bool(ecdh, proplists:get_value(public_keys, crypto:supports())) of + true -> + init_certs(GroupName, Config); + false -> + {skip, "Missing EC crypto support"} + end; init_per_group(GroupName, Config) when GroupName == ecdh_anon; GroupName == ecdhe_rsa; GroupName == ecdhe_psk -> @@ -318,6 +338,53 @@ init_per_testcase(TestCase, Config) when TestCase == psk_aes_256_ccm_8; _ -> {skip, "Missing AES_256_CCM crypto support"} end; +init_per_testcase(aes_256_gcm_sha384, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(aes_256_gcm, SupCiphers)) andalso + (lists:member(sha384, SupHashs)) + of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing AES_256_GCM_SHA384 crypto support"} + end; +init_per_testcase(aes_128_gcm_sha256, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(aes_256_gcm, SupCiphers)) andalso + (lists:member(sha256, SupHashs)) + of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing AES_128_GCM_SHA256 crypto support"} + end; +init_per_testcase(chacha20_poly1305_sha256, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(chacha20_poly1305, SupCiphers)) andalso + (lists:member(sha256, SupHashs)) + of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing chacha20_poly1305_sha256 crypto support"} + end; +init_per_testcase(aes_128_ccm_sha256, Config) -> + SupCiphers = proplists:get_value(ciphers, crypto:supports()), + SupHashs = proplists:get_value(hashs, crypto:supports()), + case (lists:member(aes_128_ccm, SupCiphers)) andalso + (lists:member(sha256, SupHashs)) of + true -> + ct:timetrap({seconds, 5}), + Config; + _ -> + {skip, "Missing AES_128_CCM_SHA256 crypto support"} + end; init_per_testcase(TestCase, Config) -> Cipher = ssl_test_lib:test_cipher(TestCase, Config), SupCiphers = proplists:get_value(ciphers, crypto:supports()), @@ -335,7 +402,6 @@ end_per_testcase(_TestCase, Config) -> %%-------------------------------------------------------------------- %% Initializtion ------------------------------------------ %%-------------------------------------------------------------------- - init_certs(srp_rsa, Config) -> DefConf = ssl_test_lib:default_cert_chain_conf(), CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf), @@ -367,6 +433,14 @@ init_certs(rsa, Config) -> [{tls_config, #{server_config => ServerOpts, client_config => ClientOpts}} | proplists:delete(tls_config, Config)]; +init_certs(ecdhe_1_3_rsa_cert, Config) -> + ClientExt = x509_test:extensions([{key_usage, [digitalSignature]}]), + {ClientOpts, ServerOpts} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[],[{extensions, ClientExt}]]}], + Config, "_peer_rsa_digitalsign"), + [{tls_config, #{server_config => ServerOpts, + client_config => ClientOpts}} | + proplists:delete(tls_config, Config)]; init_certs(dhe_dss, Config) -> DefConf = ssl_test_lib:default_cert_chain_conf(), CertChainConf = ssl_test_lib:gen_conf(dsa, dsa, DefConf, DefConf), @@ -427,6 +501,22 @@ init_certs(_GroupName, Config) -> %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- +aes_256_gcm_sha384(Config) when is_list(Config)-> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_AES_256_GCM_SHA384"), Version, Config). + +aes_128_gcm_sha256(Config) when is_list(Config) -> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_AES_128_GCM_SHA256"), Version, Config). + +chacha20_poly1305_sha256(Config) when is_list(Config) -> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_CHACHA20_POLY1305_SHA256"), Version, Config). + +aes_128_ccm_sha256(Config) when is_list(Config) -> + Version = ssl_test_lib:protocol_version(Config), + cipher_suite_test(ssl:str_to_suite("TLS_AES_128_CCM_SHA256"), Version, Config). + %%-------------------------------------------------------------------- %% SRP -------------------------------------------------------- %%-------------------------------------------------------------------- @@ -775,3 +865,4 @@ test_ciphers(Kex, Cipher, Version) -> (_) -> false end}]). + -- cgit v1.2.1