File 1544-ssl-Add-SLH-DSA-support.patch of Package erlang
From 2c2609128a0a3ca517ef0c1689e800731f865320 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Tue, 18 Nov 2025 16:40:03 +0100
Subject: [PATCH 4/5] ssl: Add SLH-DSA support
Also remove white space errors and too long lines and
no longer needed deprecation supressions.
---
lib/ssl/src/ssl.app.src | 2 +-
lib/ssl/src/ssl.erl | 81 ++++--
lib/ssl/src/ssl_certificate.erl | 2 +-
lib/ssl/src/ssl_cipher.erl | 60 ++++
lib/ssl/src/ssl_config.erl | 30 ++
lib/ssl/src/ssl_connection.hrl | 1 +
lib/ssl/src/ssl_handshake.erl | 18 +-
lib/ssl/src/tls_handshake_1_3.erl | 39 +--
lib/ssl/src/tls_handshake_1_3.hrl | 14 +
lib/ssl/src/tls_v1.erl | 41 ++-
lib/ssl/test/ssl_cert_SUITE.erl | 438 ++++++++++++++++++------------
lib/ssl/test/ssl_cert_tests.erl | 377 +++++++++++++++++--------
lib/ssl/test/ssl_test_lib.erl | 18 ++
13 files changed, 768 insertions(+), 353 deletions(-)
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 4e89c9bdda..3e099902b9 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -424,6 +424,7 @@ still disallow sha1 use in the TLS protocol, since 27.0.1 and 26.2.5.2.
| ecdsa_brainpoolP512r1tls13_sha512
| ecdsa_brainpoolP384r1tls13_sha384
| ecdsa_brainpoolP256r1tls13_sha256
+ | post_quantum_schemes()
| rsassa_pss_scheme()
| legacy_sign_scheme() . % exported
@@ -439,6 +440,13 @@ Supported in TLS-1.3 and TLS-1.2.
| rsa_pss_pss_sha384
| rsa_pss_pss_sha256.
+-doc(#{group => <<"Algorithms">>}).
+-doc """
+Supported in TLS-1.3 only. ML-DSA since 28.1, SLH-DSA since 28.3.
+""".
+-type post_quantum_schemes() :: crypto:mldsa() | crypto:slh_dsa().
+
+
-doc(#{group => <<"Algorithms Legacy">>}).
-doc """
This is only used for certificate signatures if TLS-1.2 is negotiated,
@@ -3006,33 +3014,45 @@ Example:
```erlang
1> ssl:signature_algs(default, 'tlsv1.3').
[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
-ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,
-rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,
-rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,
-rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,
-{sha512,ecdsa},
-{sha384,ecdsa},
-{sha256,ecdsa}]
+ ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,
+ ecdsa_brainpoolP512r1tls13_sha512,
+ ecdsa_brainpoolP384r1tls13_sha384,
+ ecdsa_brainpoolP256r1tls13_sha256,rsa_pss_pss_sha512,
+ rsa_pss_pss_sha384,rsa_pss_pss_sha256,rsa_pss_rsae_sha512,
+ rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,mldsa44,mldsa65,
+ mldsa87,rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,
+ {sha512,ecdsa},
+ {sha384,ecdsa},
+ {sha256,ecdsa}]
2> ssl:signature_algs(all, 'tlsv1.3').
-[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
-ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,
-rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,
-rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,
-rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,
-{sha512,ecdsa},
-{sha384,ecdsa},
-{sha256,ecdsa},
-{sha224,ecdsa},
-{sha224,rsa},
-{sha,rsa},
-{sha,dsa}]
-
-3> ssl:signature_algs(exclusive, 'tlsv1.3').
-[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
-ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,
-rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,
-rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256]
+[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,ecdsa_secp384r1_sha384,
+ ecdsa_secp256r1_sha256,ecdsa_brainpoolP512r1tls13_sha512,
+ ecdsa_brainpoolP384r1tls13_sha384,ecdsa_brainpoolP256r1tls13_sha256,
+ rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,rsa_pss_rsae_sha512,
+ rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,mldsa44,mldsa65,mldsa87,
+ rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,
+ {sha512,ecdsa},
+ {sha384,ecdsa},
+ {sha256,ecdsa},
+ slh_dsa_shake_256f,slh_dsa_shake_256s,slh_dsa_sha2_256f,slh_dsa_sha2_256s,
+ slh_dsa_shake_192f,slh_dsa_shake_192s,slh_dsa_sha2_192f,slh_dsa_sha2_192s,
+ slh_dsa_shake_128f,slh_dsa_shake_128s,slh_dsa_sha2_128f,slh_dsa_sha2_128s,
+ ecdsa_sha1,rsa_pkcs1_sha1,
+ {sha224,ecdsa},
+ {sha224,rsa},
+ {sha,dsa}]
+
+3> [ssl:signature_algs(exclusive, 'tlsv1.3').
+[eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,ecdsa_secp384r1_sha384,
+ ecdsa_secp256r1_sha256,ecdsa_brainpoolP512r1tls13_sha512,
+ ecdsa_brainpoolP384r1tls13_sha384,ecdsa_brainpoolP256r1tls13_sha256,
+ rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,rsa_pss_rsae_sha512,
+ rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,mldsa44,mldsa65,mldsa87,
+ rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256,slh_dsa_shake_256f,
+ slh_dsa_shake_256s,slh_dsa_sha2_256f,slh_dsa_sha2_256s,slh_dsa_shake_192f,
+ slh_dsa_shake_192s,slh_dsa_sha2_192f,slh_dsa_sha2_192s,slh_dsa_shake_128f,
+ slh_dsa_shake_128s,slh_dsa_sha2_128f,slh_dsa_sha2_128s]
```
> #### Note {: .info }
@@ -3051,19 +3071,22 @@ rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256]
%%--------------------------------------------------------------------
signature_algs(default, 'tlsv1.3') ->
- tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.3'),
+ tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.3'),
tls_record:protocol_version_name('tlsv1.2')]);
signature_algs(default, 'tlsv1.2') ->
tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.2')]);
signature_algs(all, 'tlsv1.3') ->
tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.3'),
tls_record:protocol_version_name('tlsv1.2')]) ++
- [ecdsa_sha1, rsa_pkcs1_sha1 | tls_v1:legacy_signature_algs_pre_13()] -- [{sha, ecdsa}, {sha, rsa}];
+ tls_v1:slh_dsa_schemes() ++
+ [ecdsa_sha1, rsa_pkcs1_sha1 | tls_v1:legacy_signature_algs_pre_13()] --
+ [{sha, ecdsa}, {sha, rsa}];
signature_algs(all, 'tlsv1.2') ->
- tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.2')]) ++
+ tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.2')]) ++
tls_v1:legacy_signature_algs_pre_13();
signature_algs(exclusive, 'tlsv1.3') ->
- tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.3')]);
+ tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.3')]) ++
+ tls_v1:slh_dsa_schemes();
signature_algs(exclusive, 'tlsv1.2') ->
Algs = tls_v1:default_signature_algs([tls_record:protocol_version_name('tlsv1.2')]),
Algs ++ tls_v1:legacy_signature_algs_pre_13();
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 274dcf19f6..cc151c8ad6 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -361,7 +361,7 @@ available_cert_key_pairs(CertKeyGroups) ->
%% Create the prioritized list of cert key pairs that
%% are availble for use in the negotiated version
available_cert_key_pairs(CertKeyGroups, ?TLS_1_3) ->
- RevAlgos = [mldsa, rsa, rsa_pss_pss, ecdsa, eddsa],
+ RevAlgos = [slhdsa, mldsa, rsa, rsa_pss_pss, ecdsa, eddsa],
cert_key_group_to_list(RevAlgos, CertKeyGroups, []);
available_cert_key_pairs(CertKeyGroups, ?TLS_1_2) ->
RevAlgos = [dsa, rsa, rsa_pss_pss, ecdsa],
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 36f2ad638c..98729356a3 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -599,6 +599,18 @@ signature_scheme(ecdsa_sha1) -> ?ECDSA_SHA1;
signature_scheme(mldsa44) -> ?MLDSA44;
signature_scheme(mldsa65) -> ?MLDSA65;
signature_scheme(mldsa87) -> ?MLDSA87;
+signature_scheme(slh_dsa_sha2_128f) -> ?SLHDSA_SHA2_128F;
+signature_scheme(slh_dsa_sha2_128s) -> ?SLHDSA_SHA2_128S;
+signature_scheme(slh_dsa_sha2_192f) -> ?SLHDSA_SHA2_192F;
+signature_scheme(slh_dsa_sha2_192s) -> ?SLHDSA_SHA2_192S;
+signature_scheme(slh_dsa_sha2_256f) -> ?SLHDSA_SHA2_256F;
+signature_scheme(slh_dsa_sha2_256s) -> ?SLHDSA_SHA2_256S;
+signature_scheme(slh_dsa_shake_128f) -> ?SLHDSA_SHAKE_128F;
+signature_scheme(slh_dsa_shake_128s) -> ?SLHDSA_SHAKE_128S;
+signature_scheme(slh_dsa_shake_192f) -> ?SLHDSA_SHAKE_192F;
+signature_scheme(slh_dsa_shake_192s) -> ?SLHDSA_SHAKE_192S;
+signature_scheme(slh_dsa_shake_256f) -> ?SLHDSA_SHAKE_256F;
+signature_scheme(slh_dsa_shake_256s) -> ?SLHDSA_SHAKE_256S;
%% New algorithms on legacy format
signature_scheme({sha512, rsa_pss_pss}) ->
@@ -641,6 +653,18 @@ signature_scheme(?ECDSA_SHA1) -> ecdsa_sha1;
signature_scheme(?MLDSA44) -> mldsa44;
signature_scheme(?MLDSA65) -> mldsa65;
signature_scheme(?MLDSA87) -> mldsa87;
+signature_scheme(?SLHDSA_SHA2_128F) -> slh_dsa_sha2_128f;
+signature_scheme(?SLHDSA_SHA2_128S) -> slh_dsa_sha2_128s;
+signature_scheme(?SLHDSA_SHA2_192F) -> slh_dsa_sha2_192f;
+signature_scheme(?SLHDSA_SHA2_192S) -> slh_dsa_sha2_192s;
+signature_scheme(?SLHDSA_SHA2_256F) -> slh_dsa_sha2_256f;
+signature_scheme(?SLHDSA_SHA2_256S) -> slh_dsa_sha2_256s;
+signature_scheme(?SLHDSA_SHAKE_128F) -> slh_dsa_shake_128f;
+signature_scheme(?SLHDSA_SHAKE_128S) -> slh_dsa_shake_128s;
+signature_scheme(?SLHDSA_SHAKE_192F) -> slh_dsa_shake_192f;
+signature_scheme(?SLHDSA_SHAKE_192S) -> slh_dsa_shake_192s;
+signature_scheme(?SLHDSA_SHAKE_256F) -> slh_dsa_shake_256f;
+signature_scheme(?SLHDSA_SHAKE_256S) -> slh_dsa_shake_256s;
%% Handling legacy signature algorithms for logging purposes. These algorithms
%% cannot be used in TLS 1.3 handshakes.
@@ -712,6 +736,18 @@ scheme_to_components(ecdsa_sha1) -> {sha, ecdsa, undefined};
scheme_to_components(mldsa44) -> {none, mldsa44, undefined};
scheme_to_components(mldsa65) -> {none, mldsa65, undefined};
scheme_to_components(mldsa87) -> {none, mldsa87, undefined};
+scheme_to_components(slh_dsa_sha2_128f = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_sha2_128s = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_sha2_192f = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_sha2_192s = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_sha2_256f = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_sha2_256s = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_shake_128f = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_shake_128s = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_shake_192f = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_shake_192s = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_shake_256f = Scheme) -> {Scheme, slhdsa, undefined};
+scheme_to_components(slh_dsa_shake_256s = Scheme) -> {Scheme, slhdsa, undefined};
%% Handling legacy signature algorithms
scheme_to_components({Hash,Sign}) -> {Hash, Sign, undefined}.
@@ -890,6 +926,30 @@ signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-ml-dsa-65'}
mldsa65;
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-ml-dsa-87'}) ->
mldsa87;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-shake-256f'}) ->
+ slh_dsa_shake_256f;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-shake-192f'}) ->
+ slh_dsa_shake_192f;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-shake-128f'}) ->
+ slh_dsa_shake_128f;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-shake-256s'}) ->
+ slh_dsa_shake_256s;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-shake-192s'}) ->
+ slh_dsa_shake_192s;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-shake-128s'}) ->
+ slh_dsa_shake_128s;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-sha2-256f'}) ->
+ slh_dsa_sha2_256f;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-sha2-192f'}) ->
+ slh_dsa_sha2_192f;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-sha2-128f'}) ->
+ slh_dsa_sha2_128f;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-sha2-256s'}) ->
+ slh_dsa_sha2_256s;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-sha2-192s'}) ->
+ slh_dsa_sha2_192s;
+signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-slh-dsa-sha2-128s'}) ->
+ slh_dsa_sha2_128s;
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?sha256WithRSAEncryption}) ->
rsa_pkcs1_sha256;
signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?sha384WithRSAEncryption}) ->
diff --git a/lib/ssl/src/ssl_config.erl b/lib/ssl/src/ssl_config.erl
index eeaedb2fac..ac5c4481a2 100644
--- a/lib/ssl/src/ssl_config.erl
+++ b/lib/ssl/src/ssl_config.erl
@@ -162,6 +162,7 @@ group_pairs([#{certs := []}]) ->
rsa_pss_pss => [],
rsa => [],
mldsa => [],
+ slhdsa => [],
dsa => []
};
group_pairs(Pairs) ->
@@ -170,6 +171,7 @@ group_pairs(Pairs) ->
rsa_pss_pss => [],
rsa => [],
mldsa => [],
+ slhdsa => [],
dsa => []
}).
@@ -188,6 +190,8 @@ group_pairs([#{private_key := #'RSAPrivateKey'{}} = Pair | Rest], #{rsa := RSA}
group_pairs(Rest, Group#{rsa => [Pair | RSA]});
group_pairs([#{private_key := #'ML-DSAPrivateKey'{}} = Pair | Rest], #{mldsa := MLDSA} = Group) ->
group_pairs(Rest, Group#{mldsa => [Pair | MLDSA]});
+group_pairs([#{private_key := #'SLH-DSAPrivateKey'{}} = Pair | Rest], #{slhdsa := SLHDSA} = Group) ->
+ group_pairs(Rest, Group#{slhdsa => [Pair | SLHDSA]});
group_pairs([#{private_key := #'DSAPrivateKey'{}} = Pair | Rest], #{dsa := DSA} = Group) ->
group_pairs(Rest, Group#{dsa => [Pair | DSA]});
group_pairs([#{private_key := #{algorithm := dss, engine := _}} = Pair | Rest], Group) ->
@@ -207,6 +211,7 @@ prioritize_groups(#{eddsa := EDDSA,
rsa_pss_pss := RSAPSS,
rsa := RSA,
mldsa := MLDSA,
+ slhdsa := SLHDSA,
dsa := DSA} = CertKeyGroups, Opts) ->
EC = ecdsa_support(Opts),
CertKeyGroups#{eddsa => prio_eddsa(EDDSA),
@@ -214,6 +219,7 @@ prioritize_groups(#{eddsa := EDDSA,
rsa_pss_pss => prio_rsa_pss(RSAPSS),
rsa => prio_rsa(RSA),
mldsa => prio_mldsa(MLDSA),
+ slhdsa => prio_slhdsa(SLHDSA),
dsa => prio_dsa(DSA)}.
prio_eddsa(EDDSA) ->
%% Engine not supported yet
@@ -276,6 +282,12 @@ prio_mldsa(MLDSA) ->
SignFunPairs
++ lists:keysort(#'ML-DSAPrivateKey'.algorithm, MLDSA -- SignFunPairs).
+prio_slhdsa(SLHDSA) ->
+ %% Engine not supported yet
+ SignFunPairs = [Pair || Pair = #{private_key := #{sign_fun := _}} <- SLHDSA],
+ SignFunPairs
+ ++ lists:keysort(#'SLH-DSAPrivateKey'.algorithm, SLHDSA -- SignFunPairs).
+
prio_dsa(DSA) ->
Order = fun(#{key := #'DSAPrivateKey'{q = N}},
#{key := #'DSAPrivateKey'{q = M}}) when M > N ->
@@ -309,6 +321,22 @@ private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
#'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-ml-dsa-87'},
privateKey = DerKey}) ->
mldsa_priv_key_dec('ML-DSA-87-PrivateKey', DerKey, #'ML-DSAPrivateKey'{algorithm = mldsa87});
+private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
+ #'PrivateKeyInfo_privateKeyAlgorithm'{
+ algorithm = Algorithm},
+ privateKey = DerKey}) when Algorithm == ?'id-slh-dsa-sha2-128f';
+ Algorithm == ?'id-slh-dsa-sha2-128s';
+ Algorithm == ?'id-slh-dsa-sha2-192f';
+ Algorithm == ?'id-slh-dsa-sha2-192s';
+ Algorithm == ?'id-slh-dsa-sha2-256f';
+ Algorithm == ?'id-slh-dsa-sha2-256s';
+ Algorithm == ?'id-slh-dsa-shake-128f';
+ Algorithm == ?'id-slh-dsa-shake-128s';
+ Algorithm == ?'id-slh-dsa-shake-192f';
+ Algorithm == ?'id-slh-dsa-shake-192s';
+ Algorithm == ?'id-slh-dsa-shake-256f';
+ Algorithm == ?'id-slh-dsa-shake-256s' ->
+ public_key:der_decode('SLH-DSA-PrivateKey', DerKey);
private_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
#'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-ecPublicKey',
parameters = {asn1_OPENTYPE, Parameters}},
@@ -2240,6 +2268,8 @@ check_key(#'ECPrivateKey'{}) ->
ok;
check_key(#'ML-DSAPrivateKey'{}) ->
ok;
+check_key(#'SLH-DSAPrivateKey'{}) ->
+ ok;
check_key(NotKey) ->
{error, {unexpected_content, NotKey}}.
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index a6db74460b..48ff3d2fc5 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -119,6 +119,7 @@
cert_key_alts = undefined :: #{eddsa => list(),
ecdsa => list(),
mldsa => list(),
+ slhdsa => list(),
rsa_pss_pss => list(),
rsa => list(),
dsa => list()
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 8a975a909b..851625412a 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -50,15 +50,6 @@
#client_key_exchange{} | #finished{} | #certificate_verify{} |
#hello_request{} | #next_protocol{} | #end_of_early_data{}.
-%% Needed for legacy TLS-1.0 and TLS-1.1 functionality
--compile({nowarn_deprecated_function, [{crypto, private_encrypt, 4},
- {crypto, private_decrypt, 4},
- {public_key, encrypt_private, 3},
- {public_key, decrypt_private, 3},
- {public_key, encrypt_public, 3},
- {public_key, decrypt_public, 3}
- ]}).
-
%% Create handshake messages
-export([hello_request/0,
server_hello/4,
@@ -462,6 +453,8 @@ verify_signature(?TLS_1_3, Msg, {_, mldsa65}, Signature,
verify_signature(?TLS_1_3, Msg, {_, mldsa87}, Signature,
{?'id-ml-dsa-87', #'ML-DSAPublicKey'{algorithm = mldsa87} = PubKey,_}) ->
public_key:verify(Msg, none, Signature, PubKey);
+verify_signature(?TLS_1_3, Msg, {_ , slhdsa}, Signature, {_, #'SLH-DSAPublicKey'{} = PubKey,_}) ->
+ public_key:verify(Msg, none, Signature, PubKey);
verify_signature(?TLS_1_3, Msg, {_, eddsa}, Signature, {?'id-Ed25519', PubKey, PubKeyParams}) ->
public_key:verify(Msg, none, Signature, {PubKey, PubKeyParams});
verify_signature(?TLS_1_3, Msg, {_, eddsa}, Signature, {?'id-Ed448', PubKey, PubKeyParams}) ->
@@ -2220,6 +2213,11 @@ do_digitally_signed(Version, Msg, HashAlgo, #'ML-DSAPrivateKey'{}= Key,
SignAlgo == mldsa65 orelse
SignAlgo == mldsa87) ->
public_key:sign(Msg, HashAlgo, Key);
+do_digitally_signed(Version, Msg, _, #'SLH-DSAPrivateKey'{}= Key,
+ slhdsa) when ?TLS_GTE(Version, ?TLS_1_3) ->
+ %% HashAlgo will in this case be the full scheme that public_key/crypto deduces from the key.
+ %% and none should be used for second argument.
+ public_key:sign(Msg, none, Key);
do_digitally_signed(Version, Msg, HashAlgo, {#'RSAPrivateKey'{} = Key,
#'RSASSA-PSS-params'{}},
SignAlgo) when ?TLS_GTE(Version, ?TLS_1_2) ->
@@ -2286,6 +2284,8 @@ bad_key(#'ECPrivateKey'{}) ->
unacceptable_ecdsa_key;
bad_key(#'ML-DSAPrivateKey'{}) ->
unacceptable_mldsa_key;
+bad_key(#'SLH-DSAPrivateKey'{}) ->
+ unacceptable_slhdsa_key;
bad_key(#{algorithm := rsa}) ->
unacceptable_rsa_key;
bad_key(#{algorithm := rsa_pss_pss}) ->
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
index 6ecc881415..482c3d03b3 100644
--- a/lib/ssl/src/tls_handshake_1_3.erl
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -1594,22 +1594,19 @@ select_sign_algo(_, _RSAKeySize, [], _, _) ->
select_sign_algo(_, _RSAKeySize, undefined, _OwnSignAlgs, _) ->
{error, ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_public_key)};
select_sign_algo(PublicKeyAlgo, RSAKeySize, [CertSignAlg|CertSignAlgs], OwnSignAlgs, Curve) ->
- {_, S, _} = ssl_cipher:scheme_to_components(CertSignAlg),
+ Sign = case ssl_cipher:scheme_to_components(CertSignAlg) of
+ {S, slhdsa, _} ->
+ S;
+ {_, S, _} ->
+ S
+ end,
%% RSASSA-PKCS1-v1_5 and Legacy algorithms are not defined for use in signed
- %% TLS handshake messages: filter sha-1 and rsa_pkcs1.
+ %% TLS handshake messages: Has been filtered out in get_signature_scheme_list
%%
%% RSASSA-PSS RSAE algorithms: If the public key is carried in an X.509
%% certificate, it MUST use the rsaEncryption OID.
- %% RSASSA-PSS PSS algorithms: If the public key is carried in an X.509 certificate,
- %% it MUST use the RSASSA-PSS OID.
- case ((PublicKeyAlgo =:= rsa andalso S =:= rsa_pss_rsae)
- orelse (PublicKeyAlgo =:= rsa_pss_pss andalso S =:= rsa_pss_pss)
- orelse (PublicKeyAlgo =:= ecdsa andalso S =:= ecdsa)
- orelse (PublicKeyAlgo =:= eddsa andalso S =:= eddsa)
- orelse (PublicKeyAlgo =:= mldsa44 andalso S =:= mldsa44)
- orelse (PublicKeyAlgo =:= mldsa65 andalso S =:= mldsa65)
- orelse (PublicKeyAlgo =:= mldsa87 andalso S =:= mldsa87)
- )
+ case ((PublicKeyAlgo =:= rsa andalso Sign =:= rsa_pss_rsae)
+ orelse (PublicKeyAlgo =:= Sign))
andalso
lists:member(CertSignAlg, OwnSignAlgs) of
true ->
@@ -1685,6 +1682,8 @@ compare_sign_algos(rsa, Hash, Algo, Hash)
when Algo =:= rsa_pss_rsae orelse
Algo =:= rsa_pkcs1 ->
true;
+compare_sign_algos(Algo, none, slhdsa, Algo) ->
+ true;
compare_sign_algos(Algo, Hash, Algo, Hash) ->
true;
compare_sign_algos(_, _, _, _) ->
@@ -1705,25 +1704,17 @@ oids_to_atoms(?'id-RSASSA-PSS', #'RSASSA-PSS-params'{maskGenAlgorithm =
oids_to_atoms(SignAlgo, _) ->
public_key:pkix_sign_types(SignAlgo).
-%% Note: copied from ssl_handshake
public_key_algo(?'id-RSASSA-PSS') ->
rsa_pss_pss;
public_key_algo(?rsaEncryption) ->
rsa;
public_key_algo(?'id-ecPublicKey') ->
ecdsa;
-public_key_algo(?'id-Ed25519') ->
- eddsa;
-public_key_algo(?'id-Ed448') ->
- eddsa;
-public_key_algo(?'id-ml-dsa-44') ->
- mldsa44;
-public_key_algo(?'id-ml-dsa-65') ->
- mldsa65;
-public_key_algo(?'id-ml-dsa-87') ->
- mldsa87;
public_key_algo(?'id-dsa') ->
- dsa.
+ dsa;
+public_key_algo(Oid) ->
+ {_, Algo } =public_key:pkix_sign_types(Oid),
+ Algo.
get_signature_scheme_list(undefined) ->
undefined;
diff --git a/lib/ssl/src/tls_handshake_1_3.hrl b/lib/ssl/src/tls_handshake_1_3.hrl
index ac7c081336..29da65dc8d 100644
--- a/lib/ssl/src/tls_handshake_1_3.hrl
+++ b/lib/ssl/src/tls_handshake_1_3.hrl
@@ -166,6 +166,20 @@
-define(MLDSA65, 16#0905).
-define(MLDSA87, 16#0906).
+%% SLH-DSA
+-define(SLHDSA_SHA2_128S, 16#0911).
+-define(SLHDSA_SHA2_128F, 16#0912).
+-define(SLHDSA_SHA2_192S, 16#0913).
+-define(SLHDSA_SHA2_192F, 16#0914).
+-define(SLHDSA_SHA2_256S, 16#0915).
+-define(SLHDSA_SHA2_256F, 16#0916).
+-define(SLHDSA_SHAKE_128S, 16#0917).
+-define(SLHDSA_SHAKE_128F, 16#0918).
+-define(SLHDSA_SHAKE_192S, 16#0919).
+-define(SLHDSA_SHAKE_192F, 16#091A).
+-define(SLHDSA_SHAKE_256S, 16#091B).
+-define(SLHDSA_SHAKE_256F, 16#091C).
+
%% Legacy algorithms
-define(RSA_PKCS1_SHA1, 16#201).
-define(ECDSA_SHA1, 16#0203).
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index 34c483556e..6e023e119c 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -64,6 +64,7 @@
legacy_signature_algs_pre_13/0,
signature_algs/2,
signature_schemes/2,
+ slh_dsa_schemes/0,
rsa_schemes/0,
groups/0,
groups/1,
@@ -967,7 +968,31 @@ signature_schemes(Version, [_|_] =SignatureSchemes) when is_tuple(Version)
[Scheme | Acc];
(mldsa87 = Scheme, Acc)->
[Scheme | Acc];
- (Scheme, Acc) when is_atom(Scheme) ->
+ (slh_dsa_shake_256f = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_shake_256s = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_shake_192f = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_shake_192s = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_shake_128f = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_shake_128s = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_sha2_256f = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_sha2_256s = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_sha2_192f = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_sha2_192s = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_sha2_128f = Scheme, Acc)->
+ [Scheme | Acc];
+ (slh_dsa_sha2_128s = Scheme, Acc)->
+ [Scheme | Acc];
+ (Scheme, Acc) when is_atom(Scheme) ->
{Hash, Sign0, Curve} =
ssl_cipher:scheme_to_components(Scheme),
Sign = case Sign0 of
@@ -1073,6 +1098,20 @@ rsa_schemes() ->
[]
end.
+slh_dsa_schemes() ->
+ [slh_dsa_shake_256f,
+ slh_dsa_shake_256s,
+ slh_dsa_sha2_256f,
+ slh_dsa_sha2_256s,
+ slh_dsa_shake_192f,
+ slh_dsa_shake_192s,
+ slh_dsa_sha2_192f,
+ slh_dsa_sha2_192s,
+ slh_dsa_shake_128f,
+ slh_dsa_shake_128s,
+ slh_dsa_sha2_128f,
+ slh_dsa_sha2_128s].
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_cert_SUITE.erl b/lib/ssl/test/ssl_cert_SUITE.erl
index 46a031f021..0c7d6bfcb3 100644
--- a/lib/ssl/test/ssl_cert_SUITE.erl
+++ b/lib/ssl/test/ssl_cert_SUITE.erl
@@ -169,27 +169,32 @@ all() ->
groups() ->
[
- {'tlsv1.3', [], tls_1_3_protocol_groups()},
+ {'tlsv1.3', [], tls_1_3_protocol_groups()},
{'tlsv1.2', [], tls_1_2_protocol_groups()},
{'tlsv1.1', [], ssl_protocol_groups()},
{'tlsv1', [], ssl_protocol_groups()},
{'dtlsv1.2', [], tls_1_2_protocol_groups()},
{'dtlsv1', [], ssl_protocol_groups()},
- {rsa, [parallel], all_version_tests() ++ rsa_tests() ++ pre_tls_1_3_rsa_tests() ++ [client_auth_seelfsigned_peer]},
+ {rsa, [parallel], all_version_tests() ++ rsa_tests() ++
+ pre_tls_1_3_rsa_tests() ++ [client_auth_seelfsigned_peer]},
{ecdsa, [parallel], all_version_tests() ++ partial_chain_with_ecdsa()},
{dsa, [parallel], all_version_tests()},
{rsa_1_3, [parallel], all_version_tests() ++ rsa_tests() ++
tls_1_3_tests() ++ tls_1_3_rsa_tests() ++ [client_auth_seelfsigned_peer, basic_rsa_1024]},
{rsa_pss_rsae, [parallel], all_version_tests() ++ tls_1_2_rsa_tests()},
- {rsa_pss_rsae_1_3, [parallel], all_version_tests() ++ rsa_tests() ++ tls_1_3_tests() ++ tls_1_3_rsa_tests()},
+ {rsa_pss_rsae_1_3, [parallel], all_version_tests() ++ rsa_tests() ++ tls_1_3_tests() ++
+ tls_1_3_rsa_tests()},
{rsa_pss_pss, [parallel], all_version_tests()},
- {rsa_pss_pss_1_3, [parallel], all_version_tests() ++ rsa_tests() ++ tls_1_3_tests() ++ tls_1_3_rsa_tests()},
+ {rsa_pss_pss_1_3, [parallel], all_version_tests() ++ rsa_tests() ++ tls_1_3_tests() ++
+ tls_1_3_rsa_tests()},
{ecdsa_1_3, [parallel], all_version_tests() ++ tls_1_3_tests() ++ partial_chain_with_ecdsa() ++
[signature_algorithms_bad_curve_secp256r1,
signature_algorithms_bad_curve_secp384r1,
signature_algorithms_bad_curve_secp521r1]},
{eddsa, [parallel], all_version_tests() ++ tls_1_3_tests()},
- {mldsa, [parallel], all_version_tests() ++ tls_1_3_tests()}
+ {mldsa, [parallel], all_version_tests() ++ tls_1_3_tests()},
+ {slhdsa_sha2, [parallel], all_version_tests() ++ tls_1_3_tests()},
+ {slhdsa_shake, [parallel], all_version_tests() ++ tls_1_3_tests()}
].
ssl_protocol_groups() ->
@@ -210,7 +215,9 @@ tls_1_3_protocol_groups() ->
{group, eddsa},
{group, rsa_pss_rsae_1_3},
{group, rsa_pss_pss_1_3},
- {group, mldsa}
+ {group, mldsa},
+ {group, slhdsa_sha2},
+ {group, slhdsa_shake}
].
tls_1_3_tests() ->
@@ -322,8 +329,12 @@ init_per_group(GroupName, Config) ->
do_init_per_group(openssl_client, Config) ->
[{client_type, openssl}, {server_type, erlang} | Config];
-do_init_per_group(Group, Config) when Group == mldsa ->
+do_init_per_group(mldsa, Config) ->
ssl_cert_tests:mldsa_config(Config);
+do_init_per_group(slhdsa_sha2, Config) ->
+ ssl_cert_tests:slh_dsa_sha2_config(Config);
+do_init_per_group(slhdsa_shake, Config) ->
+ ssl_cert_tests:slh_dsa_shake_config(Config);
do_init_per_group(Group, Config) when Group == rsa;
Group == rsa_1_3 ->
ssl_cert_tests:rsa_config(Config);
@@ -367,15 +378,18 @@ end_per_testcase(_TestCase, Config) ->
init_ecdsa_opts(Config0, Curve) ->
Version = ssl_test_lib:n_version(proplists:get_value(version, Config0)),
PKAlg = crypto:supports(public_keys),
- case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg) orelse lists:member(dh, PKAlg)) of
+ case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg)
+ orelse lists:member(dh, PKAlg)) of
true ->
Config = ssl_test_lib:make_rsa_ecdsa_cert(Config0, Curve),
COpts = ssl_test_lib:ssl_options(client_ecdsa_verify_opts, Config),
SOpts = ssl_test_lib:ssl_options(server_ecdsa_opts, Config),
[{cert_key_alg, ecdsa} |
lists:delete(cert_key_alg,
- [{client_cert_opts, fun() -> ssl_test_lib:sig_algs(ecdsa, Version) ++ COpts end},
- {server_cert_opts, fun() -> ssl_test_lib:sig_algs(ecdsa, Version) ++ SOpts end} |
+ [{client_cert_opts, fun() -> ssl_test_lib:sig_algs(ecdsa, Version) ++
+ COpts end},
+ {server_cert_opts, fun() -> ssl_test_lib:sig_algs(ecdsa, Version) ++
+ SOpts end} |
lists:delete(server_cert_opts,
lists:delete(client_cert_opts, Config))]
)];
@@ -455,7 +469,9 @@ missing_root_cert_no_auth(Config) when is_list(Config) ->
missing_root_cert_auth() ->
[{doc,"Must have ROOT certs to be able to verify verify peer"}].
missing_root_cert_auth(Config) when is_list(Config) ->
- ServerOpts = proplists:delete(cacertfile, ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)),
+ ServerOpts =
+ proplists:delete(cacertfile,
+ ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)),
{ClientNode, ServerNode, _} = ssl_test_lib:run_where(Config),
Version = ssl_test_lib:n_version(proplists:get_value(version, Config)),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
@@ -466,15 +482,17 @@ missing_root_cert_auth(Config) when is_list(Config) ->
Error = {error, {options, incompatible,
[{verify,verify_peer},{cacerts,undefined}]}},
ssl_test_lib:check_result(Server, Error),
-
- ClientOpts = proplists:delete(cacertfile, ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)),
+
+ ClientOpts =
+ proplists:delete(cacertfile,
+ ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, 0},
{from, self()},
{options, [{verify, verify_peer}
| ClientOpts]}]),
ssl_test_lib:check_result(Client, Error).
-
+
%%--------------------------------------------------------------------
missing_root_cert_auth_user_verify_fun_accept() ->
[{doc, "Test that the client succeeds if the ROOT CA is unknown in verify_peer mode"
@@ -558,17 +576,20 @@ incomplete_chain_auth(Config) when is_list(Config) ->
Group = proplists:get_value(name, Prop),
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(Group),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain, DefaultCertConf},
- {client_chain, DefaultCertConf}]),
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain, DefaultCertConf},
+ {client_chain, DefaultCertConf}]),
[ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerOpts0),
ClientCas = proplists:get_value(cacerts, ClientOpts0),
- ClientOpts = ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
- {cacerts, ServerCas ++ ClientCas} |
- proplists:delete(cacerts, ClientOpts0)], Config),
- ServerOpts = ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer},
- {cacerts, [ServerRoot]} |
- proplists:delete(cacerts, ServerOpts0)], Config),
+ ClientOpts =
+ ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
+ {cacerts, ServerCas ++ ClientCas} |
+ proplists:delete(cacerts, ClientOpts0)], Config),
+ ServerOpts =
+ ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer},
+ {cacerts, [ServerRoot]} |
+ proplists:delete(cacerts, ServerOpts0)], Config),
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -582,18 +603,21 @@ no_chain_client_auth(Config) when is_list(Config) ->
Group = proplists:get_value(name, Prop),
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(Group),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain, DefaultCertConf},
- {client_chain, DefaultCertConf}]),
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain, DefaultCertConf},
+ {client_chain, DefaultCertConf}]),
ServerCas = proplists:get_value(cacerts, ServerOpts0),
[ClientRoot| _] = ClientCas = proplists:get_value(cacerts, ClientOpts0),
- ClientOpts = ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
- {cacerts, [ClientRoot]} |
- proplists:delete(cacerts, ClientOpts0)], Config),
- ServerOpts = ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer},
- {fail_if_no_peer_cert, true},
- {cacerts, ClientCas ++ ServerCas} |
- proplists:delete(cacerts, ServerOpts0)], Config),
+ ClientOpts =
+ ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
+ {cacerts, [ClientRoot]} |
+ proplists:delete(cacerts, ClientOpts0)], Config),
+ ServerOpts =
+ ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer},
+ {fail_if_no_peer_cert, true},
+ {cacerts, ClientCas ++ ServerCas} |
+ proplists:delete(cacerts, ServerOpts0)], Config),
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -610,7 +634,8 @@ verify_fun_always_run_client(Config) when is_list(Config) ->
{from, self()},
{mfa, {ssl_test_lib,
no_result, []}},
- {options, no_reuse(ssl_test_lib:n_version(Version)) ++ ServerOpts}]),
+ {options, no_reuse(ssl_test_lib:n_version(Version))
+ ++ ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
%% If user verify fun is called correctly we fail the connection.
@@ -674,9 +699,10 @@ verify_fun_always_run_server(Config) when is_list(Config) ->
{mfa, {ssl_test_lib,
no_result, []}},
{options,
- no_reuse(ssl_test_lib:n_version(Version)) ++ [{verify, verify_peer},
- {verify_fun, FunAndState} |
- ServerOpts]}]),
+ no_reuse(ssl_test_lib:n_version(Version)) ++
+ [{verify, verify_peer},
+ {verify_fun, FunAndState} |
+ ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
@@ -685,7 +711,7 @@ verify_fun_always_run_server(Config) when is_list(Config) ->
{mfa, {ssl_test_lib,
no_result, []}},
{options, ClientOpts}]),
-
+
ssl_test_lib:check_client_alert(Server, Client, handshake_failure).
%%--------------------------------------------------------------------
@@ -710,20 +736,22 @@ critical_extension_auth(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain,
- [[],[],[{extensions, Ext}]]},
- {client_chain, DefaultCertConf}]),
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[],[],[{extensions, Ext}]]},
+ {client_chain, DefaultCertConf}]),
ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config),
-
+
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Version = proplists:get_value(version, Config),
Server = ssl_test_lib:start_server_error(
[{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, no_reuse(ssl_test_lib:n_version(Version)) ++ [{verify, verify_none} | ServerOpts]}]),
+ {options, no_reuse(ssl_test_lib:n_version(Version)) ++
+ [{verify, verify_none} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error(
[{node, ClientNode}, {port, Port},
@@ -742,20 +770,22 @@ critical_extension_client_auth(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_cert_chain_conf(),
Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{client_chain,
- [[],[],[{extensions, Ext}]]},
- {server_chain, DefaultCertConf}]),
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{client_chain,
+ [[],[],[{extensions, Ext}]]},
+ {server_chain, DefaultCertConf}]),
ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config),
-
+
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Version = proplists:get_value(version, Config),
Server = ssl_test_lib:start_server_error(
[{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, no_reuse(ssl_test_lib:n_version(Version)) ++ [{verify, verify_peer} | ServerOpts]}]),
+ {options, no_reuse(ssl_test_lib:n_version(Version)) ++
+ [{verify, verify_peer} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error(
[{node, ClientNode}, {port, Port},
@@ -765,7 +795,7 @@ critical_extension_client_auth(Config) when is_list(Config) ->
{options, [{verify, verify_none} | ClientOpts]}]),
%% This certificate has a critical extension that we don't
- %% understand. Therefore, verification should fail.
+ %% understand. Therefore, verification should fail.
ssl_test_lib:check_server_alert(Server, Client, unsupported_certificate).
%%--------------------------------------------------------------------
@@ -777,13 +807,16 @@ critical_extension_no_auth(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain,
- [[],[], [{extensions, Ext}]]},
- {client_chain, DefaultCertConf}]),
- ClientOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
- ServerOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
-
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[],[], [{extensions, Ext}]]},
+ {client_chain, DefaultCertConf}]),
+ ClientOpts =
+ [{verify, verify_none} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ ServerOpts =
+ [{verify, verify_none} | ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
+
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
@@ -791,7 +824,7 @@ critical_extension_no_auth(Config) when is_list(Config) ->
extended_key_usage_auth() ->
[{doc,"Test cert that has a critical extended_key_usage extension in server cert"}].
-extended_key_usage_auth(Config) when is_list(Config) ->
+extended_key_usage_auth(Config) when is_list(Config) ->
Prop = proplists:get_value(tc_group_properties, Config),
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
Ext = x509_test:extensions([{?'id-ce-extKeyUsage',
@@ -821,10 +854,11 @@ extended_key_usage_client_auth(Config) when is_list(Config) ->
{server_chain, [[],[],[{extensions, ServerExt}]]}]),
positive_extended_keyusage(ClientOpts, ServerOpts, Config).
-
+
%%--------------------------------------------------------------------
extended_key_usage_mixup_server() ->
- [{doc,"Test cert extended_key_usage extension is always verified by having server use client extension"}].
+ [{doc,"Test cert extended_key_usage extension is always verified by having server use "
+ "client extension"}].
extended_key_usage_mixup_server(Config) when is_list(Config) ->
ClientExt = x509_test:extensions([{?'id-ce-extKeyUsage',
@@ -838,14 +872,14 @@ extended_key_usage_mixup_server(Config) when is_list(Config) ->
ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
[{client_chain, [[],[],[{extensions, ClientExt}]]},
{server_chain, [[],[],[{extensions, ClientExt}]]}]),
-
negative_extended_keyusage(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
extended_key_usage_mixup_client() ->
- [{doc,"Test cert extended_key_usage extension is always verified by having client use server extension"}].
+ [{doc,"Test cert extended_key_usage extension is always verified by having client use "
+ "server extension"}].
extended_key_usage_mixup_client(Config) when is_list(Config) ->
ServerExt = x509_test:extensions([{?'id-ce-extKeyUsage',
@@ -869,7 +903,6 @@ extended_key_usage_ca(Config) when is_list(Config) ->
[?'id-kp-clientAuth'], true}]),
CAExt = x509_test:extensions([{?'id-ce-keyUsage',
[keyCertSign, digitalSignature], true}]),
-
#{client_config := ClientOpts0,
server_config := ServerOpts0} =
ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
@@ -952,28 +985,30 @@ cert_expired(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
{Year, Month, Day} = date(),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain,
- [[],
- [{validity, {{Year-2, Month, Day},
- {Year-1, Month, Day}}}],
- []
- ]},
- {client_chain, DefaultCertConf}]),
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[],
+ [{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ []
+ ]},
+ {client_chain, DefaultCertConf}]),
ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config),
-
+
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Version = proplists:get_value(version, Config),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
- {options, no_reuse(ssl_test_lib:n_version(Version)) ++ ServerOpts}]),
+ {options, no_reuse(ssl_test_lib:n_version(Version))
+ ++ ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {options, [{verify, verify_peer} | ClientOpts]}]),
-
+ {options, [{verify, verify_peer} | ClientOpts]}]),
+
ssl_test_lib:check_client_alert(Server, Client, certificate_expired).
%%--------------------------------------------------------------------
@@ -983,15 +1018,15 @@ no_auth_key_identifier_ext() ->
no_auth_key_identifier_ext(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_cert_chain_conf(),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} =
+ server_config := ServerOpts0} =
ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
[{client_chain, DefaultCertConf},
{server_chain, DefaultCertConf}]),
ClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
ServerOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
-
+
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
-
+
%%--------------------------------------------------------------------
no_auth_key_identifier_ext_keyEncipherment() ->
[{doc, "Test cert with keyEncipherment key_usage an no"
@@ -1001,15 +1036,17 @@ no_auth_key_identifier_ext_keyEncipherment(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_cert_chain_conf(),
ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} =
+ server_config := ServerOpts0} =
ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{client_chain,
+ [{client_chain,
[[],[],[{extensions, ClientExt}]]},
{server_chain, DefaultCertConf}
]),
- ClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
- ServerOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
-
+ ClientOpts =
+ [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ ServerOpts =
+ [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
+
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -1020,18 +1057,19 @@ key_auth_ext_sign_only(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_cert_chain_conf(),
ClientExt = x509_test:extensions([{key_usage, [digitalSignature]}]),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} =
+ server_config := ServerOpts0} =
ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{client_chain,
+ [{client_chain,
[[],[],[{extensions, ClientExt}]]},
{server_chain, DefaultCertConf}
]),
Version = proplists:get_value(version, Config),
- ClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
- ServerOpts = [{verify, verify_peer}, {ciphers,
- ssl_test_lib:rsa_non_signed_suites(ssl_test_lib:n_version(Version))}
+ ClientOpts =
+ [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ ServerOpts = [{verify, verify_peer},
+ {ciphers, ssl_test_lib:rsa_non_signed_suites(ssl_test_lib:n_version(Version))}
| ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
-
+
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -1039,14 +1077,18 @@ cert_auth_in_first_ca() ->
[{doc,"Test cert auth will be available in first ca in chain, make it happen by only having one"}].
cert_auth_in_first_ca(Config) when is_list(Config) ->
#{} =
- public_key:pkix_test_data(#{server_chain => #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
- intermediates => [[]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(5)}]},
- client_chain => #{root => [{key, ssl_test_lib:hardcode_rsa_key(3)}],
- intermediates => [[]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]}}),
- ClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
- ServerOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates => [[]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(5)}]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(3)}],
+ intermediates => [[]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]}}),
+ ClientOpts =
+ [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
+ ServerOpts =
+ [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
@@ -1058,24 +1100,32 @@ longer_chain() ->
longer_chain(Config) when is_list(Config) ->
#{server_config := ServerOpts0,
client_config := ClientOpts0} =
- public_key:pkix_test_data(#{server_chain => #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
- intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}],
- [{key, ssl_test_lib:hardcode_rsa_key(3)}],
- [{key, ssl_test_lib:hardcode_rsa_key(4)}]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(5)}]},
- client_chain => #{root => [{key, ssl_test_lib:hardcode_rsa_key(3)}],
- intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
- peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]}}),
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(1)}],
+ intermediates =>
+ [[{key, ssl_test_lib:hardcode_rsa_key(2)}],
+ [{key, ssl_test_lib:hardcode_rsa_key(3)}],
+ [{key, ssl_test_lib:hardcode_rsa_key(4)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(5)}]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(3)}],
+ intermediates =>
+ [[{key, ssl_test_lib:hardcode_rsa_key(2)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(1)}]}}),
[ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerOpts0),
ClientCas = proplists:get_value(cacerts, ClientOpts0),
Version = ssl_test_lib:n_version(proplists:get_value(version, Config)),
-
- ServerOpts = ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer}, {cacerts, [ServerRoot]} |
- proplists:delete(cacerts, ServerOpts0)] ++ ssl_test_lib:sig_algs(rsa, Version), Config),
- ClientOpts = ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
- {depth, 5},
- {cacerts, ServerCas ++ ClientCas} |
- proplists:delete(cacerts, ClientOpts0)]++ ssl_test_lib:sig_algs(rsa, Version) , Config),
+
+ ServerOpts =
+ ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer}, {cacerts, [ServerRoot]} |
+ proplists:delete(cacerts, ServerOpts0)] ++
+ ssl_test_lib:sig_algs(rsa, Version), Config),
+ ClientOpts =
+ ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer},
+ {depth, 5},
+ {cacerts, ServerCas ++ ClientCas} |
+ proplists:delete(cacerts, ClientOpts0)]++
+ ssl_test_lib:sig_algs(rsa, Version) , Config),
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
cross_signed_chain() ->
@@ -1092,14 +1142,16 @@ cross_signed_chain(Config)
public_key:pkix_test_data(#{server_chain => #{root => [{key, Key1}],
peer => [{key, Key5}]},
client_chain => #{root => [{key, Key3}],
- intermediates => [[{key, Key2}], [{key, Key3}]],
+ intermediates =>
+ [[{key, Key2}], [{key, Key3}]],
peer => [{key, Key1}]}}),
#{client_config := ClientOptsNew} =
public_key:pkix_test_data(#{server_chain => #{root => [{key, Key1}],
peer => [{key, Key5}]},
client_chain => #{root => [{key, Key4}],
- intermediates => [[{key, Key2}], [{key, Key1}]],
+ intermediates =>
+ [[{key, Key2}], [{key, Key1}]],
peer => [{key, Key1}]}}),
ServerCas0 = proplists:get_value(cacerts, ServerOpts0),
@@ -1110,29 +1162,41 @@ cross_signed_chain(Config)
{[_Peer,CI1New,CI2New,CRNew], CRNew} = chain_and_root(ClientOptsNew),
ServerCas = [CRNew|ServerCas0 -- [CROld]],
- ServerOpts = ssl_test_lib:ssl_options(extra_server, [{verify, verify_peer} |
- lists:keyreplace(cacerts, 1, ServerOpts0, {cacerts, ServerCas})]
+ ServerOpts = ssl_test_lib:ssl_options(extra_server,
+ [{verify, verify_peer} |
+ lists:keyreplace(cacerts, 1, ServerOpts0,
+ {cacerts, ServerCas})]
++ ssl_test_lib:sig_algs(rsa, Version),
Config),
- ClientOpts = ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer} |
- lists:keyreplace(cacerts, 1,
- lists:keyreplace(cert, 1, ClientOpts0,
- {cert, [Peer,CI1New,CI2New,CI1,CI2,CRNew,CROld]}),
- {cacerts, ClientCas0})] ++ ssl_test_lib:sig_algs(rsa, Version),
+ ClientOpts =
+ ssl_test_lib:ssl_options(extra_client,
+ [{verify, verify_peer} |
+ lists:keyreplace(cacerts, 1,
+ lists:keyreplace(cert, 1, ClientOpts0,
+ {cert, [Peer,CI1New,CI2New,
+ CI1,CI2,CRNew,CROld]}),
+ {cacerts, ClientCas0})] ++
+ ssl_test_lib:sig_algs(rsa, Version),
Config),
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config),
- ClientOpts2 = ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer} |
- lists:keyreplace(cacerts, 1,
- lists:keyreplace(cert, 1, ClientOpts0,
- {cert, [Peer,CI1,CI1New,CI2,CI2New,CROld,CRNew]}),
- {cacerts, ClientCas0})] ++ ssl_test_lib:sig_algs(rsa, Version),
+ ClientOpts2 =
+ ssl_test_lib:ssl_options(extra_client,
+ [{verify, verify_peer} |
+ lists:keyreplace(cacerts, 1,
+ lists:keyreplace(cert, 1, ClientOpts0,
+ {cert,
+ [Peer,CI1,CI1New,
+ CI2,CI2New,CROld,CRNew]}),
+ {cacerts, ClientCas0})] ++
+ ssl_test_lib:sig_algs(rsa, Version),
Config),
ssl_test_lib:basic_test(ClientOpts2, ServerOpts, Config),
ok.
expired_root_with_cross_signed_root() ->
- [{doc,"Test that we can verify a chain with an expired Root Cert if there is an alternative chain with"
- " a cross signed Root CA further down the chain that is however not present in the sent chain"}].
+ [{doc,"Test that we can verify a chain with an expired Root Cert if there is an alternative "
+ "chain with a cross signed Root CA further down the chain that is however not present in "
+ "the sent chain"}].
expired_root_with_cross_signed_root(Config) when is_list(Config) ->
Key1 = ssl_test_lib:hardcode_rsa_key(1),
@@ -1144,12 +1208,15 @@ expired_root_with_cross_signed_root(Config) when is_list(Config) ->
{Year, Month, Day} = date(),
%% Create expired ROOT
- #{cert := Root} = SRoot = public_key:pkix_test_root_cert("OTP test server ROOT", [{key, Key1},
- {validity, {{Year-2, Month, Day},
- {Year-1, Month, Day}}}]),
+ #{cert := Root} = SRoot =
+ public_key:pkix_test_root_cert("OTP test server ROOT",
+ [{key, Key1},
+ {validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}]),
#{server_config := ServerOpts0, client_config := ClientOpts0} =
public_key:pkix_test_data(#{server_chain => #{root => SRoot,
- intermediates => [[{key, Key2}], [{key, Key3}]],
+ intermediates =>
+ [[{key, Key2}], [{key, Key3}]],
peer => [{key, Key4}]},
client_chain => #{root => [{key, Key5}],
peer => [{key, Key6}]}}),
@@ -1161,8 +1228,9 @@ expired_root_with_cross_signed_root(Config) when is_list(Config) ->
SCerts = proplists:get_value(cacerts, ServerOpts),
{ok, ExtractedCAs} = ssl_pkix_db:extract_trusted_certs({der, SCerts}),
- {ok, Root, [_Peer, CA1, CA2, Root]} = ssl_certificate:certificate_chain(SCert, ets:new(foo, []),
- ExtractedCAs, [], encoded),
+ {ok, Root, [_Peer, CA1, CA2, Root]} =
+ ssl_certificate:certificate_chain(SCert, ets:new(foo, []),
+ ExtractedCAs, [], encoded),
OTPCA1 = public_key:pkix_decode_cert(CA1, otp),
OTPCA2 = public_key:pkix_decode_cert(CA2, otp),
@@ -1174,19 +1242,24 @@ expired_root_with_cross_signed_root(Config) when is_list(Config) ->
SubjectPublicKeyInfo = TBS2#'OTPTBSCertificate'.subjectPublicKeyInfo,
- AltCrossRoot = public_key:pkix_sign(TBS1#'OTPTBSCertificate'{subject = Issuer,
- subjectPublicKeyInfo = SubjectPublicKeyInfo}, Key2),
+ AltCrossRoot =
+ public_key:pkix_sign(TBS1#'OTPTBSCertificate'{subject = Issuer,
+ subjectPublicKeyInfo = SubjectPublicKeyInfo},
+ Key2),
ClientCas0 = proplists:get_value(cacerts, ClientOpts),
%% Only expired ROOT present
- ssl_test_lib:basic_alert([{verify, verify_peer} | ClientOpts], ServerOpts, Config, certificate_expired),
+ ssl_test_lib:basic_alert([{verify, verify_peer} | ClientOpts], ServerOpts, Config,
+ certificate_expired),
%% Only CROSS ROOT present
ssl_test_lib:basic_test([{verify, verify_peer},
- {cacerts, [AltCrossRoot]} | proplists:delete(cacerts, ClientOpts)], ServerOpts, Config),
+ {cacerts, [AltCrossRoot]} | proplists:delete(cacerts, ClientOpts)],
+ ServerOpts, Config),
%% Both expired ROOT and CROSS ROOT present
ssl_test_lib:basic_test([{verify, verify_peer},
- {cacerts, [AltCrossRoot | ClientCas0]} | proplists:delete(cacerts, ClientOpts)],
+ {cacerts, [AltCrossRoot | ClientCas0]} |
+ proplists:delete(cacerts, ClientOpts)],
ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -1197,8 +1270,8 @@ hello_retry_request() ->
"is not supported"}].
hello_retry_request(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups, [x448, x25519]}|ServerOpts0],
ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
@@ -1209,8 +1282,8 @@ custom_groups() ->
[{doc,"Test that ssl server can select a common group for key-exchange"}].
custom_groups(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
%% Set versions
ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
@@ -1224,8 +1297,8 @@ mlkem_groups() ->
[{doc,"Test that ssl server can select a common mlkem group for key-exchange"}].
mlkem_groups(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
mlkem_kex(mlkem512, ClientOpts0, ServerOpts0, Config),
mlkem_kex(mlkem768, ClientOpts0, ServerOpts0, Config),
@@ -1235,8 +1308,8 @@ mlkem_hybrid_groups() ->
[{doc,"Test that ssl server can select a common mlkem-hybrid group for key-exchange"}].
mlkem_hybrid_groups(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
mlkem_kex(x25519mlkem768, ClientOpts0, ServerOpts0, Config),
mlkem_kex(secp256r1mlkem768, ClientOpts0, ServerOpts0, Config),
@@ -1278,7 +1351,8 @@ unsupported_sign_algo_cert_client_auth(Config) ->
%%--------------------------------------------------------------------
unsupported_sign_algo_client_auth() ->
- [{doc,"TLS 1.3 (backported to TLS-1.2): Test client authentication with unsupported signature_algorithm"}].
+ [{doc,"TLS 1.3 (backported to TLS-1.2): Test client authentication with unsupported "
+ "signature_algorithm"}].
unsupported_sign_algo_client_auth(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
@@ -1293,8 +1367,8 @@ hello_retry_client_auth() ->
[{doc, "TLS 1.3 (HelloRetryRequest): Test client authentication."}].
hello_retry_client_auth(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
ServerOpts1 = [{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups, [x448, x25519]}|ServerOpts0],
ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
@@ -1305,16 +1379,16 @@ hello_retry_client_auth(Config) ->
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
hello_retry_client_auth_empty_cert_accepted() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty "
+ [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty "
"certificate and fail_if_no_peer_cert is set to true."}].
hello_retry_client_auth_empty_cert_accepted(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
%% Delete Client Cert and Key
ClientOpts1 = proplists:delete(certfile, ClientOpts0),
ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
%% Set versions
ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{verify, verify_peer},
@@ -1329,12 +1403,13 @@ hello_retry_client_auth_empty_cert_rejected() ->
"sends an empty certificate and fail_if_no_peer_cert is set to true."}].
hello_retry_client_auth_empty_cert_rejected(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
%% Delete Client Cert and Key
+
ClientOpts1 = proplists:delete(certfile, ClientOpts0),
ClientOpts2 = proplists:delete(keyfile, ClientOpts1),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
%% Set versions
ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{verify, verify_peer},
@@ -1342,7 +1417,7 @@ hello_retry_client_auth_empty_cert_rejected(Config) ->
{supported_groups, [x448, x25519]}|ServerOpts0],
ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']},
{supported_groups, [secp256r1, x25519]}|ClientOpts2],
-
+
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required).
%%--------------------------------------------------------------------
@@ -1399,8 +1474,8 @@ signature_algorithms_bad_curve_secp521r1(Config) ->
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, insufficient_security).
%%--------------------------------------------------------------------
-basic_rsa_1024() ->
- [{doc, "TLS 1.3 (Basic): Test if connection can be established using 1024 bits RSA keys in certificates."}].
+basic_rsa_1024() -> [{doc, "TLS 1.3 (Basic): Test if connection can be "
+ "established using 1024 bits RSA keys in certificates."}].
basic_rsa_1024(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_1024_opts, Config),
@@ -1413,13 +1488,14 @@ basic_rsa_1024(Config) ->
%%--------------------------------------------------------------------
server_certificate_authorities_disabled() ->
- [{doc,"TLS 1.3: Disabling certificate_authorities extension on the server when verify_peer is set to true"
- " allows the client to send a chain that could be verifiable by the server but that would not adhere to"
- " the certificate_authorities extension as it is not part of the regular trusted certificate set"}].
+ [{doc,"TLS 1.3: Disabling certificate_authorities extension on the server when verify_peer is "
+ " set to true allows the client to send a chain that could be verifiable by the server but "
+ "that would not adhere to the certificate_authorities extension as it is not part of the "
+ "regular trusted certificate set"}].
server_certificate_authorities_disabled(Config) ->
- ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
- ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
% Strip out the ClientRoot to simulate cases where the they are manually managed and
% not expected to be included in certificate requests during mutual authentication.
@@ -1430,10 +1506,13 @@ server_certificate_authorities_disabled(Config) ->
{unknown, UserState};
(_, valid, UserState) ->
{valid, UserState};
- % Because this is a manually managed setup, we also need to manually verify
- % an unknown_ca (ClientCert) as expected. Typically you would have custom logic
- % here to decide if you know the cert (like looking up pinned values in a DB)
- % but for testing purposes, we'll allow everything
+ % Because this is a manually managed setup, we
+ % also need to manually verify an unknown_ca
+ % (ClientCert) as expected. Typically you would
+ % have custom logic here to decide if you know
+ % the cert (like looking up pinned values in a
+ % DB) but for testing purposes, we'll allow
+ % everything
(_, {bad_cert, unknown_ca}, UserState) ->
{valid, UserState};
(_, valid_peer, UserState) ->
@@ -1449,16 +1528,20 @@ server_certificate_authorities_disabled(Config) ->
%%--------------------------------------------------------------------
legacy_server_certificate_authorities_disabled() ->
- [{doc,"Test that code pre TLS-1.3 can send an empty list for certificate authorities in the certificate request"
- "will be run and not fail, black box verification is not possible without strict legacy client, but code coverage will show that right thing happens"}].
+ [{doc,"Test that code pre TLS-1.3 can send an empty list for certificate authorities in the "
+ "certificate request will be run and not fail, black box verification is not possible "
+ "without strict legacy client, but code coverage will show that right thing happens"}].
legacy_server_certificate_authorities_disabled(Config) ->
Version = proplists:get_value(version,Config),
ClientOpts = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_cert_opts, Config),
- ssl_test_lib:basic_test([{versions, [Version]} | ClientOpts], [{versions, [Version]}, {verify, verify_peer},
- {fail_if_no_peer_cert, true},
- {certificate_authorities, false} | ServerOpts], Config).
+ ssl_test_lib:basic_test([{versions, [Version]} | ClientOpts],
+ [{versions, [Version]},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, true},
+ {certificate_authorities, false} |
+ ServerOpts], Config).
%%--------------------------------------------------------------------
%% Internal functions -----------------------------------------------
@@ -1479,8 +1562,10 @@ no_reuse(_) ->
chain_and_root(Config) ->
OwnCert = proplists:get_value(cert, Config),
- {ok, ExtractedCAs} = ssl_pkix_db:extract_trusted_certs({der, proplists:get_value(cacerts, Config)}),
- {ok, Root, Chain} = ssl_certificate:certificate_chain(OwnCert, ets:new(foo, []), ExtractedCAs, [], encoded),
+ {ok, ExtractedCAs} =
+ ssl_pkix_db:extract_trusted_certs({der, proplists:get_value(cacerts, Config)}),
+ {ok, Root, Chain} =
+ ssl_certificate:certificate_chain(OwnCert, ets:new(foo, []), ExtractedCAs, [], encoded),
{Chain, Root}.
@@ -1518,7 +1603,8 @@ negative_extended_keyusage(ClientOpts0, ServerOpts0, Config) ->
{mfa, {ssl_test_lib, no_result, []}},
{options, [{verify, verify_peer},
{fail_if_no_peer_cert, true}] ++
- no_reuse(ssl_test_lib:n_version(Version)) ++ ServerOpts
+ no_reuse(ssl_test_lib:n_version(Version)) ++
+ ServerOpts
}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
diff --git a/lib/ssl/test/ssl_cert_tests.erl b/lib/ssl/test/ssl_cert_tests.erl
index 54ee261e2d..b7c7fbd6c1 100644
--- a/lib/ssl/test/ssl_cert_tests.erl
+++ b/lib/ssl/test/ssl_cert_tests.erl
@@ -22,7 +22,6 @@
%%
-module(ssl_cert_tests).
--compile({nowarn_deprecated_function, [{public_key, encrypt_private, 3}]}).
-include("ssl_test_lib.hrl").
-include_lib("public_key/include/public_key.hrl").
@@ -34,7 +33,9 @@
openssl_dsa_config/1,
eddsa_config/1,
ecdsa_config/1,
- openssl_eddsa_config/1]).
+ openssl_eddsa_config/1,
+ slh_dsa_sha2_config/1,
+ slh_dsa_shake_config/1]).
%% Test cases
-export([no_auth/0,
@@ -121,7 +122,6 @@ mldsa_config(Config) ->
{client_config, ClientConf}] =
x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
[{cert_key_alg, {mldsa, [[Keys1], [Keys2], [Keys3]]}},
- {cert_key_alg, mldsa},
{extra_client, ssl_test_lib:sig_algs(mldsa, Version)},
{extra_server, ssl_test_lib:sig_algs(mldsa, Version)} |
lists:delete(cert_key_alg,
@@ -133,6 +133,92 @@ mldsa_config(Config) ->
{skip, "Missing ML-DSA crypto support"}
end.
+slh_dsa_sha2_config(Config) ->
+ PKAlgs = crypto:supports(public_keys),
+ case lists:member(slh_dsa_sha2_256f, PKAlgs)
+ andalso lists:member(slh_dsa_sha2_192f, PKAlgs)
+ andalso lists:member(slh_dsa_sha2_128f, PKAlgs)
+ andalso lists:member(slh_dsa_sha2_256s, PKAlgs)
+ andalso lists:member(slh_dsa_sha2_192s, PKAlgs)
+ andalso lists:member(slh_dsa_sha2_128s, PKAlgs)
+ of
+ true ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ [Keys1, Keys2, Keys3,
+ Keys4, Keys5, Keys6] = slh_dsa_sha2_keys(),
+ Conf = #{server_chain =>
+ #{root => [Keys1],
+ intermediates => [[Keys2]],
+ peer => [Keys3]},
+ client_chain => #{root => [Keys4],
+ intermediates => [[Keys5]],
+ peer => [Keys6]
+ }},
+ GenCertData =
+ public_key:pkix_test_data(Conf),
+ Version = proplists:get_value(version, Config),
+ ClientFileBase = filename:join(PrivDir, "slh_sha2_dsa"),
+ ServerFileBase = filename:join(PrivDir, "slh_sha2_dsa"),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ [{cert_key_alg, {slhdsa, [[Keys3], [Keys2], [Keys1]]}},
+ {extra_client, [{max_handshake_size, 256 * 1024},
+ ssl_test_lib:sig_algs(slhdsa_sha2, Version)]},
+ {extra_server, [{max_handshake_size, 256 * 1024},
+ ssl_test_lib:sig_algs(slhdsa_sha2, Version)]} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, fun() -> ClientConf end},
+ {server_cert_opts, fun() -> ServerConf end} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ false ->
+ {skip, "Missing SLH-DSA SHA2 crypto support"}
+ end.
+
+slh_dsa_shake_config(Config) ->
+ PKAlgs = crypto:supports(public_keys),
+ case lists:member(slh_dsa_shake_256f, PKAlgs)
+ andalso lists:member(slh_dsa_shake_192f, PKAlgs)
+ andalso lists:member(slh_dsa_shake_128f, PKAlgs)
+ andalso lists:member(slh_dsa_shake_256s, PKAlgs)
+ andalso lists:member(slh_dsa_shake_192s, PKAlgs)
+ andalso lists:member(slh_dsa_shake_128s, PKAlgs)
+ of
+ true ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+ [Keys1, Keys2, Keys3,
+ Keys4, Keys5, Keys6] = slh_dsa_shake_keys(),
+ Conf = #{server_chain =>
+ #{root => [Keys1],
+ intermediates => [[Keys2]],
+ peer => [Keys3]},
+ client_chain => #{root => [Keys4],
+ intermediates => [[Keys5]],
+ peer => [Keys6]
+ }},
+ GenCertData =
+ public_key:pkix_test_data(Conf),
+ Version = proplists:get_value(version, Config),
+ ClientFileBase = filename:join(PrivDir, "slh_shake_dsa"),
+ ServerFileBase = filename:join(PrivDir, "slh_shake_dsa"),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ [{cert_key_alg, {slhdsa, [[Keys3], [Keys2], [Keys1]]}},
+ {extra_client, [{max_handshake_size, 256 * 1024},
+ ssl_test_lib:sig_algs(slhdsa_shake, Version)]},
+ {extra_server,[{max_handshake_size, 256 * 1024},
+ ssl_test_lib:sig_algs(slhdsa_shake, Version)]} |
+ lists:delete(cert_key_alg,
+ [{client_cert_opts, fun() -> ClientConf end},
+ {server_cert_opts, fun() -> ServerConf end} |
+ lists:delete(server_cert_opts,
+ lists:delete(client_cert_opts, Config))])];
+ false ->
+ {skip, "Missing SLH-DSA SHAKE crypto support"}
+ end.
+
rsa_config(Config0) ->
Config1 = ssl_test_lib:make_rsa_cert(Config0),
Config = ssl_test_lib:make_rsa_1024_cert(Config1),
@@ -151,7 +237,7 @@ rsa_pss_config(Alg, Config) ->
Supports = crypto:supports(),
RSAOpts = proplists:get_value(rsa_opts, Supports),
Version = ssl_test_lib:n_version(proplists:get_value(version, Config)),
-
+
case lists:member(rsa_pkcs1_pss_padding, RSAOpts)
andalso lists:member(rsa_pss_saltlen, RSAOpts)
andalso lists:member(rsa_mgf1_md, RSAOpts) of
@@ -239,15 +325,18 @@ eddsa_config(Config0) ->
PrivDir = proplists:get_value(priv_dir, Config0),
case lists:member(eddsa, PKAlg) andalso (lists:member(ecdh, PKAlg)) of
true ->
- Conf = public_key:pkix_test_data(#{server_chain => #{root => ssl_test_lib:eddsa_conf(),
- intermediates => [ssl_test_lib:eddsa_conf()],
- peer => ssl_test_lib:eddsa_conf()},
- client_chain => #{root => ssl_test_lib:eddsa_conf(),
- intermediates => [ssl_test_lib:eddsa_conf()],
- peer => ssl_test_lib:eddsa_conf()}}),
+ Conf = public_key:pkix_test_data(#{server_chain =>
+ #{root => ssl_test_lib:eddsa_conf(),
+ intermediates => [ssl_test_lib:eddsa_conf()],
+ peer => ssl_test_lib:eddsa_conf()},
+ client_chain =>
+ #{root => ssl_test_lib:eddsa_conf(),
+ intermediates => [ssl_test_lib:eddsa_conf()],
+ peer => ssl_test_lib:eddsa_conf()}}),
[{server_config, SOpts},
- {client_config, COpts}] = x509_test:gen_pem_config_files(Conf, filename:join(PrivDir, "client_eddsa"),
- filename:join(PrivDir, "server_eddsa")),
+ {client_config, COpts}] =
+ x509_test:gen_pem_config_files(Conf, filename:join(PrivDir, "client_eddsa"),
+ filename:join(PrivDir, "server_eddsa")),
[{cert_key_alg, eddsa} |
lists:delete(cert_key_alg,
@@ -292,17 +381,23 @@ openssl_eddsa_config(Config0)->
(lists:member(ecdh, PKAlg) andalso
lists:member(ecdsa, PKAlg)) of
true ->
- Conf = public_key:pkix_test_data(#{server_chain => #{root => ssl_test_lib:eddsa_conf(),
- intermediates => [ssl_test_lib:eddsa_conf()],
- peer => ssl_test_lib:eddsa_conf()},
- %% OpenSSL does currently not support EDDSA private key files
- client_chain => #{root => ssl_test_lib:ecdsa_conf(),
- intermediates => [ssl_test_lib:ecdsa_conf()],
- peer => ssl_test_lib:ecdsa_conf()}}),
+ Conf =
+ public_key:pkix_test_data(#{server_chain =>
+ #{root => ssl_test_lib:eddsa_conf(),
+ intermediates => [ssl_test_lib:eddsa_conf()],
+ peer => ssl_test_lib:eddsa_conf()},
+ %% OpenSSL does currently not support
+ %% EDDSA private key files
+ client_chain =>
+ #{root => ssl_test_lib:ecdsa_conf(),
+ intermediates => [ssl_test_lib:ecdsa_conf()],
+ peer => ssl_test_lib:ecdsa_conf()}}),
[{server_config, SOpts},
- {client_config, COpts}] = x509_test:gen_pem_config_files(Conf, filename:join(PrivDir,
- "client_ecdsa_missing_eddsa"),
- filename:join(PrivDir, "server_eddsa")),
+ {client_config, COpts}] =
+ x509_test:gen_pem_config_files(Conf,
+ filename:join(PrivDir,
+ "client_ecdsa_missing_eddsa"),
+ filename:join(PrivDir, "server_eddsa")),
[{cert_key_alg, eddsa} |
lists:delete(cert_key_alg,
@@ -323,9 +418,10 @@ no_auth() ->
[{doc,"Test connection without authentication"}].
no_auth(Config) ->
- ClientOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
- ServerOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
-
+ ClientOpts = [{verify, verify_none} |
+ ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
+ ServerOpts = [{verify, verify_none} |
+ ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
auth() ->
@@ -333,14 +429,16 @@ auth() ->
auth(Config) ->
Version = proplists:get_value(version,Config),
- CommonClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
+ CommonClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client,
+ client_cert_opts, Config)],
ClientOpts = case Version of
'tlsv1.3' ->
[{certificate_authorities, true} | CommonClientOpts];
_ ->
CommonClientOpts
end,
- ServerOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
+ ServerOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_server,
+ server_cert_opts, Config)],
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -349,7 +447,8 @@ client_auth_custom_key() ->
client_auth_custom_key(Config) when is_list(Config) ->
Version = proplists:get_value(version,Config),
- CommonClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
+ CommonClientOpts = [{verify, verify_peer} | ssl_test_lib:ssl_options(extra_client,
+ client_cert_opts, Config)],
ClientOpts0 = case Version of
'tlsv1.3' ->
[{certificate_authorities, true} | CommonClientOpts];
@@ -378,9 +477,11 @@ client_auth_empty_cert_accepted() ->
client_auth_empty_cert_accepted(Config) ->
ClientOpts = [{verify, verify_peer} |
- proplists:delete(keyfile,
- proplists:delete(certfile,
- ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)))],
+ proplists:delete(keyfile,
+ proplists:delete(certfile,
+ ssl_test_lib:ssl_options(extra_client,
+ client_cert_opts,
+ Config)))],
ServerOpts0 = ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config),
ServerOpts = [{verify, verify_peer},
{fail_if_no_peer_cert, false} | ServerOpts0],
@@ -396,7 +497,7 @@ client_auth_empty_cert_rejected(Config) ->
%% Delete Client Cert and Key
ClientOpts1 = proplists:delete(certfile, ClientOpts0),
ClientOpts = proplists:delete(keyfile, ClientOpts1),
-
+
Version = proplists:get_value(version,Config),
case Version of
'tlsv1.3' ->
@@ -410,17 +511,19 @@ client_auth_no_suitable_chain() ->
client_auth_no_suitable_chain(Config) when is_list(Config) ->
CRoot = public_key:pkix_test_root_cert("OTP other client test ROOT", []),
- #{client_config := ClientOpts0} = public_key:pkix_test_data(#{server_chain => #{root => [],
- intermediates => [[]],
- peer => []},
- client_chain => #{root => CRoot,
- intermediates => [[]],
- peer => []}}),
- ClientOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ #{client_config := ClientOpts0} =
+ public_key:pkix_test_data(#{server_chain => #{root => [],
+ intermediates => [[]],
+ peer => []},
+ client_chain => #{root => CRoot,
+ intermediates => [[]],
+ peer => []}}),
+ ClientOpts = [{verify, verify_none} |
+ ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
| ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
Version = proplists:get_value(version, Config),
-
+
case Version of
'tlsv1.3' ->
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required);
@@ -437,14 +540,15 @@ client_auth_use_partial_chain(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
{Year, Month, Day} = date(),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain,
- [[{validity, {{Year-2, Month, Day},
- {Year-1, Month, Day}}}],
- [],
- []
- ]},
- {client_chain, DefaultCertConf}]),
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {client_chain, DefaultCertConf}]),
ClientOpts = ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config),
ServerOpts = ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config),
[_, IntermidiateCA, _] = proplists:get_value(cacerts, ServerOpts),
@@ -456,7 +560,8 @@ client_auth_use_partial_chain(Config) when is_list(Config) ->
unknown_ca
end
end,
- ssl_test_lib:basic_test([{verify, verify_peer}, {partial_chain, PartialChain} |ClientOpts], ServerOpts, Config).
+ ssl_test_lib:basic_test([{verify, verify_peer},
+ {partial_chain, PartialChain} |ClientOpts], ServerOpts, Config).
%%--------------------------------------------------------------------
client_auth_do_not_use_partial_chain() ->
@@ -467,21 +572,23 @@ client_auth_do_not_use_partial_chain(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
{Year, Month, Day} = date(),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain,
- [[{validity, {{Year-2, Month, Day},
- {Year-1, Month, Day}}}],
- [],
- []
- ]},
- {client_chain, DefaultCertConf}]),
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {client_chain, DefaultCertConf}]),
PartialChain = fun(_CertChain) ->
unknown_ca
end,
- ClientOpts = [{verify, verify_peer}, {partial_chain, PartialChain} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ ClientOpts = [{verify, verify_peer}, {partial_chain, PartialChain} |
+ ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
ServerOpts = ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config),
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_expired).
-
+
%%--------------------------------------------------------------------
client_auth_partial_chain_fun_fail() ->
[{doc, "If partial_chain fun crashes, treat it as if it returned unkown_ca"}].
@@ -491,23 +598,24 @@ client_auth_partial_chain_fun_fail(Config) when is_list(Config) ->
DefaultCertConf = ssl_test_lib:default_ecc_cert_chain_conf(proplists:get_value(name, Prop)),
{Year, Month, Day} = date(),
#{client_config := ClientOpts0,
- server_config := ServerOpts0} = ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
- [{server_chain,
- [[{validity, {{Year-2, Month, Day},
- {Year-1, Month, Day}}}],
- [],
- []
- ]},
- {client_chain, DefaultCertConf}]),
-
+ server_config := ServerOpts0} =
+ ssl_test_lib:make_cert_chains_der(proplists:get_value(cert_key_alg, Config),
+ [{server_chain,
+ [[{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ [],
+ []
+ ]},
+ {client_chain, DefaultCertConf}]),
PartialChain = fun(_CertChain) ->
error(crash_on_purpose)
end,
- ClientOpts = [{verify, verify_peer}, {partial_chain, PartialChain} | ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
+ ClientOpts = [{verify, verify_peer}, {partial_chain, PartialChain} |
+ ssl_test_lib:ssl_options(extra_client, ClientOpts0, Config)],
ServerOpts = [ssl_test_lib:ssl_options(extra_server, ServerOpts0, Config)],
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_expired).
-
+
%%--------------------------------------------------------------------
client_auth_sni() ->
@@ -517,7 +625,7 @@ client_auth_sni(Config) when is_list(Config) ->
FunAndState = {fun(valid_peer, {bad_cert, unknown_ca}, UserState) ->
{valid_peer, UserState};
- (_,{bad_cert, _} = Reason, _) ->
+ (_,{bad_cert, _} = Reason, _) ->
{fail, Reason};
(_,{extension, _}, UserState) ->
{unknown, UserState};
@@ -529,7 +637,7 @@ client_auth_sni(Config) when is_list(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config),
ClientOpts = [{verify, verify_peer}, {verify_fun, FunAndState
- }, {server_name_indication, "localhost"} | ClientOpts0],
+ }, {server_name_indication, "localhost"} | ClientOpts0],
{ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts0)),
[{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
@@ -546,25 +654,33 @@ client_auth_sni(Config) when is_list(Config) ->
client_auth_seelfsigned_peer() ->
[{doc, "Check that selfsigned peer raises alert"}].
client_auth_seelfsigned_peer(Config) when is_list(Config) ->
- Ext = x509_test:extensions([{key_usage, [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]),
+ Ext = x509_test:extensions([{key_usage,
+ [keyCertSign, cRLSign, digitalSignature, keyAgreement]}]),
#{cert := Cert,
- key := Key} = public_key:pkix_test_root_cert("OTP test server ROOT", [{key, ssl_test_lib:hardcode_rsa_key(6)},
- {extensions, Ext}]),
+ key := Key} = public_key:pkix_test_root_cert("OTP test server ROOT",
+ [{key, ssl_test_lib:hardcode_rsa_key(6)},
+ {extensions, Ext}]),
Version = ssl_test_lib:n_version(proplists:get_value(version, Config)),
DerKey = public_key:der_encode('RSAPrivateKey', Key),
- ssl_test_lib:basic_alert(ssl_test_lib:ssl_options(extra_client, [{verify, verify_peer}, {cacerts , [Cert]}] ++
- ssl_test_lib:sig_algs(rsa, Version), Config),
- ssl_test_lib:ssl_options(extra_server, [{cert, Cert},
- {key, {'RSAPrivateKey', DerKey}}] ++
- ssl_test_lib:sig_algs(rsa, Version), Config),
+ ssl_test_lib:basic_alert(ssl_test_lib:ssl_options(extra_client,
+ [{verify, verify_peer}, {cacerts , [Cert]}] ++
+ ssl_test_lib:sig_algs(rsa, Version),
+ Config),
+ ssl_test_lib:ssl_options(extra_server,
+ [{cert, Cert},
+ {key, {'RSAPrivateKey', DerKey}}] ++
+ ssl_test_lib:sig_algs(rsa, Version),
+ Config),
Config, bad_certificate).
%%--------------------------------------------------------------------
missing_root_cert_no_auth() ->
[{doc,"Test that the client succeeds if the ROOT CA is unknown in verify_none mode"}].
missing_root_cert_no_auth(Config) ->
- ClientOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
- ServerOpts = [{verify, verify_none} | ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
+ ClientOpts = [{verify, verify_none} |
+ ssl_test_lib:ssl_options(extra_client, client_cert_opts, Config)],
+ ServerOpts = [{verify, verify_none} |
+ ssl_test_lib:ssl_options(extra_server, server_cert_opts, Config)],
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
@@ -615,7 +731,7 @@ invalid_signature_server(Config) when is_list(Config) ->
ServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts0)],
ClientOpts = [{verify, verify_peer} | ClientOpts0],
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, unknown_ca).
-
+
%%--------------------------------------------------------------------
%% TLS 1.3 Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
@@ -626,10 +742,11 @@ hello_retry_request() ->
hello_retry_request(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
-
- {ServerOpts, ClientOpts} = group_config(Config,
- [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
- [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]),
+
+ {ServerOpts, ClientOpts} =
+ group_config(Config,
+ [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
+ [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]),
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -640,10 +757,11 @@ custom_groups(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
- {ServerOpts, ClientOpts} = group_config_custom(Config,
- [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
- [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]),
-
+ {ServerOpts, ClientOpts} =
+ group_config_custom(Config,
+ [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0],
+ [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]),
+
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
@@ -667,9 +785,10 @@ test_mlkem(Config, MLKemGroup) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
- {ServerOpts, ClientOpts} = group_config_mlkem(Config,
- [{versions, ['tlsv1.3']} | ServerOpts0],
- [{versions, ['tlsv1.3']} | ClientOpts0], MLKemGroup),
+ {ServerOpts, ClientOpts} =
+ group_config_mlkem(Config,
+ [{versions, ['tlsv1.3']} | ServerOpts0],
+ [{versions, ['tlsv1.3']} | ClientOpts0], MLKemGroup),
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
@@ -713,31 +832,34 @@ hello_retry_client_auth() ->
hello_retry_client_auth(Config) ->
ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
-
- {ServerOpts, ClientOpts} = group_config(Config,
+
+ {ServerOpts, ClientOpts} = group_config(Config,
[{versions, ['tlsv1.2','tlsv1.3']},
{verify, verify_peer},
{fail_if_no_peer_cert, true} | ServerOpts0],
- [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]),
-
+ [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer} | ClientOpts0]),
+
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
hello_retry_client_auth_empty_cert_accepted() ->
- [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty "
+ [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty "
"certificate and fail_if_no_peer_cert is set to false."}].
hello_retry_client_auth_empty_cert_accepted(Config) ->
ClientOpts0 = proplists:delete(keyfile,
- proplists:delete(certfile,
- ssl_test_lib:ssl_options(client_cert_opts, Config))),
+ proplists:delete(certfile,
+ ssl_test_lib:ssl_options(client_cert_opts,
+ Config))),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
- {ServerOpts, ClientOpts} = group_config(Config,
+ {ServerOpts, ClientOpts} = group_config(Config,
[{versions, ['tlsv1.2','tlsv1.3']},
{verify, verify_peer},
{fail_if_no_peer_cert, false} | ServerOpts0],
- [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]),
-
+ [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer} | ClientOpts0]),
+
ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config).
%%--------------------------------------------------------------------
hello_retry_client_auth_empty_cert_rejected() ->
@@ -746,16 +868,18 @@ hello_retry_client_auth_empty_cert_rejected() ->
hello_retry_client_auth_empty_cert_rejected(Config) ->
ClientOpts0 = proplists:delete(keyfile,
- proplists:delete(certfile,
- ssl_test_lib:ssl_options(client_cert_opts, Config))),
+ proplists:delete(certfile,
+ ssl_test_lib:ssl_options(client_cert_opts,
+ Config))),
ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config),
-
- {ServerOpts, ClientOpts} = group_config(Config,
+
+ {ServerOpts, ClientOpts} = group_config(Config,
[{versions, ['tlsv1.2','tlsv1.3']},
{verify, verify_peer},
{fail_if_no_peer_cert, true} | ServerOpts0],
- [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]),
-
+ [{versions, ['tlsv1.2','tlsv1.3']},
+ {verify, verify_peer} | ClientOpts0]),
+
ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required).
%%--------------------------------------------------------------------
@@ -782,7 +906,7 @@ test_ciphers(_, Version) when Version == 'dtlsv1';
lists:member(ssl_cipher_format:suite_map_to_openssl_str(C), OpenSSLCiphers)
end, Ciphers);
test_ciphers(Kex, Version) ->
- Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, Version),
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, Version),
[{key_exchange, Kex}]),
?CT_LOG("Version ~p Testing ~p~n", [Version, Ciphers]),
OpenSSLCiphers = openssl_ciphers(),
@@ -816,6 +940,28 @@ mldsa_key_spec(PubFile, PrivFile) ->
{key, {both, public_key:pem_entry_decode(PubPemEntry),
public_key:pem_entry_decode(PrivPemEntry)}}.
+slh_dsa_sha2_keys()->
+ [slh_dsa_key_spec(public_key:generate_key(slh_dsa_sha2_128f)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_sha2_192f)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_sha2_256f)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_sha2_128s)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_sha2_192s)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_sha2_256s))
+ ].
+
+slh_dsa_shake_keys()->
+ [slh_dsa_key_spec(public_key:generate_key(slh_dsa_shake_128f)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_shake_192f)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_shake_256f)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_shake_128s)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_shake_192s)),
+ slh_dsa_key_spec(public_key:generate_key(slh_dsa_shake_256s))
+ ].
+
+slh_dsa_key_spec({Pub, Priv}) ->
+ {key, {both, Pub, Priv}}.
+
+
group_config_custom(Config, ServerOpts, ClientOpts) ->
case proplists:get_value(client_type, Config) of
erlang ->
@@ -874,6 +1020,11 @@ choose_custom_key(#'RSAPrivateKey'{} = Key, Version)
public_key:sign(Msg, HashAlgo, Key, Options)
end,
{key, #{algorithm => rsa, sign_fun => SFun, encrypt_fun => EFun}};
+choose_custom_key(#'SLH-DSAPrivateKey'{}= Key, _) ->
+ Fun = fun (Msg, _HashAlgo, Options) ->
+ public_key:sign(Msg, none, Key, Options)
+ end,
+ {key, #{algorithm => alg_key(Key), sign_fun => Fun}};
choose_custom_key(Key, _) ->
Fun = fun (Msg, HashAlgo, Options) ->
public_key:sign(Msg, HashAlgo, Key, Options)
@@ -892,4 +1043,6 @@ alg_key(#'ECPrivateKey'{parameters = {namedCurve, CurveOId}}) when CurveOId == ?
alg_key(#'ECPrivateKey'{}) ->
ecdsa;
alg_key(#'ML-DSAPrivateKey'{}) ->
- mldsa.
+ mldsa;
+alg_key(#'SLH-DSAPrivateKey'{}) ->
+ slhdsa.
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 2dfab49032..221a9233d5 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -477,6 +477,22 @@ sig_algs(Alg, {254,_} = Version) ->
sig_algs(Alg, Version) ->
do_sig_algs(Alg, Version).
+do_sig_algs(slhdsa_shake, Version) when ?TLS_GTE(Version, ?TLS_1_3) ->
+ [{signature_algs, [slh_dsa_shake_256s,
+ slh_dsa_shake_256f,
+ slh_dsa_shake_192s,
+ slh_dsa_shake_192f,
+ slh_dsa_shake_128s,
+ slh_dsa_shake_128f
+ ]}];
+do_sig_algs(slhdsa_sha2, Version) when ?TLS_GTE(Version, ?TLS_1_3) ->
+ [{signature_algs, [slh_dsa_sha2_256s,
+ slh_dsa_sha2_256f,
+ slh_dsa_sha2_192s,
+ slh_dsa_sha2_192f,
+ slh_dsa_sha2_128s,
+ slh_dsa_sha2_128f
+ ]}];
do_sig_algs(mldsa, Version) when ?TLS_GTE(Version, ?TLS_1_3) ->
[{signature_algs, [mldsa44, mldsa65, mldsa87]}];
do_sig_algs(rsa_pss_pss, _) ->
@@ -1824,6 +1840,8 @@ chain_spec(_Role, dsa, _) ->
[Digest, {key, hardcode_dsa_key(2)}],
[Digest, {key, hardcode_dsa_key(3)}]];
chain_spec(_, {mldsa, Keys} , _) ->
+ Keys;
+chain_spec(_,{slhdsa, Keys}, _) ->
Keys.
merge_chain_spec([], [], Acc)->
--
2.51.0