aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/test')
-rw-r--r--lib/ssl/test/Makefile9
-rw-r--r--lib/ssl/test/erl_make_certs.erl477
-rw-r--r--lib/ssl/test/make_certs.erl18
-rw-r--r--lib/ssl/test/ssl.spec3
-rw-r--r--lib/ssl/test/ssl_ECC.erl171
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl568
-rw-r--r--lib/ssl/test/ssl_ECC_openssl_SUITE.erl218
-rw-r--r--lib/ssl/test/ssl_alpn_handshake_SUITE.erl66
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl814
-rw-r--r--lib/ssl/test/ssl_bench_SUITE.erl128
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl654
-rw-r--r--lib/ssl/test/ssl_crl_SUITE.erl110
-rw-r--r--lib/ssl/test/ssl_dist_SUITE.erl350
-rw-r--r--lib/ssl/test/ssl_engine_SUITE.erl162
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl15
-rw-r--r--lib/ssl/test/ssl_npn_handshake_SUITE.erl11
-rw-r--r--lib/ssl/test/ssl_npn_hello_SUITE.erl28
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl187
-rw-r--r--lib/ssl/test/ssl_payload_SUITE.erl20
-rw-r--r--lib/ssl/test/ssl_pem_cache_SUITE.erl11
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl4
-rw-r--r--lib/ssl/test/ssl_sni_SUITE.erl240
-rw-r--r--lib/ssl/test/ssl_test_lib.erl1125
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl536
-rw-r--r--lib/ssl/test/ssl_upgrade_SUITE.erl22
-rw-r--r--lib/ssl/test/x509_test.erl108
26 files changed, 3894 insertions, 2161 deletions
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index a2eb4ce449..256c0bb017 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2016. All Rights Reserved.
+# Copyright Ericsson AB 1999-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ MODULES = \
ssl_certificate_verify_SUITE\
ssl_crl_SUITE\
ssl_dist_SUITE \
+ ssl_engine_SUITE\
ssl_handshake_SUITE \
ssl_npn_hello_SUITE \
ssl_npn_handshake_SUITE \
@@ -52,11 +53,13 @@ MODULES = \
ssl_pem_cache_SUITE \
ssl_session_cache_SUITE \
ssl_to_openssl_SUITE \
- ssl_ECC_SUITE \
+ ssl_ECC\
+ ssl_ECC_SUITE \
+ ssl_ECC_openssl_SUITE\
ssl_upgrade_SUITE\
ssl_sni_SUITE \
make_certs\
- erl_make_certs
+ x509_test
ERL_FILES = $(MODULES:%=%.erl)
diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl
deleted file mode 100644
index a6657be995..0000000000
--- a/lib/ssl/test/erl_make_certs.erl
+++ /dev/null
@@ -1,477 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%% Create test certificates
-
--module(erl_make_certs).
--include_lib("public_key/include/public_key.hrl").
-
--export([make_cert/1, gen_rsa/1, verify_signature/3, write_pem/3]).
--compile(export_all).
-
-%%--------------------------------------------------------------------
-%% @doc Create and return a der encoded certificate
-%% Option Default
-%% -------------------------------------------------------
-%% digest sha1
-%% validity {date(), date() + week()}
-%% version 3
-%% subject [] list of the following content
-%% {name, Name}
-%% {email, Email}
-%% {city, City}
-%% {state, State}
-%% {org, Org}
-%% {org_unit, OrgUnit}
-%% {country, Country}
-%% {serial, Serial}
-%% {title, Title}
-%% {dnQualifer, DnQ}
-%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created)
-%% (obs IssuerKey migth be {Key, Password}
-%% key = KeyFile|KeyBin|rsa|dsa|ec Subject PublicKey rsa, dsa or ec generates key
-%%
-%%
-%% (OBS: The generated keys are for testing only)
-%% @spec ([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()}
-%% @end
-%%--------------------------------------------------------------------
-
-make_cert(Opts) ->
- SubjectPrivateKey = get_key(Opts),
- {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts),
- Cert = public_key:pkix_sign(TBSCert, IssuerKey),
- true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok
- {Cert, encode_key(SubjectPrivateKey)}.
-
-%%--------------------------------------------------------------------
-%% @doc Writes pem files in Dir with FileName ++ ".pem" and FileName ++ "_key.pem"
-%% @spec (::string(), ::string(), {Cert,Key}) -> ok
-%% @end
-%%--------------------------------------------------------------------
-write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
- ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
- [{'Certificate', Cert, not_encrypted}]),
- ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
-
-%%--------------------------------------------------------------------
-%% @doc Creates a rsa key (OBS: for testing only)
-%% the size are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_rsa(Size) when is_integer(Size) ->
- Key = gen_rsa2(Size),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Creates a dsa key (OBS: for testing only)
-%% the sizes are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
- Key = gen_dsa2(LSize, NSize),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Creates a ec key (OBS: for testing only)
-%% the sizes are in bytes
-%% @spec (::integer()) -> {::atom(), ::binary(), ::opaque()}
-%% @end
-%%--------------------------------------------------------------------
-gen_ec(Curve) when is_atom(Curve) ->
- Key = gen_ec2(Curve),
- {Key, encode_key(Key)}.
-
-%%--------------------------------------------------------------------
-%% @doc Verifies cert signatures
-%% @spec (::binary(), ::tuple()) -> ::boolean()
-%% @end
-%%--------------------------------------------------------------------
-verify_signature(DerEncodedCert, DerKey, _KeyParams) ->
- Key = decode_key(DerKey),
- case Key of
- #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} ->
- public_key:pkix_verify(DerEncodedCert,
- #'RSAPublicKey'{modulus=Mod, publicExponent=Exp});
- #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} ->
- public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}});
- #'ECPrivateKey'{version = _Version, privateKey = _PrivKey,
- parameters = Params, publicKey = PubKey} ->
- public_key:pkix_verify(DerEncodedCert, {#'ECPoint'{point = PubKey}, Params})
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-get_key(Opts) ->
- case proplists:get_value(key, Opts) of
- undefined -> make_key(rsa, Opts);
- rsa -> make_key(rsa, Opts);
- dsa -> make_key(dsa, Opts);
- ec -> make_key(ec, Opts);
- Key ->
- Password = proplists:get_value(password, Opts, no_passwd),
- decode_key(Key, Password)
- end.
-
-decode_key({Key, Pw}) ->
- decode_key(Key, Pw);
-decode_key(Key) ->
- decode_key(Key, no_passwd).
-
-
-decode_key(#'RSAPublicKey'{} = Key,_) ->
- Key;
-decode_key(#'RSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(#'DSAPrivateKey'{} = Key,_) ->
- Key;
-decode_key(#'ECPrivateKey'{} = Key,_) ->
- Key;
-decode_key(PemEntry = {_,_,_}, Pw) ->
- public_key:pem_entry_decode(PemEntry, Pw);
-decode_key(PemBin, Pw) ->
- [KeyInfo] = public_key:pem_decode(PemBin),
- decode_key(KeyInfo, Pw).
-
-encode_key(Key = #'RSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
- {'RSAPrivateKey', Der, not_encrypted};
-encode_key(Key = #'DSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {'DSAPrivateKey', Der, not_encrypted};
-encode_key(Key = #'ECPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('ECPrivateKey', Key),
- {'ECPrivateKey', Der, not_encrypted}.
-
-make_tbs(SubjectKey, Opts) ->
- Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))),
-
- IssuerProp = proplists:get_value(issuer, Opts, true),
- {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey),
-
- {Algo, Parameters} = sign_algorithm(IssuerKey, Opts),
-
- SignAlgo = #'SignatureAlgorithm'{algorithm = Algo,
- parameters = Parameters},
- Subject = case IssuerProp of
- true -> %% Is a Root Ca
- Issuer;
- _ ->
- subject(proplists:get_value(subject, Opts),false)
- end,
-
- {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1,
- signature = SignAlgo,
- issuer = Issuer,
- validity = validity(Opts),
- subject = Subject,
- subjectPublicKeyInfo = publickey(SubjectKey),
- version = Version,
- extensions = extensions(Opts)
- }, IssuerKey}.
-
-issuer(true, Opts, SubjectKey) ->
- %% Self signed
- {subject(proplists:get_value(subject, Opts), true), SubjectKey};
-issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) ->
- {issuer_der(Issuer), decode_key(IssuerKey)};
-issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) ->
- {ok, [{cert, Cert, _}|_]} = pem_to_der(File),
- {issuer_der(Cert), decode_key(IssuerKey)}.
-
-issuer_der(Issuer) ->
- Decoded = public_key:pkix_decode_cert(Issuer, otp),
- #'OTPCertificate'{tbsCertificate=Tbs} = Decoded,
- #'OTPTBSCertificate'{subject=Subject} = Tbs,
- Subject.
-
-subject(undefined, IsRootCA) ->
- User = if IsRootCA -> "RootCA"; true -> os:getenv("USER", "test_user") end,
- Opts = [{email, User ++ "@erlang.org"},
- {name, User},
- {city, "Stockholm"},
- {country, "SE"},
- {org, "erlang"},
- {org_unit, "testing dep"}],
- subject(Opts);
-subject(Opts, _) ->
- subject(Opts).
-
-subject(SubjectOpts) when is_list(SubjectOpts) ->
- Encode = fun(Opt) ->
- {Type,Value} = subject_enc(Opt),
- [#'AttributeTypeAndValue'{type=Type, value=Value}]
- end,
- {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}.
-
-%% Fill in the blanks
-subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}};
-subject_enc({email, Email}) -> {?'id-emailAddress', Email};
-subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}};
-subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}};
-subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}};
-subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}};
-subject_enc({country, Country}) -> {?'id-at-countryName', Country};
-subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial};
-subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}};
-subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ};
-subject_enc(Other) -> Other.
-
-
-extensions(Opts) ->
- case proplists:get_value(extensions, Opts, []) of
- false ->
- asn1_NOVALUE;
- Exts ->
- lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)])
- end.
-
-default_extensions(Exts) ->
- Def = [{key_usage,undefined},
- {subject_altname, undefined},
- {issuer_altname, undefined},
- {basic_constraints, default},
- {name_constraints, undefined},
- {policy_constraints, undefined},
- {ext_key_usage, undefined},
- {inhibit_any, undefined},
- {auth_key_id, undefined},
- {subject_key_id, undefined},
- {policy_mapping, undefined}],
- Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end,
- Exts ++ lists:foldl(Filter, Def, Exts).
-
-extension({_, undefined}) -> [];
-extension({basic_constraints, Data}) ->
- case Data of
- default ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true},
- critical=true};
- false ->
- [];
- Len when is_integer(Len) ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len},
- critical=true};
- _ ->
- #'Extension'{extnID = ?'id-ce-basicConstraints',
- extnValue = Data}
- end;
-extension({Id, Data, Critical}) ->
- #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
-
-
-publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
- Public = #'RSAPublicKey'{modulus=N, publicExponent=E},
- Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = Public};
-publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y};
-publickey(#'ECPrivateKey'{version = _Version,
- privateKey = _PrivKey,
- parameters = Params,
- publicKey = PubKey}) ->
- Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params},
- #'OTPSubjectPublicKeyInfo'{algorithm = Algo,
- subjectPublicKey = #'ECPoint'{point = PubKey}}.
-
-validity(Opts) ->
- DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1),
- DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7),
- {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}),
- Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end,
- #'Validity'{notBefore={generalTime, Format(DefFrom)},
- notAfter ={generalTime, Format(DefTo)}}.
-
-sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
- Type = case proplists:get_value(digest, Opts, sha1) of
- sha1 -> ?'sha1WithRSAEncryption';
- sha512 -> ?'sha512WithRSAEncryption';
- sha384 -> ?'sha384WithRSAEncryption';
- sha256 -> ?'sha256WithRSAEncryption';
- md5 -> ?'md5WithRSAEncryption';
- md2 -> ?'md2WithRSAEncryption'
- end,
- {Type, 'NULL'};
-sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}};
-sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) ->
- Type = case proplists:get_value(digest, Opts, sha1) of
- sha1 -> ?'ecdsa-with-SHA1';
- sha512 -> ?'ecdsa-with-SHA512';
- sha384 -> ?'ecdsa-with-SHA384';
- sha256 -> ?'ecdsa-with-SHA256'
- end,
- {Type, Parms}.
-
-make_key(rsa, _Opts) ->
- %% (OBS: for testing only)
- gen_rsa2(64);
-make_key(dsa, _Opts) ->
- gen_dsa2(128, 20); %% Bytes i.e. {1024, 160}
-make_key(ec, _Opts) ->
- %% (OBS: for testing only)
- CurveOid = hd(tls_v1:ecc_curves(0)),
- NamedCurve = pubkey_cert_records:namedCurves(CurveOid),
- gen_ec2(NamedCurve).
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% RSA key generation (OBS: for testing only)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
--define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53,
- 47,43,41,37,31,29,23,19,17,13,11,7,5,3]).
-
-gen_rsa2(Size) ->
- P = prime(Size),
- Q = prime(Size),
- N = P*Q,
- Tot = (P - 1) * (Q - 1),
- [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES),
- {D1,D2} = extended_gcd(E, Tot),
- D = erlang:max(D1,D2),
- case D < E of
- true ->
- gen_rsa2(Size);
- false ->
- {Co1,Co2} = extended_gcd(Q, P),
- Co = erlang:max(Co1,Co2),
- #'RSAPrivateKey'{version = 'two-prime',
- modulus = N,
- publicExponent = E,
- privateExponent = D,
- prime1 = P,
- prime2 = Q,
- exponent1 = D rem (P-1),
- exponent2 = D rem (Q-1),
- coefficient = Co
- }
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% DSA key generation (OBS: for testing only)
-%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm
-%% and the fips_186-3.pdf
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-gen_dsa2(LSize, NSize) ->
- Q = prime(NSize), %% Choose N-bit prime Q
- X0 = prime(LSize),
- P0 = prime((LSize div 2) +1),
-
- %% Choose L-bit prime modulus P such that p-1 is a multiple of q.
- case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of
- error ->
- gen_dsa2(LSize, NSize);
- P ->
- G = crypto:mod_pow(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q.
- %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used.
-
- X = prime(20), %% Choose x by some random method, where 0 < x < q.
- Y = crypto:mod_pow(G, X, P), %% Calculate y = g^x mod p.
-
- #'DSAPrivateKey'{version=0, p = P, q = Q,
- g = crypto:bytes_to_integer(G), y = crypto:bytes_to_integer(Y), x = X}
- end.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% EC key generation (OBS: for testing only)
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-gen_ec2(CurveId) ->
- {PubKey, PrivKey} = crypto:generate_key(ecdh, CurveId),
-
- #'ECPrivateKey'{version = 1,
- privateKey = PrivKey,
- parameters = {namedCurve, pubkey_cert_records:namedCurves(CurveId)},
- publicKey = PubKey}.
-
-%% See fips_186-3.pdf
-dsa_search(T, P0, Q, Iter) when Iter > 0 ->
- P = 2*T*Q*P0 + 1,
- case is_prime(P, 50) of
- true -> P;
- false -> dsa_search(T+1, P0, Q, Iter-1)
- end;
-dsa_search(_,_,_,_) ->
- error.
-
-
-%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-prime(ByteSize) ->
- Rand = odd_rand(ByteSize),
- prime_odd(Rand, 0).
-
-prime_odd(Rand, N) ->
- case is_prime(Rand, 50) of
- true ->
- Rand;
- false ->
- prime_odd(Rand+2, N+1)
- end.
-
-%% see http://en.wikipedia.org/wiki/Fermat_primality_test
-is_prime(_, 0) -> true;
-is_prime(Candidate, Test) ->
- CoPrime = odd_rand(10000, Candidate),
- Result = crypto:mod_pow(CoPrime, Candidate, Candidate) ,
- is_prime(CoPrime, crypto:bytes_to_integer(Result), Candidate, Test).
-
-is_prime(CoPrime, CoPrime, Candidate, Test) ->
- is_prime(Candidate, Test-1);
-is_prime(_,_,_,_) ->
- false.
-
-odd_rand(Size) ->
- Min = 1 bsl (Size*8-1),
- Max = (1 bsl (Size*8))-1,
- odd_rand(Min, Max).
-
-odd_rand(Min,Max) ->
- Rand = crypto:rand_uniform(Min,Max),
- case Rand rem 2 of
- 0 ->
- Rand + 1;
- _ ->
- Rand
- end.
-
-extended_gcd(A, B) ->
- case A rem B of
- 0 ->
- {0, 1};
- N ->
- {X, Y} = extended_gcd(B, N),
- {Y, X-Y*(A div B)}
- end.
-
-pem_to_der(File) ->
- {ok, PemBin} = file:read_file(File),
- public_key:pem_decode(PemBin).
-
-der_to_pem(File, Entries) ->
- PemBin = public_key:pem_encode(Entries),
- file:write_file(File, PemBin).
-
diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl
index 009bcd81ad..ecbacc1590 100644
--- a/lib/ssl/test/make_certs.erl
+++ b/lib/ssl/test/make_certs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -172,8 +172,8 @@ revoke(Root, CA, User, C) ->
gencrl(Root, CA, C).
gencrl(Root, CA, C) ->
- %% By default, the CRL is valid for 24 hours from now.
- gencrl(Root, CA, C, 24).
+ %% By default, the CRL is valid for a week from now.
+ gencrl(Root, CA, C, 24*7).
gencrl(Root, CA, C, CrlHours) ->
CACnfFile = filename:join([Root, CA, "ca.cnf"]),
@@ -385,6 +385,7 @@ req_cnf(Root, C) ->
"subjectAltName = email:copy\n"].
ca_cnf(Root, C = #config{issuing_distribution_point = true}) ->
+ Hostname = net_adm:localhost(),
["# Purpose: Configuration for CAs.\n"
"\n"
"ROOTDIR = " ++ Root ++ "\n"
@@ -434,7 +435,7 @@ ca_cnf(Root, C = #config{issuing_distribution_point = true}) ->
"keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
"subjectKeyIdentifier = hash\n"
"authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
+ "subjectAltName = DNS.1:" ++ Hostname ++ "\n"
"issuerAltName = issuer:copy\n"
"crlDistributionPoints=@crl_section\n"
@@ -449,7 +450,7 @@ ca_cnf(Root, C = #config{issuing_distribution_point = true}) ->
"keyUsage = digitalSignature\n"
"subjectKeyIdentifier = hash\n"
"authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
+ "subjectAltName = DNS.1:" ++ Hostname ++ "\n"
"issuerAltName = issuer:copy\n"
"\n"
@@ -458,12 +459,13 @@ ca_cnf(Root, C = #config{issuing_distribution_point = true}) ->
"keyUsage = cRLSign, keyCertSign\n"
"subjectKeyIdentifier = hash\n"
"authorityKeyIdentifier = keyid:always,issuer:always\n"
- "subjectAltName = email:copy\n"
+ "subjectAltName = DNS.1:" ++ Hostname ++ "\n"
"issuerAltName = issuer:copy\n"
"crlDistributionPoints=@crl_section\n"
];
ca_cnf(Root, C = #config{issuing_distribution_point = false}) ->
+ Hostname = net_adm:localhost(),
["# Purpose: Configuration for CAs.\n"
"\n"
"ROOTDIR = " ++ Root ++ "\n"
@@ -513,7 +515,7 @@ ca_cnf(Root, C = #config{issuing_distribution_point = false}) ->
"keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n"
"subjectKeyIdentifier = hash\n"
"authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
+ "subjectAltName = DNS.1:" ++ Hostname ++ "\n"
"issuerAltName = issuer:copy\n"
%"crlDistributionPoints=@crl_section\n"
@@ -528,7 +530,7 @@ ca_cnf(Root, C = #config{issuing_distribution_point = false}) ->
"keyUsage = digitalSignature\n"
"subjectKeyIdentifier = hash\n"
"authorityKeyIdentifier = keyid,issuer:always\n"
- "subjectAltName = email:copy\n"
+ "subjectAltName = DNS.1:" ++ Hostname ++ "\n"
"issuerAltName = issuer:copy\n"
"\n"
diff --git a/lib/ssl/test/ssl.spec b/lib/ssl/test/ssl.spec
index 86e14c033e..0ad94e22bc 100644
--- a/lib/ssl/test/ssl.spec
+++ b/lib/ssl/test/ssl.spec
@@ -1,4 +1,5 @@
{suites,"../ssl_test",all}.
{skip_cases, "../ssl_test",
- ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple],
+ ssl_bench_SUITE, [setup_sequential, setup_concurrent, payload_simple,
+ use_pem_cache, bypass_pem_cache],
"Benchmarks run separately"}.
diff --git a/lib/ssl/test/ssl_ECC.erl b/lib/ssl/test/ssl_ECC.erl
new file mode 100644
index 0000000000..6422cd75e9
--- /dev/null
+++ b/lib/ssl/test/ssl_ECC.erl
@@ -0,0 +1,171 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_ECC).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%% Test diffrent certificate chain types, note that it is the servers
+%% chain that affect what cipher suit that will be choosen
+
+%% ECDH_RSA
+client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ Suites = all_rsa_suites(Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_rsa, ecdh_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_rsa}, {ciphers, Suites} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ Suites = all_rsa_suites(Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdh_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_rsa}, {ciphers, Suites} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ Suites = all_rsa_suites(Config),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdh_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_rsa}, {ciphers, Suites} | proplists:delete(check_keyex, Config)]).
+
+%% ECDHE_RSA
+client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_ecdsa, ecdhe_rsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]).
+
+%% ECDH_ECDSA
+client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain,
+ ssl_test_lib:default_cert_chain_conf()}],
+ ecdh_ecdsa, ecdh_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain,
+ ssl_test_lib:default_cert_chain_conf()}],
+ ecdhe_rsa, ecdh_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
+
+client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [keyAgreement]}]),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain,
+ ssl_test_lib:default_cert_chain_conf()}],
+ ecdhe_ecdsa, ecdh_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]).
+
+%% ECDHE_ECDSA
+client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
+client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdh_ecdsa, ecdhe_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
+client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain,
+ [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ ssl_test_lib:basic_test(ssl_test_lib:ssl_options(COpts, Config),
+ ssl_test_lib:ssl_options(SOpts, Config),
+ [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]).
+
+all_rsa_suites(Config) ->
+ Version = proplists:get_value(tls_version, Config),
+ All = ssl:cipher_suites(all, Version),
+ Default = ssl:cipher_suites(default, Version),
+ RSASuites = ssl:filter_cipher_suites(All,[{key_exchange, fun(rsa) -> true;(_) -> false end}]),
+ ssl:append_cipher_suites(RSASuites, Default).
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index b8a03f578d..c93f066825 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -36,51 +36,84 @@ all() ->
[
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
- {group, 'tlsv1'}
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
].
groups() ->
[
- {'tlsv1.2', [], all_versions_groups()},
- {'tlsv1.1', [], all_versions_groups()},
- {'tlsv1', [], all_versions_groups()},
- {'erlang_server', [], key_cert_combinations()},
- {'erlang_client', [], key_cert_combinations()},
- {'erlang', [], key_cert_combinations() ++ misc()}
+ {'tlsv1.2', [], [mix_sign | test_cases()]},
+ {'tlsv1.1', [], test_cases()},
+ {'tlsv1', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
+ {'dtlsv1', [], test_cases()}
].
-all_versions_groups ()->
- [{group, 'erlang_server'},
- {group, 'erlang_client'},
- {group, 'erlang'}
- ].
+test_cases()->
+ key_cert_combinations()
+ ++ misc()
+ ++ ecc_negotiation().
key_cert_combinations() ->
- [client_ecdh_server_ecdh,
- client_rsa_server_ecdh,
- client_ecdh_server_rsa,
- client_rsa_server_rsa,
- client_ecdsa_server_ecdsa,
- client_ecdsa_server_rsa,
- client_rsa_server_ecdsa
- ].
+ server_ecdh_rsa() ++
+ server_ecdhe_rsa() ++
+ server_ecdh_ecdsa() ++
+ server_ecdhe_ecdsa().
+
+server_ecdh_rsa() ->
+ [client_ecdh_rsa_server_ecdh_rsa,
+ client_ecdhe_rsa_server_ecdh_rsa,
+ client_ecdhe_ecdsa_server_ecdh_rsa].
+
+server_ecdhe_rsa() ->
+ [client_ecdh_rsa_server_ecdhe_rsa,
+ client_ecdhe_rsa_server_ecdhe_rsa,
+ client_ecdhe_ecdsa_server_ecdhe_rsa].
+
+server_ecdh_ecdsa() ->
+ [client_ecdh_ecdsa_server_ecdh_ecdsa,
+ client_ecdhe_rsa_server_ecdh_ecdsa,
+ client_ecdhe_ecdsa_server_ecdh_ecdsa].
+
+server_ecdhe_ecdsa() ->
+ [client_ecdh_rsa_server_ecdhe_ecdsa,
+ client_ecdh_ecdsa_server_ecdhe_ecdsa,
+ client_ecdhe_ecdsa_server_ecdhe_ecdsa].
misc()->
[client_ecdsa_server_ecdsa_with_raw_key].
+ecc_negotiation() ->
+ [ecc_default_order,
+ ecc_default_order_custom_curves,
+ ecc_client_order,
+ ecc_client_order_custom_curves,
+ ecc_unknown_curve,
+ client_ecdh_rsa_server_ecdhe_ecdsa_server_custom,
+ client_ecdh_rsa_server_ecdhe_rsa_server_custom,
+ client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom,
+ client_ecdhe_rsa_server_ecdhe_rsa_server_custom,
+ client_ecdhe_rsa_server_ecdh_rsa_server_custom,
+ client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom,
+ client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom,
+ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom,
+ client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom
+ ].
+
%%--------------------------------------------------------------------
init_per_suite(Config0) ->
end_per_suite(Config0),
try crypto:start() of
ok ->
- %% make rsa certs using oppenssl
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- Config1 = ssl_test_lib:make_ecdsa_cert(Config0),
- Config2 = ssl_test_lib:make_ecdh_rsa_cert(Config1),
- ssl_test_lib:cert_options(Config2)
+ case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
+ true ->
+ Config0;
+ false ->
+ {skip, "Crypto does not support ECC"}
+ end
catch _:_ ->
- {skip, "Crypto did not start"}
+ {skip, "Crypto did not start"}
end.
end_per_suite(_Config) ->
@@ -88,56 +121,24 @@ end_per_suite(_Config) ->
application:stop(crypto).
%%--------------------------------------------------------------------
-init_per_group(erlang_client = Group, Config) ->
- case ssl_test_lib:is_sane_ecc(openssl) of
- true ->
- common_init_per_group(Group, [{server_type, openssl},
- {client_type, erlang} | Config]);
- false ->
- {skip, "Known ECC bug in openssl"}
- end;
-
-init_per_group(erlang_server = Group, Config) ->
- case ssl_test_lib:is_sane_ecc(openssl) of
- true ->
- common_init_per_group(Group, [{server_type, erlang},
- {client_type, openssl} | Config]);
- false ->
- {skip, "Known ECC bug in openssl"}
- end;
-
-init_per_group(erlang = Group, Config) ->
- case ssl_test_lib:sufficient_crypto_support(Group) of
- true ->
- common_init_per_group(Group, [{server_type, erlang},
- {client_type, erlang} | Config]);
- false ->
- {skip, "Crypto does not support ECC"}
- end;
-
-init_per_group(openssl = Group, Config) ->
- case ssl_test_lib:sufficient_crypto_support(Group) of
- true ->
- common_init_per_group(Group, [{server_type, openssl},
- {client_type, openssl} | Config]);
- false ->
- {skip, "Crypto does not support ECC"}
- end;
-
-init_per_group(Group, Config) ->
- common_init_per_group(Group, Config).
-
-common_init_per_group(GroupName, Config) ->
+init_per_group(GroupName, Config) ->
case ssl_test_lib:is_tls_version(GroupName) of
true ->
- Config0 = ssl_test_lib:init_tls_version(GroupName, Config),
- [{tls_version, GroupName} | Config0];
- _ ->
- openssl_check(GroupName, Config)
+ [{tls_version, GroupName},
+ {server_type, erlang},
+ {client_type, erlang} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ _ ->
+ Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config0) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ Config = ssl_test_lib:clean_tls_version(Config0),
+ proplists:delete(tls_version, Config);
+ false ->
+ Config0
+ end.
%%--------------------------------------------------------------------
@@ -145,7 +146,7 @@ init_per_testcase(TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
end_per_testcase(TestCase, Config),
- ssl:start(),
+ ssl:start(),
ct:timetrap({seconds, 15}),
Config.
@@ -156,199 +157,248 @@ end_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
-
-client_ecdh_server_ecdh(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
- SOpts = proplists:get_value(server_ecdh_rsa_verify_opts, Config),
- basic_test(COpts, SOpts, Config).
-
-client_ecdh_server_rsa(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
- SOpts = proplists:get_value(server_ecdh_rsa_verify_opts, Config),
- basic_test(COpts, SOpts, Config).
-
-client_rsa_server_ecdh(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdh_rsa_opts, Config),
- SOpts = proplists:get_value(server_ecdh_rsa_verify_opts, Config),
- basic_test(COpts, SOpts, Config).
-
-client_rsa_server_rsa(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_verification_opts, Config),
- SOpts = proplists:get_value(server_verification_opts, Config),
- basic_test(COpts, SOpts, Config).
-
-client_ecdsa_server_ecdsa(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
- basic_test(COpts, SOpts, Config).
-
-client_ecdsa_server_rsa(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
- basic_test(COpts, SOpts, Config).
-
-client_rsa_server_ecdsa(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
- basic_test(COpts, SOpts, Config).
+%% Test diffrent certificate chain types, note that it is the servers
+%% chain that affect what cipher suit that will be choosen
+
+%% ECDH_RSA
+client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
+client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
+client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
+%% ECDHE_RSA
+client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
+%% ECDH_ECDSA
+client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
+client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
+%% ECDHE_ECDSA
+client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
+client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) ->
- COpts = proplists:get_value(client_ecdsa_opts, Config),
- SOpts = proplists:get_value(server_ecdsa_verify_opts, Config),
- ServerCert = proplists:get_value(certfile, SOpts),
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}]
+ , ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
ServerKeyFile = proplists:get_value(keyfile, SOpts),
{ok, PemBin} = file:read_file(ServerKeyFile),
PemEntries = public_key:pem_decode(PemBin),
- {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries),
+ {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries),
ServerKey = {'ECPrivateKey', Key},
- ServerCA = proplists:get_value(cacertfile, SOpts),
- ClientCert = proplists:get_value(certfile, COpts),
- ClientKey = proplists:get_value(keyfile, COpts),
- ClientCA = proplists:get_value(cacertfile, COpts),
SType = proplists:get_value(server_type, Config),
CType = proplists:get_value(client_type, Config),
- {Server, Port} = start_server_with_raw_key(SType,
- ClientCA, ServerCA,
- ServerCert,
- ServerKey,
- Config),
- Client = start_client(CType, Port, ServerCA, ClientCA,
- ClientCert,
- ClientKey, Config),
- check_result(Server, SType, Client, CType),
- close(Server, Client).
+ {Server, Port} = ssl_test_lib:start_server_with_raw_key(SType,
+ [{key, ServerKey} | proplists:delete(keyfile, SOpts)],
+ Config),
+ Client = ssl_test_lib:start_client(CType, Port, COpts, Config),
+ ssl_test_lib:gen_check_result(Server, SType, Client, CType),
+ ssl_test_lib:stop(Server, Client).
+
+ecc_default_order(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [],
+ case ssl_test_lib:supported_eccs([{eccs, [sect571r1]}]) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+ecc_default_order_custom_curves(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
-%%--------------------------------------------------------------------
-%% Internal functions ------------------------------------------------
-%%--------------------------------------------------------------------
-basic_test(COpts, SOpts, Config) ->
- basic_test(proplists:get_value(certfile, COpts),
- proplists:get_value(keyfile, COpts),
- proplists:get_value(cacertfile, COpts),
- proplists:get_value(certfile, SOpts),
- proplists:get_value(keyfile, SOpts),
- proplists:get_value(cacertfile, SOpts),
- Config).
+ecc_client_order(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, false}],
+ case ssl_test_lib:supported_eccs([{eccs, [sect571r1]}]) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+ecc_client_order_custom_curves(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+ecc_unknown_curve(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{eccs, ['123_fake_curve']}],
+ ssl_test_lib:ecc_test_error(COpts, SOpts, [], ECCOpts, Config).
+
+client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdh_rsa, ecdhe_rsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
-basic_test(ClientCert, ClientKey, ClientCA, ServerCert, ServerKey, ServerCA, Config) ->
- SType = proplists:get_value(server_type, Config),
- CType = proplists:get_value(client_type, Config),
- {Server, Port} = start_server(SType,
- ClientCA, ServerCA,
- ServerCert,
- ServerKey,
- Config),
- Client = start_client(CType, Port, ServerCA, ClientCA,
- ClientCert,
- ClientKey, Config),
- check_result(Server, SType, Client, CType),
- close(Server, Client).
-
-start_client(openssl, Port, CA, OwnCa, Cert, Key, Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa),
- Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Exe = "openssl",
- Args = ["s_client", "-verify", "2", "-port", integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cert", Cert, "-CAfile", NewCA,
- "-key", Key, "-host","localhost", "-msg", "-debug"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, "Hello world"),
- OpenSslPort;
-start_client(erlang, Port, CA, _, Cert, Key, Config) ->
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
- ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, [{verify, verify_peer},
- {cacertfile, CA},
- {certfile, Cert}, {keyfile, Key}]}]).
-
-start_server(openssl, CA, OwnCa, Cert, Key, Config) ->
- PrivDir = proplists:get_value(priv_dir, Config),
- NewCA = new_ca(filename:join(PrivDir, "new_ca.pem"), CA, OwnCa),
-
- Port = ssl_test_lib:inet_port(node()),
- Version = tls_record:protocol_version(tls_record:highest_protocol_version([])),
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
- "-verify", "2", "-cert", Cert, "-CAfile", NewCA,
- "-key", Key, "-msg", "-debug"],
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, "Hello world"),
- {OpenSslPort, Port};
-start_server(erlang, CA, _, Cert, Key, Config) ->
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- send_recv_result_active,
- []}},
- {options,
- [{verify, verify_peer}, {cacertfile, CA},
- {certfile, Cert}, {keyfile, Key}]}]),
- {Server, ssl_test_lib:inet_port(Server)}.
-start_server_with_raw_key(erlang, CA, _, Cert, Key, Config) ->
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
- {mfa, {ssl_test_lib,
- send_recv_result_active,
- []}},
- {options,
- [{verify, verify_peer}, {cacertfile, CA},
- {certfile, Cert}, {key, Key}]}]),
- {Server, ssl_test_lib:inet_port(Server)}.
-
-check_result(Server, erlang, Client, erlang) ->
- ssl_test_lib:check_result(Server, ok, Client, ok);
-check_result(Server, erlang, _, _) ->
- ssl_test_lib:check_result(Server, ok);
-check_result(_, _, Client, erlang) ->
- ssl_test_lib:check_result(Client, ok);
-check_result(_,openssl, _, openssl) ->
- ok.
-
-openssl_check(erlang, Config) ->
- Config;
-openssl_check(_, Config) ->
- TLSVersion = proplists:get_value(tls_version, Config),
- case ssl_test_lib:check_sane_openssl_version(TLSVersion) of
- true ->
- Config;
- false ->
- {skip, "TLS version not supported by openssl"}
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_rsa, Config),
+
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdh_rsa, Config),
+
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ Expected = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(0))), %% The certificate curve
+
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(Expected, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_rsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_ecdsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
+ false -> {skip, "unsupported named curves"}
+ end.
+
+client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
+ Default = ssl_test_lib:default_cert_chain_conf(),
+ {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
+ {client_chain, Default}],
+ ecdhe_rsa, ecdhe_ecdsa, Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECCOpts = [{eccs, [secp256r1, sect571r1]}],
+ case ssl_test_lib:supported_eccs(ECCOpts) of
+ true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
+ false -> {skip, "unsupported named curves"}
end.
-close(Port1, Port2) when is_port(Port1), is_port(Port2) ->
- ssl_test_lib:close_port(Port1),
- ssl_test_lib:close_port(Port2);
-close(Port, Pid) when is_port(Port) ->
- ssl_test_lib:close_port(Port),
- ssl_test_lib:close(Pid);
-close(Pid, Port) when is_port(Port) ->
- ssl_test_lib:close_port(Port),
- ssl_test_lib:close(Pid);
-close(Client, Server) ->
- ssl_test_lib:close(Server),
- ssl_test_lib:close(Client).
-
-%% Work around OpenSSL bug, apparently the same bug as we had fixed in
-%% 11629690ba61f8e0c93ef9b2b6102fd279825977
-new_ca(FileName, CA, OwnCa) ->
- {ok, P1} = file:read_file(CA),
- E1 = public_key:pem_decode(P1),
- {ok, P2} = file:read_file(OwnCa),
- E2 = public_key:pem_decode(P2),
- case os:cmd("openssl version") of
- "OpenSSL 1.0.1p-freebsd" ++ _ ->
- Pem = public_key:pem_encode(E1 ++E2),
- file:write_file(FileName, Pem);
- _ ->
- Pem = public_key:pem_encode(E2 ++E1),
- file:write_file(FileName, Pem)
- end,
- FileName.
+mix_sign(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config).
diff --git a/lib/ssl/test/ssl_ECC_openssl_SUITE.erl b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
new file mode 100644
index 0000000000..81a7dfd2da
--- /dev/null
+++ b/lib/ssl/test/ssl_ECC_openssl_SUITE.erl
@@ -0,0 +1,218 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssl_ECC_openssl_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ case test_cases() of
+ [_|_] ->
+ all_groups();
+ [] ->
+ [skip]
+ end.
+
+all_groups() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}];
+ false ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'}]
+ end.
+
+groups() ->
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
+ {'tlsv1.1', [], test_cases()},
+ {'tlsv1', [], test_cases()},
+ {'dtlsv1.2', [], [mix_sign | test_cases()]},
+ {'dtlsv1', [], test_cases()}];
+ false ->
+ [{'tlsv1.2', [], [mix_sign | test_cases()]},
+ {'tlsv1.1', [], test_cases()},
+ {'tlsv1', [], test_cases()}]
+ end.
+
+test_cases()->
+ cert_combinations().
+
+cert_combinations() ->
+ lists:append(lists:map(fun({Name, Suites}) ->
+ case ssl_test_lib:openssl_filter(Name) of
+ [] ->
+ [];
+ [_|_] ->
+ Suites
+ end
+ end, [{"ECDH-ECDSA", server_ecdh_ecdsa()},
+ {"ECDH-RSA", server_ecdh_rsa()},
+ {"ECDHE-RSA", server_ecdhe_rsa()},
+ {"ECDHE-ECDSA", server_ecdhe_ecdsa()}
+ ])).
+server_ecdh_rsa() ->
+ [client_ecdh_rsa_server_ecdh_rsa,
+ client_ecdhe_rsa_server_ecdh_rsa,
+ client_ecdhe_ecdsa_server_ecdh_rsa].
+
+server_ecdhe_rsa() ->
+ [client_ecdh_rsa_server_ecdhe_rsa,
+ client_ecdhe_rsa_server_ecdhe_rsa,
+ client_ecdhe_ecdsa_server_ecdhe_rsa].
+
+server_ecdh_ecdsa() ->
+ [client_ecdh_ecdsa_server_ecdh_ecdsa,
+ client_ecdhe_rsa_server_ecdh_ecdsa,
+ client_ecdhe_ecdsa_server_ecdh_ecdsa].
+
+server_ecdhe_ecdsa() ->
+ [client_ecdh_rsa_server_ecdhe_ecdsa,
+ client_ecdh_ecdsa_server_ecdhe_ecdsa,
+ client_ecdhe_ecdsa_server_ecdhe_ecdsa].
+
+%%--------------------------------------------------------------------
+init_per_suite(Config0) ->
+ end_per_suite(Config0),
+ try crypto:start() of
+ ok ->
+ case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
+ true ->
+ Config0;
+ false ->
+ {skip, "Openssl does not support ECC"}
+ end
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ application:stop(ssl),
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ [{tls_version, GroupName},
+ {server_type, erlang},
+ {client_type, openssl} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
+ Config
+ end.
+
+end_per_group(GroupName, Config0) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ Config = ssl_test_lib:clean_tls_version(Config0),
+ proplists:delete(tls_version, Config);
+ false ->
+ Config0
+ end.
+
+%%--------------------------------------------------------------------
+init_per_testcase(skip, Config) ->
+ Config;
+init_per_testcase(TestCase, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ Version = proplists:get_value(tls_version, Config),
+ ct:log("Ciphers: ~p~n ", [ssl:cipher_suites(default, Version)]),
+ end_per_testcase(TestCase, Config),
+ ssl:start(),
+ ct:timetrap({seconds, 30}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ application:stop(ssl),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+skip(Config) when is_list(Config) ->
+ {skip, openssl_does_not_support_ECC}.
+
+%% Test diffrent certificate chain types, note that it is the servers
+%% chain that affect what cipher suit that will be choosen
+
+%% ECDH_RSA
+client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdh_rsa(Config).
+client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_rsa(Config).
+client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_rsa(Config).
+%% ECDHE_RSA
+client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdhe_rsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_rsa(Config).
+%% ECDH_ECDSA
+client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdh_ecdsa(Config).
+client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_rsa_server_ecdh_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdh_ecdsa(Config).
+%% ECDHE_ECDSA
+client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_rsa_server_ecdhe_ecdsa(Config).
+client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdh_ecdsa_server_ecdhe_ecdsa(Config).
+client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) ->
+ ssl_ECC:client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config).
+
+mix_sign(Config) ->
+ {COpts0, SOpts0} = ssl_test_lib:make_mix_cert(Config),
+ COpts = ssl_test_lib:ssl_options(COpts0, Config),
+ SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
+ ECDHE_ECDSA =
+ ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
+ [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
+ ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], [{client_type, erlang},
+ {server_type, openssl} | Config]).
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
index da181faf64..055f05a900 100644
--- a/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_alpn_handshake_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,14 +35,19 @@ all() ->
[{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
- {group, 'sslv3'}].
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
groups() ->
[
{'tlsv1.2', [], alpn_tests()},
{'tlsv1.1', [], alpn_tests()},
{'tlsv1', [], alpn_tests()},
- {'sslv3', [], alpn_not_supported()}
+ {'sslv3', [], alpn_not_supported()},
+ {'dtlsv1.2', [], alpn_tests() -- [client_renegotiate]},
+ {'dtlsv1', [], alpn_tests() -- [client_renegotiate]}
].
alpn_tests() ->
@@ -67,13 +72,12 @@ alpn_not_supported() ->
alpn_not_supported_server
].
-init_per_suite(Config) ->
+init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config),
- proplists:get_value(priv_dir, Config)),
+ ssl_test_lib:clean_start(),
+ Config = ssl_test_lib:make_rsa_cert(Config0),
ssl_test_lib:cert_options(Config)
catch _:_ ->
{skip, "Crypto did not start"}
@@ -90,8 +94,7 @@ init_per_group(GroupName, Config) ->
true ->
case ssl_test_lib:sufficient_crypto_support(GroupName) of
true ->
- ssl_test_lib:init_tls_version(GroupName, Config),
- Config;
+ ssl_test_lib:init_tls_version(GroupName, Config);
false ->
{skip, "Missing crypto support"}
end;
@@ -100,8 +103,14 @@ init_per_group(GroupName, Config) ->
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
+
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
@@ -116,26 +125,29 @@ end_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
empty_protocols_are_not_allowed(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{error, {options, {alpn_preferred_protocols, {invalid_protocol, <<>>}}}}
= (catch ssl:listen(9443,
- [{alpn_preferred_protocols, [<<"foo/1">>, <<"">>]}])),
+ [{alpn_preferred_protocols, [<<"foo/1">>, <<"">>]}| ServerOpts])),
{error, {options, {alpn_advertised_protocols, {invalid_protocol, <<>>}}}}
= (catch ssl:connect({127,0,0,1}, 9443,
- [{alpn_advertised_protocols, [<<"foo/1">>, <<"">>]}])).
+ [{alpn_advertised_protocols, [<<"foo/1">>, <<"">>]} | ServerOpts])).
%--------------------------------------------------------------------------------
protocols_must_be_a_binary_list(Config) when is_list(Config) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
Option1 = {alpn_preferred_protocols, hello},
- {error, {options, Option1}} = (catch ssl:listen(9443, [Option1])),
+ {error, {options, Option1}} = (catch ssl:listen(9443, [Option1 | ServerOpts])),
Option2 = {alpn_preferred_protocols, [<<"foo/1">>, hello]},
{error, {options, {alpn_preferred_protocols, {invalid_protocol, hello}}}}
- = (catch ssl:listen(9443, [Option2])),
+ = (catch ssl:listen(9443, [Option2 | ServerOpts])),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
Option3 = {alpn_advertised_protocols, hello},
- {error, {options, Option3}} = (catch ssl:connect({127,0,0,1}, 9443, [Option3])),
+ {error, {options, Option3}} = (catch ssl:connect({127,0,0,1}, 9443, [Option3 | ClientOpts])),
Option4 = {alpn_advertised_protocols, [<<"foo/1">>, hello]},
{error, {options, {alpn_advertised_protocols, {invalid_protocol, hello}}}}
- = (catch ssl:connect({127,0,0,1}, 9443, [Option4])).
+ = (catch ssl:connect({127,0,0,1}, 9443, [Option4 | ClientOpts])).
%--------------------------------------------------------------------------------
@@ -226,9 +238,9 @@ client_alpn_and_server_alpn_npn(Config) when is_list(Config) ->
client_renegotiate(Config) when is_list(Config) ->
Data = "hello world",
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"http/1.0">>]}] ++ ClientOpts0,
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}] ++ ServerOpts0,
ExpectedProtocol = {ok, <<"http/1.0">>},
@@ -250,9 +262,9 @@ client_renegotiate(Config) when is_list(Config) ->
%--------------------------------------------------------------------------------
session_reused(Config) when is_list(Config)->
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"http/1.0">>]}] ++ ClientOpts0,
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]}] ++ ServerOpts0,
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -299,7 +311,7 @@ session_reused(Config) when is_list(Config)->
%--------------------------------------------------------------------------------
alpn_not_supported_client(Config) when is_list(Config) ->
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
PrefProtocols = {client_preferred_next_protocols,
{client, [<<"http/1.0">>], <<"http/1.1">>}},
ClientOpts = [PrefProtocols] ++ ClientOpts0,
@@ -315,7 +327,7 @@ alpn_not_supported_client(Config) when is_list(Config) ->
%--------------------------------------------------------------------------------
alpn_not_supported_server(Config) when is_list(Config)->
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
AdvProtocols = {next_protocols_advertised, [<<"spdy/2">>, <<"http/1.1">>, <<"http/1.0">>]},
ServerOpts = [AdvProtocols] ++ ServerOpts0,
@@ -326,8 +338,8 @@ alpn_not_supported_server(Config) when is_list(Config)->
%%--------------------------------------------------------------------
run_failing_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedResult) ->
- ClientOpts = ClientExtraOpts ++ proplists:get_value(client_opts, Config),
- ServerOpts = ServerExtraOpts ++ proplists:get_value(server_opts, Config),
+ ClientOpts = ClientExtraOpts ++ ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ServerExtraOpts ++ ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -346,9 +358,9 @@ run_failing_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedResult)
run_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) ->
Data = "hello world",
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = ClientExtraOpts ++ ClientOpts0,
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = ServerExtraOpts ++ ServerOpts0,
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index efa5faa218..0023c8656a 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@
-define(SLEEP, 500).
-define(RENEGOTIATION_DISABLE_TIME, 12000).
-define(CLEAN_SESSION_DB, 60000).
+-define(SEC_RENEGOTIATION_TIMEOUT, 30).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -51,8 +52,8 @@ all() ->
{group, options},
{group, options_tls},
{group, session},
- %%{group, 'dtlsv1.2'},
- %%{group, 'dtlsv1'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'},
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
@@ -64,14 +65,15 @@ groups() ->
{basic_tls, [], basic_tests_tls()},
{options, [], options_tests()},
{options_tls, [], options_tests_tls()},
- %%{'dtlsv1.2', [], all_versions_groups()},
- %%{'dtlsv1', [], all_versions_groups()},
+ {'dtlsv1.2', [], all_versions_groups()},
+ {'dtlsv1', [], all_versions_groups()},
{'tlsv1.2', [], all_versions_groups() ++ tls_versions_groups() ++ [conf_signature_algs, no_common_signature_algs]},
{'tlsv1.1', [], all_versions_groups() ++ tls_versions_groups()},
{'tlsv1', [], all_versions_groups() ++ tls_versions_groups() ++ rizzo_tests()},
{'sslv3', [], all_versions_groups() ++ tls_versions_groups() ++ rizzo_tests() ++ [tls_ciphersuite_vs_version]},
{api,[], api_tests()},
{api_tls,[], api_tests_tls()},
+ {tls_ciphers,[], tls_cipher_tests()},
{session, [], session_tests()},
{renegotiate, [], renegotiate_tests()},
{ciphers, [], cipher_tests()},
@@ -81,7 +83,9 @@ groups() ->
].
tls_versions_groups ()->
- [{group, api_tls},
+ [
+ {group, api_tls},
+ {group, tls_ciphers},
{group, error_handling_tests_tls}].
all_versions_groups ()->
@@ -115,7 +119,6 @@ options_tests() ->
[der_input,
ssl_options_not_proplist,
raw_ssl_option,
- socket_options,
invalid_inet_get_option,
invalid_inet_get_option_not_list,
invalid_inet_get_option_improper_list,
@@ -134,7 +137,8 @@ options_tests() ->
honor_server_cipher_order,
honor_client_cipher_order,
unordered_protocol_versions_server,
- unordered_protocol_versions_client
+ unordered_protocol_versions_client,
+ max_handshake_size
].
options_tests_tls() ->
@@ -143,12 +147,12 @@ options_tests_tls() ->
api_tests() ->
[connection_info,
+ secret_connection_info,
connection_information,
- peername,
peercert,
peercert_with_client_cert,
- sockname,
versions,
+ eccs,
controlling_process,
getstat,
close_with_timeout,
@@ -158,8 +162,9 @@ api_tests() ->
ssl_recv_timeout,
server_name_indication_option,
accept_pool,
- new_options_in_accept,
- prf
+ prf,
+ socket_options,
+ cipher_suites
].
api_tests_tls() ->
@@ -171,7 +176,11 @@ api_tests_tls() ->
tls_shutdown,
tls_shutdown_write,
tls_shutdown_both,
- tls_shutdown_error
+ tls_shutdown_error,
+ peername,
+ sockname,
+ tls_socket_options,
+ new_options_in_accept
].
session_tests() ->
@@ -193,8 +202,13 @@ renegotiate_tests() ->
renegotiate_dos_mitigate_passive,
renegotiate_dos_mitigate_absolute].
+tls_cipher_tests() ->
+ [rc4_rsa_cipher_suites,
+ rc4_ecdh_rsa_cipher_suites,
+ rc4_ecdsa_cipher_suites].
+
cipher_tests() ->
- [cipher_suites,
+ [old_cipher_suites,
cipher_suites_mix,
ciphers_rsa_signed_certs,
ciphers_rsa_signed_certs_openssl_names,
@@ -208,9 +222,6 @@ cipher_tests() ->
srp_cipher_suites,
srp_anon_cipher_suites,
srp_dsa_cipher_suites,
- rc4_rsa_cipher_suites,
- rc4_ecdh_rsa_cipher_suites,
- rc4_ecdsa_cipher_suites,
des_rsa_cipher_suites,
des_ecdh_rsa_cipher_suites,
default_reject_anonymous].
@@ -222,15 +233,16 @@ cipher_tests_ec() ->
ciphers_ecdh_rsa_signed_certs_openssl_names].
error_handling_tests()->
- [controller_dies,
- close_transport_accept,
+ [close_transport_accept,
recv_active,
recv_active_once,
recv_error_handling
].
error_handling_tests_tls()->
- [tls_client_closes_socket,
+ [controller_dies,
+ tls_client_closes_socket,
+ tls_closed_in_active_once,
tls_tcp_error_propagation_in_active_mode,
tls_tcp_connect,
tls_tcp_connect_big,
@@ -249,7 +261,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
+ ssl_test_lib:clean_start(),
%% make rsa certs using oppenssl
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
proplists:get_value(priv_dir, Config0)),
@@ -266,6 +278,15 @@ end_per_suite(_Config) ->
application:stop(crypto).
%%--------------------------------------------------------------------
+
+init_per_group(GroupName, Config) when GroupName == basic_tls;
+ GroupName == options_tls;
+ GroupName == options;
+ GroupName == basic;
+ GroupName == session;
+ GroupName == error_handling_tests_tls
+ ->
+ ssl_test_lib:clean_tls_version(Config);
init_per_group(GroupName, Config) ->
case ssl_test_lib:is_tls_version(GroupName) andalso ssl_test_lib:sufficient_crypto_support(GroupName) of
true ->
@@ -280,8 +301,13 @@ init_per_group(GroupName, Config) ->
end
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
%%--------------------------------------------------------------------
init_per_testcase(Case, Config) when Case == unordered_protocol_versions_client;
@@ -306,6 +332,7 @@ init_per_testcase(protocol_versions, Config) ->
init_per_testcase(reuse_session_expired, Config) ->
ssl:stop(),
application:load(ssl),
+ ssl_test_lib:clean_env(),
application:set_env(ssl, session_lifetime, ?EXPIRE),
application:set_env(ssl, session_delay_cleanup_time, 500),
ssl:start(),
@@ -315,6 +342,7 @@ init_per_testcase(reuse_session_expired, Config) ->
init_per_testcase(empty_protocol_versions, Config) ->
ssl:stop(),
application:load(ssl),
+ ssl_test_lib:clean_env(),
application:set_env(ssl, protocol_version, []),
ssl:start(),
ct:timetrap({seconds, 5}),
@@ -340,42 +368,75 @@ init_per_testcase(TestCase, Config) when TestCase == client_renegotiate;
TestCase == renegotiate_dos_mitigate_passive;
TestCase == renegotiate_dos_mitigate_absolute ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 30}),
+ ct:timetrap({seconds, ?SEC_RENEGOTIATION_TIMEOUT + 5}),
Config;
init_per_testcase(TestCase, Config) when TestCase == psk_cipher_suites;
TestCase == psk_with_hint_cipher_suites;
TestCase == ciphers_rsa_signed_certs;
TestCase == ciphers_rsa_signed_certs_openssl_names;
+ TestCase == ciphers_ecdh_rsa_signed_certs_openssl_names;
+ TestCase == ciphers_ecdh_rsa_signed_certs;
TestCase == ciphers_dsa_signed_certs;
TestCase == ciphers_dsa_signed_certs_openssl_names;
TestCase == anonymous_cipher_suites;
- TestCase == versions_option,
+ TestCase == ciphers_ecdsa_signed_certs;
+ TestCase == ciphers_ecdsa_signed_certs_openssl_names;
+ TestCase == anonymous_cipher_suites;
+ TestCase == psk_anon_cipher_suites;
+ TestCase == psk_anon_with_hint_cipher_suites;
+ TestCase == srp_cipher_suites;
+ TestCase == srp_anon_cipher_suites;
+ TestCase == srp_dsa_cipher_suites;
+ TestCase == des_rsa_cipher_suites;
+ TestCase == des_ecdh_rsa_cipher_suites;
+ TestCase == versions_option;
TestCase == tls_tcp_connect_big ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 60}),
Config;
+init_per_testcase(version_option, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config;
+
+init_per_testcase(reuse_session, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config;
+
init_per_testcase(rizzo, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 40}),
+ ct:timetrap({seconds, 60}),
+ Config;
+
+init_per_testcase(no_rizzo_rc4, Config) ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 60}),
Config;
init_per_testcase(rizzo_one_n_minus_one, Config) ->
ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 40}),
+ ct:timetrap({seconds, 60}),
rizzo_add_mitigation_option(one_n_minus_one, Config);
init_per_testcase(rizzo_zero_n, Config) ->
ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 40}),
+ ct:timetrap({seconds, 60}),
rizzo_add_mitigation_option(zero_n, Config);
init_per_testcase(rizzo_disabled, Config) ->
ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
- ct:timetrap({seconds, 40}),
+ ct:timetrap({seconds, 60}),
rizzo_add_mitigation_option(disabled, Config);
+init_per_testcase(TestCase, Config) when TestCase == no_reuses_session_server_restart_new_cert_file;
+ TestCase == no_reuses_session_server_restart_new_cert ->
+ ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
+ ct:timetrap({seconds, 15}),
+ Config;
+
init_per_testcase(prf, Config) ->
ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),
ct:timetrap({seconds, 40}),
@@ -404,12 +465,18 @@ init_per_testcase(prf, Config) ->
init_per_testcase(TestCase, Config) when TestCase == tls_ssl_accept_timeout;
TestCase == tls_client_closes_socket;
+ TestCase == tls_closed_in_active_once;
TestCase == tls_downgrade ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 15}),
Config;
-init_per_testcase(clear_pem_cache, Config) ->
+init_per_testcase(TestCase, Config) when TestCase == clear_pem_cache;
+ TestCase == der_input;
+ TestCase == defaults ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ %% White box test need clean start
+ ssl:stop(),
+ ssl:start(),
ct:timetrap({seconds, 20}),
Config;
init_per_testcase(raw_ssl_option, Config) ->
@@ -430,7 +497,18 @@ init_per_testcase(accept_pool, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
Config
end;
-
+init_per_testcase(controller_dies, Config) ->
+ ct:timetrap({seconds, 10}),
+ Config;
+init_per_testcase(eccs, Config) ->
+ case ssl:eccs() of
+ [] ->
+ {skip, "named curves not supported"};
+ [_|_] ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 5}),
+ Config
+ end;
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 5}),
@@ -441,6 +519,11 @@ end_per_testcase(reuse_session_expired, Config) ->
application:unset_env(ssl, session_delay_cleanup_time),
end_per_testcase(default_action, Config);
+end_per_testcase(Case, Config) when Case == protocol_versions;
+ Case == empty_protocol_versions->
+ application:unset_env(ssl, protocol_versions),
+ end_per_testcase(default_action, Config);
+
end_per_testcase(_TestCase, Config) ->
Config.
@@ -461,7 +544,7 @@ alerts() ->
[{doc, "Test ssl_alert:alert_txt/1"}].
alerts(Config) when is_list(Config) ->
Descriptions = [?CLOSE_NOTIFY, ?UNEXPECTED_MESSAGE, ?BAD_RECORD_MAC,
- ?DECRYPTION_FAILED, ?RECORD_OVERFLOW, ?DECOMPRESSION_FAILURE,
+ ?DECRYPTION_FAILED_RESERVED, ?RECORD_OVERFLOW, ?DECOMPRESSION_FAILURE,
?HANDSHAKE_FAILURE, ?BAD_CERTIFICATE, ?UNSUPPORTED_CERTIFICATE,
?CERTIFICATE_REVOKED,?CERTIFICATE_EXPIRED, ?CERTIFICATE_UNKNOWN,
?ILLEGAL_PARAMETER, ?UNKNOWN_CA, ?ACCESS_DENIED, ?DECODE_ERROR,
@@ -565,10 +648,10 @@ prf(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
connection_info() ->
- [{doc,"Test the API function ssl:connection_information/1"}].
+ [{doc,"Test the API function ssl:connection_information/2"}].
connection_info(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -599,6 +682,36 @@ connection_info(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
+secret_connection_info() ->
+ [{doc,"Test the API function ssl:connection_information/2"}].
+secret_connection_info(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, secret_connection_info_result, []}},
+ {options, ServerOpts}]),
+
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, secret_connection_info_result, []}},
+ {options, ClientOpts}]),
+
+ ct:log("Testcase ~p, Client ~p Server ~p ~n",
+ [self(), Client, Server]),
+
+ ssl_test_lib:check_result(Server, true, Client, true),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
+%%--------------------------------------------------------------------
+
connection_information() ->
[{doc,"Test the API function ssl:connection_information/1"}].
connection_information(Config) when is_list(Config) ->
@@ -801,8 +914,7 @@ controller_dies(Config) when is_list(Config) ->
Server ! listen,
Tester = self(),
Connect = fun(Pid) ->
- {ok, Socket} = ssl:connect(Hostname, Port,
- [{reuseaddr,true},{ssl_imp,new}]),
+ {ok, Socket} = ssl:connect(Hostname, Port, ClientOpts),
%% Make sure server finishes and verification
%% and is in coonection state before
%% killing client
@@ -883,6 +995,48 @@ tls_client_closes_socket(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, {error,closed}).
%%--------------------------------------------------------------------
+tls_closed_in_active_once() ->
+ [{doc, "Test that ssl_closed is delivered in active once with non-empty buffer, check ERL-420."}].
+
+tls_closed_in_active_once(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {_ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ TcpOpts = [binary, {reuseaddr, true}],
+ Port = ssl_test_lib:inet_port(node()),
+ Server = fun() ->
+ {ok, Listen} = gen_tcp:listen(Port, TcpOpts),
+ {ok, TcpServerSocket} = gen_tcp:accept(Listen),
+ {ok, ServerSocket} = ssl:ssl_accept(TcpServerSocket, ServerOpts),
+ lists:foreach(
+ fun(_) ->
+ ssl:send(ServerSocket, "some random message\r\n")
+ end, lists:seq(1, 20)),
+ %% Close TCP instead of SSL socket to trigger the bug:
+ gen_tcp:close(TcpServerSocket),
+ gen_tcp:close(Listen)
+ end,
+ spawn_link(Server),
+ {ok, Socket} = ssl:connect(Hostname, Port, [{active, false} | ClientOpts]),
+ Result = tls_closed_in_active_once_loop(Socket),
+ ssl:close(Socket),
+ case Result of
+ ok -> ok;
+ _ -> ct:fail(Result)
+ end.
+
+tls_closed_in_active_once_loop(Socket) ->
+ ssl:setopts(Socket, [{active, once}]),
+ receive
+ {ssl, Socket, _} ->
+ tls_closed_in_active_once_loop(Socket);
+ {ssl_closed, Socket} ->
+ ok
+ after 5000 ->
+ no_ssl_closed_received
+ end.
+
+%%--------------------------------------------------------------------
connect_dist() ->
[{doc,"Test a simple connect as is used by distribution"}].
@@ -919,9 +1073,9 @@ clear_pem_cache(Config) when is_list(Config) ->
{status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)),
[_, _,_, _, Prop] = StatusInfo,
State = ssl_test_lib:state(Prop),
- [_,FilRefDb |_] = element(6, State),
+ [_,{FilRefDb, _} |_] = element(6, State),
{Server, Client} = basic_verify_test_no_close(Config),
- CountReferencedFiles = fun({_,-1}, Acc) ->
+ CountReferencedFiles = fun({_, -1}, Acc) ->
Acc;
({_, N}, Acc) ->
N + Acc
@@ -973,11 +1127,16 @@ fallback(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
cipher_format() ->
- [{doc, "Test that cipher conversion from tuples to binarys works"}].
+ [{doc, "Test that cipher conversion from maps | tuples | stings to binarys works"}].
cipher_format(Config) when is_list(Config) ->
- {ok, Socket} = ssl:listen(0, [{ciphers, ssl:cipher_suites()}]),
- ssl:close(Socket).
-
+ {ok, Socket0} = ssl:listen(0, [{ciphers, ssl:cipher_suites(default, 'tlsv1.2')}]),
+ ssl:close(Socket0),
+ %% Legacy
+ {ok, Socket1} = ssl:listen(0, [{ciphers, ssl:cipher_suites()}]),
+ ssl:close(Socket1),
+ {ok, Socket2} = ssl:listen(0, [{ciphers, ssl:cipher_suites(openssl)}]),
+ ssl:close(Socket2).
+
%%--------------------------------------------------------------------
peername() ->
@@ -1128,10 +1287,62 @@ sockname_result(S) ->
ssl:sockname(S).
%%--------------------------------------------------------------------
+
cipher_suites() ->
- [{doc,"Test API function cipher_suites/0"}].
+ [{doc,"Test API function cipher_suites/2, filter_cipher_suites/2"
+ " and prepend|append_cipher_suites/2"}].
cipher_suites(Config) when is_list(Config) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ All = [_|_] = ssl:cipher_suites(all, Version),
+ Default = [_|_] = ssl:cipher_suites(default, Version),
+ Anonymous = [_|_] = ssl:cipher_suites(anonymous, Version),
+ true = length(Default) < length(All),
+ Filters = [{key_exchange,
+ fun(dhe_rsa) ->
+ true;
+ (_) ->
+ false
+ end
+ },
+ {cipher,
+ fun(aes_256_cbc) ->
+ true;
+ (_) ->
+ false
+ end
+ },
+ {mac,
+ fun(sha) ->
+ true;
+ (_) ->
+ false
+ end
+ }
+ ],
+ Cipher = #{cipher => aes_256_cbc,
+ key_exchange => dhe_rsa,
+ mac => sha,
+ prf => default_prf},
+ [Cipher] = ssl:filter_cipher_suites(All, Filters),
+ [Cipher | Rest0] = ssl:prepend_cipher_suites([Cipher], Default),
+ [Cipher | Rest0] = ssl:prepend_cipher_suites(Filters, Default),
+ true = lists:member(Cipher, Default),
+ false = lists:member(Cipher, Rest0),
+ [Cipher | Rest1] = lists:reverse(ssl:append_cipher_suites([Cipher], Default)),
+ [Cipher | Rest1] = lists:reverse(ssl:append_cipher_suites(Filters, Default)),
+ true = lists:member(Cipher, Default),
+ false = lists:member(Cipher, Rest1),
+ [] = lists:dropwhile(fun(X) -> not lists:member(X, Default) end, Anonymous),
+ [] = lists:dropwhile(fun(X) -> not lists:member(X, All) end, Anonymous).
+
+
+%%--------------------------------------------------------------------
+
+old_cipher_suites() ->
+ [{doc,"Test API function cipher_suites/0"}].
+
+old_cipher_suites(Config) when is_list(Config) ->
MandatoryCipherSuite = {rsa,'3des_ede_cbc',sha},
[_|_] = Suites = ssl:cipher_suites(),
true = lists:member(MandatoryCipherSuite, Suites),
@@ -1144,8 +1355,8 @@ cipher_suites_mix() ->
cipher_suites_mix(Config) when is_list(Config) ->
CipherSuites = [{ecdh_rsa,aes_128_cbc,sha256,sha256}, {rsa,aes_128_cbc,sha}],
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -1164,10 +1375,10 @@ cipher_suites_mix(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-socket_options() ->
+tls_socket_options() ->
[{doc,"Test API function getopts/2 and setopts/2"}].
-socket_options(Config) when is_list(Config) ->
+tls_socket_options(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -1182,14 +1393,14 @@ socket_options(Config) when is_list(Config) ->
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, socket_options_result,
+ {mfa, {?MODULE, tls_socket_options_result,
[Options, Values, NewOptions, NewValues]}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, socket_options_result,
+ {mfa, {?MODULE, tls_socket_options_result,
[Options, Values, NewOptions, NewValues]}},
{options, ClientOpts}]),
@@ -1204,7 +1415,7 @@ socket_options(Config) when is_list(Config) ->
{ok,[{recbuf, _}]} = ssl:getopts(Listen, [recbuf]),
ssl:close(Listen).
-socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
+tls_socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
%% Test get/set emulated opts
{ok, DefaultValues} = ssl:getopts(Socket, Options),
ssl:setopts(Socket, NewValues),
@@ -1219,6 +1430,59 @@ socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
%%--------------------------------------------------------------------
+socket_options() ->
+ [{doc,"Test API function getopts/2 and setopts/2"}].
+
+socket_options(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Values = [{mode, list}, {active, true}],
+ %% Shall be the reverse order of Values!
+ Options = [active, mode],
+
+ NewValues = [{mode, binary}, {active, once}],
+ %% Shall be the reverse order of NewValues!
+ NewOptions = [active, mode],
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, socket_options_result,
+ [Options, Values, NewOptions, NewValues]}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, socket_options_result,
+ [Options, Values, NewOptions, NewValues]}},
+ {options, ClientOpts}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+
+ ssl_test_lib:close(Server),
+
+ {ok, Listen} = ssl:listen(0, ServerOpts),
+ {ok,[{mode,list}]} = ssl:getopts(Listen, [mode]),
+ ok = ssl:setopts(Listen, [{mode, binary}]),
+ {ok,[{mode, binary}]} = ssl:getopts(Listen, [mode]),
+ {ok,[{recbuf, _}]} = ssl:getopts(Listen, [recbuf]),
+ ssl:close(Listen).
+
+
+socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) ->
+ %% Test get/set emulated opts
+ {ok, DefaultValues} = ssl:getopts(Socket, Options),
+ ssl:setopts(Socket, NewValues),
+ {ok, NewValues} = ssl:getopts(Socket, NewOptions),
+ %% Test get/set inet opts
+ {ok,[{reuseaddr, _}]} = ssl:getopts(Socket, [reuseaddr]),
+ {ok, All} = ssl:getopts(Socket, []),
+ ct:log("All opts ~p~n", [All]),
+ ok.
+
+
+%%--------------------------------------------------------------------
invalid_inet_get_option() ->
[{doc,"Test handling of invalid inet options in getopts"}].
@@ -1474,6 +1738,25 @@ versions(Config) when is_list(Config) ->
[_|_] = Versions = ssl:versions(),
ct:log("~p~n", [Versions]).
+
+%%--------------------------------------------------------------------
+eccs() ->
+ [{doc, "Test API functions eccs/0 and eccs/1"}].
+
+eccs(Config) when is_list(Config) ->
+ [_|_] = All = ssl:eccs(),
+ [] = SSL3 = ssl:eccs({3,0}),
+ [_|_] = Tls = ssl:eccs({3,1}),
+ [_|_] = Tls1 = ssl:eccs({3,2}),
+ [_|_] = Tls2 = ssl:eccs({3,3}),
+ [] = SSL3 = ssl:eccs(sslv3),
+ [_|_] = Tls = ssl:eccs(tlsv1),
+ [_|_] = Tls1 = ssl:eccs('tlsv1.1'),
+ [_|_] = Tls2 = ssl:eccs('tlsv1.2'),
+ %% ordering is currently unverified by the test
+ true = lists:sort(All) =:= lists:usort(SSL3 ++ Tls ++ Tls1 ++ Tls2),
+ ok.
+
%%--------------------------------------------------------------------
send_recv() ->
[{doc,""}].
@@ -2113,137 +2396,121 @@ tls_shutdown_error(Config) when is_list(Config) ->
ciphers_rsa_signed_certs() ->
[{doc,"Test all rsa ssl cipher suites in highest support ssl/tls version"}].
-ciphers_rsa_signed_certs(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
+ciphers_rsa_signed_certs(Config) when is_list(Config) ->
Ciphers = ssl_test_lib:rsa_suites(crypto),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, rsa).
+ run_suites(Ciphers, Config, rsa).
%%-------------------------------------------------------------------
ciphers_rsa_signed_certs_openssl_names() ->
[{doc,"Test all rsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_rsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:openssl_rsa_suites(crypto),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, rsa).
+ Ciphers = ssl_test_lib:openssl_rsa_suites(),
+ run_suites(Ciphers, Config, rsa).
%%-------------------------------------------------------------------
ciphers_dsa_signed_certs() ->
[{doc,"Test all dsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_dsa_signed_certs(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:dsa_suites(),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, dsa).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:dsa_suites(NVersion),
+ run_suites(Ciphers, Config, dsa).
%%-------------------------------------------------------------------
ciphers_dsa_signed_certs_openssl_names() ->
[{doc,"Test all dsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_dsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:openssl_dsa_suites(),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, dsa).
+ run_suites(Ciphers, Config, dsa).
%%-------------------------------------------------------------------
anonymous_cipher_suites()->
[{doc,"Test the anonymous ciphersuites"}].
anonymous_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:anonymous_suites(),
- run_suites(Ciphers, Version, Config, anonymous).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(NVersion),
+ run_suites(Ciphers, Config, anonymous).
%%-------------------------------------------------------------------
psk_cipher_suites() ->
[{doc, "Test the PSK ciphersuites WITHOUT server supplied identity hint"}].
psk_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:psk_suites(),
- run_suites(Ciphers, Version, Config, psk).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:psk_suites(NVersion),
+ run_suites(Ciphers, Config, psk).
%%-------------------------------------------------------------------
psk_with_hint_cipher_suites()->
[{doc, "Test the PSK ciphersuites WITH server supplied identity hint"}].
psk_with_hint_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:psk_suites(),
- run_suites(Ciphers, Version, Config, psk_with_hint).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:psk_suites(NVersion),
+ run_suites(Ciphers, Config, psk_with_hint).
%%-------------------------------------------------------------------
psk_anon_cipher_suites() ->
[{doc, "Test the anonymous PSK ciphersuites WITHOUT server supplied identity hint"}].
psk_anon_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:psk_anon_suites(),
- run_suites(Ciphers, Version, Config, psk_anon).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:psk_anon_suites(NVersion),
+ run_suites(Ciphers, Config, psk_anon).
%%-------------------------------------------------------------------
psk_anon_with_hint_cipher_suites()->
[{doc, "Test the anonymous PSK ciphersuites WITH server supplied identity hint"}].
psk_anon_with_hint_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:psk_anon_suites(),
- run_suites(Ciphers, Version, Config, psk_anon_with_hint).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:psk_anon_suites(NVersion),
+ run_suites(Ciphers, Config, psk_anon_with_hint).
%%-------------------------------------------------------------------
srp_cipher_suites()->
[{doc, "Test the SRP ciphersuites"}].
srp_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:srp_suites(),
- run_suites(Ciphers, Version, Config, srp).
+ run_suites(Ciphers, Config, srp).
%%-------------------------------------------------------------------
srp_anon_cipher_suites()->
[{doc, "Test the anonymous SRP ciphersuites"}].
srp_anon_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:srp_anon_suites(),
- run_suites(Ciphers, Version, Config, srp_anon).
+ run_suites(Ciphers, Config, srp_anon).
%%-------------------------------------------------------------------
srp_dsa_cipher_suites()->
[{doc, "Test the SRP DSA ciphersuites"}].
srp_dsa_cipher_suites(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:srp_dss_suites(),
- run_suites(Ciphers, Version, Config, srp_dsa).
+ run_suites(Ciphers, Config, srp_dsa).
%%-------------------------------------------------------------------
rc4_rsa_cipher_suites()->
[{doc, "Test the RC4 ciphersuites"}].
rc4_rsa_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
- Ciphers = ssl_test_lib:rc4_suites(NVersion),
- run_suites(Ciphers, Version, Config, rc4_rsa).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = [S || {rsa,_,_} = S <- ssl_test_lib:rc4_suites(NVersion)],
+ run_suites(Ciphers, Config, rc4_rsa).
%-------------------------------------------------------------------
rc4_ecdh_rsa_cipher_suites()->
[{doc, "Test the RC4 ciphersuites"}].
rc4_ecdh_rsa_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
- Ciphers = ssl_test_lib:rc4_suites(NVersion),
- run_suites(Ciphers, Version, Config, rc4_ecdh_rsa).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = [S || {ecdh_rsa,_,_} = S <- ssl_test_lib:rc4_suites(NVersion)],
+ run_suites(Ciphers, Config, rc4_ecdh_rsa).
%%-------------------------------------------------------------------
rc4_ecdsa_cipher_suites()->
[{doc, "Test the RC4 ciphersuites"}].
rc4_ecdsa_cipher_suites(Config) when is_list(Config) ->
NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
- Ciphers = ssl_test_lib:rc4_suites(NVersion),
- run_suites(Ciphers, Version, Config, rc4_ecdsa).
+ Ciphers = [S || {ecdhe_ecdsa,_,_} = S <- ssl_test_lib:rc4_suites(NVersion)],
+ run_suites(Ciphers, Config, rc4_ecdsa).
%%-------------------------------------------------------------------
des_rsa_cipher_suites()->
- [{doc, "Test the RC4 ciphersuites"}].
+ [{doc, "Test the des_rsa ciphersuites"}].
des_rsa_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
- Ciphers = ssl_test_lib:des_suites(NVersion),
- run_suites(Ciphers, Version, Config, des_rsa).
+ Ciphers = ssl_test_lib:des_suites(Config),
+ run_suites(Ciphers, Config, des_rsa).
%-------------------------------------------------------------------
des_ecdh_rsa_cipher_suites()->
- [{doc, "Test the RC4 ciphersuites"}].
+ [{doc, "Test ECDH rsa signed ciphersuites"}].
des_ecdh_rsa_cipher_suites(Config) when is_list(Config) ->
- NVersion = tls_record:highest_protocol_version([]),
- Version = tls_record:protocol_version(NVersion),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:des_suites(NVersion),
- run_suites(Ciphers, Version, Config, des_dhe_rsa).
+ run_suites(Ciphers, Config, des_dhe_rsa).
%%--------------------------------------------------------------------
default_reject_anonymous()->
@@ -2252,9 +2519,11 @@ default_reject_anonymous(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
-
- [Cipher | _] = ssl_test_lib:anonymous_suites(),
-
+ Version = ssl_test_lib:protocol_version(Config),
+ TLSVersion = ssl_test_lib:tls_version(Version),
+
+ [CipherSuite | _] = ssl_test_lib:ecdh_dh_anonymous_suites(TLSVersion),
+
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
{options, ServerOpts}]),
@@ -2263,7 +2532,7 @@ default_reject_anonymous(Config) when is_list(Config) ->
{host, Hostname},
{from, self()},
{options,
- [{ciphers,[Cipher]} |
+ [{ciphers,[CipherSuite]} |
ClientOpts]}]),
ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}},
@@ -2274,37 +2543,31 @@ ciphers_ecdsa_signed_certs() ->
[{doc, "Test all ecdsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_ecdsa_signed_certs(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:ecdsa_suites(),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, ecdsa).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:ecdsa_suites(NVersion),
+ run_suites(Ciphers, Config, ecdsa).
%%--------------------------------------------------------------------
ciphers_ecdsa_signed_certs_openssl_names() ->
[{doc, "Test all ecdsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_ecdsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:openssl_ecdsa_suites(),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, ecdsa).
+ run_suites(Ciphers, Config, ecdsa).
%%--------------------------------------------------------------------
ciphers_ecdh_rsa_signed_certs() ->
[{doc, "Test all ecdh_rsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_ecdh_rsa_signed_certs(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:ecdh_rsa_suites(),
- ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
- run_suites(Ciphers, Version, Config, ecdh_rsa).
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:ecdh_rsa_suites(NVersion),
+ run_suites(Ciphers, Config, ecdh_rsa).
%%--------------------------------------------------------------------
ciphers_ecdh_rsa_signed_certs_openssl_names() ->
[{doc, "Test all ecdh_rsa ssl cipher suites in highest support ssl/tls version"}].
ciphers_ecdh_rsa_signed_certs_openssl_names(Config) when is_list(Config) ->
- Version = ssl_test_lib:protocol_version(Config),
Ciphers = ssl_test_lib:openssl_ecdh_rsa_suites(),
- ct:log("tls1 openssl cipher suites ~p~n", [Ciphers]),
- run_suites(Ciphers, Version, Config, ecdh_rsa).
+ run_suites(Ciphers, Config, ecdh_rsa).
%%--------------------------------------------------------------------
reuse_session() ->
[{doc,"Test reuse of sessions (short handshake)"}].
@@ -2775,10 +3038,10 @@ der_input(Config) when is_list(Config) ->
Size = ets:info(CADb, size),
- SeverVerifyOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ SeverVerifyOpts = ssl_test_lib:ssl_options(server_opts, Config),
{ServerCert, ServerKey, ServerCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
SeverVerifyOpts]),
- ClientVerifyOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ClientVerifyOpts = ssl_test_lib:ssl_options(client_opts, Config),
{ClientCert, ClientKey, ClientCaCerts, DHParams} = der_input_opts([{dhfile, DHParamFile} |
ClientVerifyOpts]),
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true},
@@ -2821,37 +3084,6 @@ der_input_opts(Opts) ->
{Cert, {Asn1Type, Key}, CaCerts, DHParams}.
%%--------------------------------------------------------------------
-%% different_ca_peer_sign() ->
-%% ["Check that a CA can have a different signature algorithm than the peer cert."];
-
-%% different_ca_peer_sign(Config) when is_list(Config) ->
-%% ClientOpts = ssl_test_lib:ssl_options(client_mix_opts, Config),
-%% ServerOpts = ssl_test_lib:ssl_options(server_mix_verify_opts, Config),
-
-%% {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-%% Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
-%% {from, self()},
-%% {mfa, {ssl_test_lib, send_recv_result_active_once, []}},
-%% {options, [{active, once},
-%% {verify, verify_peer} | ServerOpts]}]),
-%% Port = ssl_test_lib:inet_port(Server),
-
-%% Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
-%% {host, Hostname},
-%% {from, self()},
-%% {mfa, {ssl_test_lib,
-%% send_recv_result_active_once,
-%% []}},
-%% {options, [{active, once},
-%% {verify, verify_peer}
-%% | ClientOpts]}]),
-
-%% ssl_test_lib:check_result(Server, ok, Client, ok),
-%% ssl_test_lib:close(Server),
-%% ssl_test_lib:close(Client).
-
-
-%%--------------------------------------------------------------------
no_reuses_session_server_restart_new_cert() ->
[{doc,"Check that a session is not reused if the server is restarted with a new cert."}].
no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
@@ -2919,14 +3151,14 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
DsaServerOpts = ssl_test_lib:ssl_options(server_dsa_opts, Config),
PrivDir = proplists:get_value(priv_dir, Config),
- NewServerOpts = new_config(PrivDir, ServerOpts),
+ NewServerOpts0 = new_config(PrivDir, ServerOpts),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, session_info_result, []}},
- {options, NewServerOpts}]),
+ {options, NewServerOpts0}]),
Port = ssl_test_lib:inet_port(Server),
Client0 =
ssl_test_lib:start_client([{node, ClientNode},
@@ -2947,13 +3179,13 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ssl:clear_pem_cache(),
- NewServerOpts = new_config(PrivDir, DsaServerOpts),
+ NewServerOpts1 = new_config(PrivDir, DsaServerOpts),
Server1 =
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, NewServerOpts}]),
+ {options, NewServerOpts1}]),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
@@ -3265,11 +3497,11 @@ hibernate(Config) ->
process_info(Pid, current_function),
ssl_test_lib:check_result(Server, ok, Client, ok),
- timer:sleep(1100),
-
+
+ timer:sleep(1500),
{current_function, {erlang, hibernate, 3}} =
process_info(Pid, current_function),
-
+
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
@@ -3302,13 +3534,12 @@ hibernate_right_away(Config) ->
[{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]),
ssl_test_lib:check_result(Server1, ok, Client1, ok),
-
- {current_function, {erlang, hibernate, 3}} =
+
+ {current_function, {erlang, hibernate, 3}} =
process_info(Pid1, current_function),
-
ssl_test_lib:close(Server1),
ssl_test_lib:close(Client1),
-
+
Server2 = ssl_test_lib:start_server(StartServerOpts),
Port2 = ssl_test_lib:inet_port(Server2),
{Client2, #sslsocket{pid = Pid2}} = ssl_test_lib:start_client(StartClientOpts ++
@@ -3316,8 +3547,8 @@ hibernate_right_away(Config) ->
ssl_test_lib:check_result(Server2, ok, Client2, ok),
- ct:sleep(100), %% Schedule out
-
+ ct:sleep(1000), %% Schedule out
+
{current_function, {erlang, hibernate, 3}} =
process_info(Pid2, current_function),
@@ -3343,7 +3574,6 @@ listen_socket(Config) ->
{error, enotconn} = ssl:connection_information(ListenSocket),
{error, enotconn} = ssl:peername(ListenSocket),
{error, enotconn} = ssl:peercert(ListenSocket),
- {error, enotconn} = ssl:session_info(ListenSocket),
{error, enotconn} = ssl:renegotiate(ListenSocket),
{error, enotconn} = ssl:prf(ListenSocket, 'master_secret', <<"Label">>, client_random, 256),
{error, enotconn} = ssl:shutdown(ListenSocket, read_write),
@@ -3594,9 +3824,23 @@ rizzo() ->
vunrable to Rizzo/Dungon attack"}].
rizzo(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(all, NVersion),
+ [{key_exchange,
+ fun(Alg) when Alg == ecdh_rsa; Alg == ecdhe_rsa->
+ true;
+ (_) ->
+ false
+ end},
+ {cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]),
+
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_rizzo, []}).
%%--------------------------------------------------------------------
@@ -3604,9 +3848,17 @@ no_rizzo_rc4() ->
[{doc,"Test that there is no 1/n-1-split for RC4 as it is not vunrable to Rizzo/Dungon attack"}].
no_rizzo_rc4(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(),Y == rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ %% Test uses RSA certs
+ Ciphers = ssl:filter_cipher_suites(ssl_test_lib:rc4_suites(NVersion),
+ [{key_exchange,
+ fun(Alg) when Alg == ecdh_rsa; Alg == ecdhe_rsa->
+ true;
+ (_) ->
+ false
+ end}]),
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_no_rizzo, []}).
@@ -3614,19 +3866,39 @@ rizzo_one_n_minus_one() ->
[{doc,"Test that the 1/n-1-split mitigation of Rizzo/Dungon attack can be explicitly selected"}].
rizzo_one_n_minus_one(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(all, NVersion),
+ [{key_exchange,
+ fun(Alg) when Alg == ecdh_rsa; Alg == ecdhe_rsa->
+ true;
+ (_) ->
+ false
+ end},
+ {cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]),
run_send_recv_rizzo(Ciphers, Config, Version,
- {?MODULE, send_recv_result_active_rizzo, []}).
+ {?MODULE, send_recv_result_active_rizzo, []}).
rizzo_zero_n() ->
[{doc,"Test that the 0/n-split mitigation of Rizzo/Dungon attack can be explicitly selected"}].
rizzo_zero_n(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, NVersion),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]),
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_no_rizzo, []}).
@@ -3634,9 +3906,16 @@ rizzo_disabled() ->
[{doc,"Test that the mitigation of Rizzo/Dungon attack can be explicitly disabled"}].
rizzo_disabled(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, NVersion),
+ [{cipher,
+ fun(rc4_128) ->
+ false;
+ (_) ->
+ true
+ end}]),
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_no_rizzo, []}).
@@ -3757,17 +4036,16 @@ unordered_protocol_versions_server(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ClientOpts}]),
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+ ServerMsg = ClientMsg = {ok,'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
@@ -3782,21 +4060,42 @@ unordered_protocol_versions_client(Config) when is_list(Config) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, ServerOpts }]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {mfa, {?MODULE, connection_info_result, []}},
+ {mfa, {?MODULE, protocol_info_result, []}},
{options, [{versions, ['tlsv1.1', 'tlsv1.2']} | ClientOpts]}]),
-
- CipherSuite = first_rsa_suite(ssl:cipher_suites()),
- ServerMsg = ClientMsg = {ok, {'tlsv1.2', CipherSuite}},
+ ServerMsg = ClientMsg = {ok, 'tlsv1.2'},
ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg).
%%--------------------------------------------------------------------
+max_handshake_size() ->
+ [{doc,"Test that we can set max_handshake_size to max value."}].
+
+max_handshake_size(Config) when is_list(Config) ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{max_handshake_size, 8388607} |ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{max_handshake_size, 8388607} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok).
+
+%%--------------------------------------------------------------------
server_name_indication_option() ->
[{doc,"Test API server_name_indication option to connect."}].
@@ -3943,11 +4242,11 @@ prf_create_plan(TlsVersions, PRFs, Results) ->
prf_ciphers_and_expected(TlsVer, PRFs, Results) ->
case TlsVer of
TlsVer when TlsVer == sslv3 orelse TlsVer == tlsv1
- orelse TlsVer == 'tlsv1.1' ->
+ orelse TlsVer == 'tlsv1.1' orelse TlsVer == 'dtlsv1' ->
Ciphers = ssl:cipher_suites(),
{_, Expected} = lists:keyfind(md5sha, 1, Results),
[[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected}, {prf, md5sha}]];
- 'tlsv1.2' ->
+ TlsVer when TlsVer == 'tlsv1.2' orelse TlsVer == 'dtlsv1.2'->
lists:foldl(
fun(PRF, Acc) ->
Ciphers = prf_get_ciphers(TlsVer, PRF),
@@ -3962,21 +4261,20 @@ prf_ciphers_and_expected(TlsVer, PRFs, Results) ->
end
end, [], PRFs)
end.
-prf_get_ciphers(TlsVer, PRF) ->
- case TlsVer of
- 'tlsv1.2' ->
- lists:filter(
- fun(C) when tuple_size(C) == 4 andalso
- element(4, C) == PRF ->
- true;
- (_) -> false
- end, ssl:cipher_suites())
- end.
+prf_get_ciphers(_, PRF) ->
+ lists:filter(
+ fun(C) when tuple_size(C) == 4 andalso
+ element(4, C) == PRF ->
+ true;
+ (_) ->
+ false
+ end,
+ ssl:cipher_suites()).
prf_run_test(_, TlsVer, [], _, Prf) ->
ct:fail({error, cipher_list_empty, TlsVer, Prf});
prf_run_test(Config, TlsVer, Ciphers, Expected, Prf) ->
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- BaseOpts = [{active, true}, {versions, [TlsVer]}, {ciphers, Ciphers}],
+ BaseOpts = [{active, true}, {versions, [TlsVer]}, {ciphers, Ciphers}, {protocol, tls_or_dtls(TlsVer)}],
ServerOpts = BaseOpts ++ proplists:get_value(server_opts, Config),
ClientOpts = BaseOpts ++ proplists:get_value(client_opts, Config),
Server = ssl_test_lib:start_server(
@@ -4288,7 +4586,7 @@ erlang_ssl_receive(Socket, Data) ->
erlang_ssl_receive(Socket, tl(Data));
Other ->
ct:fail({unexpected_message, Other})
- after ?SLEEP * 3 * test_server:timetrap_scale_factor() ->
+ after timer:seconds(?SEC_RENEGOTIATION_TIMEOUT) * test_server:timetrap_scale_factor() ->
ct:fail({did_not_get, Data})
end.
@@ -4377,7 +4675,7 @@ rizzo_test(Cipher, Config, Version, Mfa) ->
{host, Hostname},
{from, self()},
{mfa, Mfa},
- {options, [{active, true} | ClientOpts]}]),
+ {options, [{active, true}, {ciphers, [Cipher]}| ClientOpts]}]),
Result = ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
@@ -4389,47 +4687,59 @@ rizzo_test(Cipher, Config, Version, Mfa) ->
[{Cipher, Error}]
end.
-client_server_opts({KeyAlgo,_,_}, Config)
+client_server_opts(#{key_exchange := KeyAlgo}, Config)
when KeyAlgo == rsa orelse
KeyAlgo == dhe_rsa orelse
- KeyAlgo == ecdhe_rsa ->
+ KeyAlgo == ecdhe_rsa orelse
+ KeyAlgo == rsa_psk orelse
+ KeyAlgo == srp_rsa ->
{ssl_test_lib:ssl_options(client_opts, Config),
ssl_test_lib:ssl_options(server_opts, Config)};
-client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss ->
+client_server_opts(#{key_exchange := KeyAlgo}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss ->
{ssl_test_lib:ssl_options(client_dsa_opts, Config),
ssl_test_lib:ssl_options(server_dsa_opts, Config)};
-client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == ecdh_ecdsa orelse KeyAlgo == ecdhe_ecdsa ->
+client_server_opts(#{key_exchange := KeyAlgo}, Config) when KeyAlgo == ecdh_ecdsa orelse KeyAlgo == ecdhe_ecdsa ->
{ssl_test_lib:ssl_options(client_opts, Config),
ssl_test_lib:ssl_options(server_ecdsa_opts, Config)};
-client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == ecdh_rsa ->
+client_server_opts(#{key_exchange := KeyAlgo}, Config) when KeyAlgo == ecdh_rsa ->
{ssl_test_lib:ssl_options(client_opts, Config),
ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)}.
-run_suites(Ciphers, Version, Config, Type) ->
+run_suites(Ciphers, Config, Type) ->
+ Version = ssl_test_lib:protocol_version(Config),
+ ct:log("Running cipher suites ~p~n", [Ciphers]),
{ClientOpts, ServerOpts} =
case Type of
rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_opts, Config)};
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
dsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_dsa_opts, Config)};
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_dsa_opts, Config)]};
anonymous ->
%% No certs in opts!
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_anon, Config)};
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options([], Config)]};
psk ->
{ssl_test_lib:ssl_options(client_psk, Config),
- ssl_test_lib:ssl_options(server_psk, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_psk, Config)]};
psk_with_hint ->
{ssl_test_lib:ssl_options(client_psk, Config),
- ssl_test_lib:ssl_options(server_psk_hint, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_psk_hint, Config)
+ ]};
psk_anon ->
{ssl_test_lib:ssl_options(client_psk, Config),
- ssl_test_lib:ssl_options(server_psk_anon, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_psk_anon, Config)]};
psk_anon_with_hint ->
{ssl_test_lib:ssl_options(client_psk, Config),
- ssl_test_lib:ssl_options(server_psk_anon_hint, Config)};
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_psk_anon_hint, Config)]};
srp ->
{ssl_test_lib:ssl_options(client_srp, Config),
ssl_test_lib:ssl_options(server_srp, Config)};
@@ -4440,36 +4750,45 @@ run_suites(Ciphers, Version, Config, Type) ->
{ssl_test_lib:ssl_options(client_srp_dsa, Config),
ssl_test_lib:ssl_options(server_srp_dsa, Config)};
ecdsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_ecdsa_opts, Config)};
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]};
ecdh_rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)};
rc4_rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_opts, Config)]};
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
rc4_ecdh_rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdh_rsa_opts, Config)]};
rc4_ecdsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]};
des_dhe_rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_opts, Config)]};
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
des_rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
[{ciphers, Ciphers} |
- ssl_test_lib:ssl_options(server_opts, Config)]}
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ chacha_rsa ->
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_verification_opts, Config)]};
+ chacha_ecdsa ->
+ {ssl_test_lib:ssl_options(client_verification_opts, Config),
+ [{ciphers, Ciphers} |
+ ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]}
end,
-
+ ct:pal("ssl_test_lib:filter_suites(~p ~p) -> ~p ", [Ciphers, Version, ssl_test_lib:filter_suites(Ciphers, Version)]),
Result = lists:map(fun(Cipher) ->
cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
- ssl_test_lib:filter_suites(Ciphers)),
+ ssl_test_lib:filter_suites(Ciphers, Version)),
case lists:flatten(Result) of
[] ->
ok;
@@ -4477,7 +4796,6 @@ run_suites(Ciphers, Version, Config, Type) ->
ct:log("Cipher suite errors: ~p~n", [Error]),
ct:fail(cipher_suite_failed_see_test_case_log)
end.
-
erlang_cipher_suite(Suite) when is_list(Suite)->
ssl_cipher:erl_suite_definition(ssl_cipher:openssl_suite(Suite));
erlang_cipher_suite(Suite) ->
@@ -4533,10 +4851,20 @@ connection_information_result(Socket) ->
connection_info_result(Socket) ->
{ok, Info} = ssl:connection_information(Socket, [protocol, cipher_suite]),
{ok, {proplists:get_value(protocol, Info), proplists:get_value(cipher_suite, Info)}}.
+
+protocol_info_result(Socket) ->
+ {ok, [{protocol, PVersion}]} = ssl:connection_information(Socket, [protocol]),
+ {ok, PVersion}.
+
version_info_result(Socket) ->
{ok, [{version, Version}]} = ssl:connection_information(Socket, [version]),
{ok, Version}.
+secret_connection_info_result(Socket) ->
+ {ok, [{client_random, ClientRand}, {server_random, ServerRand}, {master_secret, MasterSecret}]}
+ = ssl:connection_information(Socket, [client_random, server_random, master_secret]),
+ is_binary(ClientRand) andalso is_binary(ServerRand) andalso is_binary(MasterSecret).
+
connect_dist_s(S) ->
Msg = term_to_binary({erlang,term}),
ok = ssl:send(S, Msg).
@@ -4650,21 +4978,13 @@ try_recv_active_once(Socket) ->
{error, einval} = ssl:recv(Socket, 11),
ok.
-first_rsa_suite([{ecdhe_rsa, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{ecdhe_rsa, _, _, _} = Suite | _]) ->
- Suite;
-first_rsa_suite([{dhe_rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([{rsa, _, _, _} = Suite| _]) ->
- Suite;
-first_rsa_suite([_ | Rest]) ->
- first_rsa_suite(Rest).
-
wait_for_send(Socket) ->
%% Make sure TLS process processed send message event
_ = ssl:connection_information(Socket).
+
+tls_or_dtls('dtlsv1') ->
+ dtls;
+tls_or_dtls('dtlsv1.2') ->
+ dtls;
+tls_or_dtls(_) ->
+ tls.
diff --git a/lib/ssl/test/ssl_bench_SUITE.erl b/lib/ssl/test/ssl_bench_SUITE.erl
index ed439a425f..ae2928b1c3 100644
--- a/lib/ssl/test/ssl_bench_SUITE.erl
+++ b/lib/ssl/test/ssl_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,11 +25,12 @@
suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}].
-all() -> [{group, setup}, {group, payload}].
+all() -> [{group, setup}, {group, payload}, {group, pem_cache}].
groups() ->
[{setup, [{repeat, 3}], [setup_sequential, setup_concurrent]},
- {payload, [{repeat, 3}], [payload_simple]}
+ {payload, [{repeat, 3}], [payload_simple]},
+ {pem_cache, [{repeat, 3}], [use_pem_cache, bypass_pem_cache]}
].
init_per_group(_GroupName, Config) ->
@@ -49,9 +50,33 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
ok.
+init_per_testcase(use_pem_cache, Conf) ->
+ case bypass_pem_cache_supported() of
+ false -> {skipped, "PEM cache bypass support required"};
+ true ->
+ application:set_env(ssl, bypass_pem_cache, false),
+ Conf
+ end;
+init_per_testcase(bypass_pem_cache, Conf) ->
+ case bypass_pem_cache_supported() of
+ false -> {skipped, "PEM cache bypass support required"};
+ true ->
+ application:set_env(ssl, bypass_pem_cache, true),
+ Conf
+ end;
init_per_testcase(_Func, Conf) ->
Conf.
+end_per_testcase(use_pem_cache, _Config) ->
+ case bypass_pem_cache_supported() of
+ false -> ok;
+ true -> application:set_env(ssl, bypass_pem_cache, false)
+ end;
+end_per_testcase(bypass_pem_cache, _Config) ->
+ case bypass_pem_cache_supported() of
+ false -> ok;
+ true -> application:set_env(ssl, bypass_pem_cache, false)
+ end;
end_per_testcase(_Func, _Conf) ->
ok.
@@ -63,7 +88,6 @@ end_per_testcase(_Func, _Conf) ->
-define(FPROF_SERVER, false).
-define(EPROF_CLIENT, false).
-define(EPROF_SERVER, false).
--define(PERCEPT_SERVER, false).
%% Current numbers gives roughly a testcase per minute on todays hardware..
@@ -94,6 +118,18 @@ payload_simple(Config) ->
{suite, "ssl"}, {name, "Payload simple"}]}),
ok.
+use_pem_cache(_Config) ->
+ {ok, Result} = do_test(ssl, pem_cache, 100, 500, node()),
+ ct_event:notify(#event{name = benchmark_data,
+ data=[{value, Result},
+ {suite, "ssl"}, {name, "Use PEM cache"}]}).
+
+bypass_pem_cache(_Config) ->
+ {ok, Result} = do_test(ssl, pem_cache, 100, 500, node()),
+ ct_event:notify(#event{name = benchmark_data,
+ data=[{value, Result},
+ {suite, "ssl"}, {name, "Bypass PEM cache"}]}).
+
ssl() ->
test(ssl, ?COUNT, node()).
@@ -153,7 +189,6 @@ server_init(ssl, setup_connection, _, _, Server) ->
?FPROF_SERVER andalso start_profile(fprof, [whereis(ssl_manager), new]),
%%?EPROF_SERVER andalso start_profile(eprof, [ssl_connection_sup, ssl_manager]),
?EPROF_SERVER andalso start_profile(eprof, [ssl_manager]),
- ?PERCEPT_SERVER andalso percept:profile("/tmp/ssl_server.percept"),
Server ! {self(), {init, Host, Port}},
Test = fun(TSocket) ->
ok = ssl:ssl_accept(TSocket),
@@ -172,6 +207,18 @@ server_init(ssl, payload, Loop, _, Server) ->
ssl:close(TSocket)
end,
setup_server_connection(Socket, Test);
+server_init(ssl, pem_cache, Loop, _, Server) ->
+ {ok, Socket} = ssl:listen(0, ssl_opts(listen_der)),
+ {ok, {_Host, Port}} = ssl:sockname(Socket),
+ {ok, Host} = inet:gethostname(),
+ Server ! {self(), {init, Host, Port}},
+ Test = fun(TSocket) ->
+ ok = ssl:ssl_accept(TSocket),
+ Size = byte_size(msg()),
+ server_echo(TSocket, Size, Loop),
+ ssl:close(TSocket)
+ end,
+ setup_server_connection(Socket, Test);
server_init(Type, Tc, _, _, Server) ->
io:format("No server init code for ~p ~p~n",[Type, Tc]),
@@ -185,6 +232,11 @@ client_init(Master, ssl, payload, Host, Port) ->
Master ! {self(), init},
Size = byte_size(msg()),
{Sock, Size};
+client_init(Master, ssl, pem_cache, Host, Port) ->
+ {ok, Sock} = ssl:connect(Host, Port, ssl_opts(connect_der)),
+ Master ! {self(), init},
+ Size = byte_size(msg()),
+ {Sock, Size};
client_init(_Me, Type, Tc, Host, Port) ->
io:format("No client init code for ~p ~p~n",[Type, Tc]),
{Host, Port}.
@@ -193,7 +245,6 @@ setup_server_connection(LSocket, Test) ->
receive quit ->
?FPROF_SERVER andalso stop_profile(fprof, "test_server_res.fprof"),
?EPROF_SERVER andalso stop_profile(eprof, "test_server_res.eprof"),
- ?PERCEPT_SERVER andalso stop_profile(percept, "/tmp/ssl_server.percept"),
ok
after 0 ->
case ssl:transport_accept(LSocket, 2000) of
@@ -228,6 +279,13 @@ payload(Loop, ssl, D = {Socket, Size}) when Loop > 0 ->
payload(_, _, {Socket, _}) ->
ssl:close(Socket).
+pem_cache(N, ssl, Data = {Socket, Size}) when N > 0 ->
+ ok = ssl:send(Socket, msg()),
+ {ok, _} = ssl:recv(Socket, Size),
+ pem_cache(N-1, ssl, Data);
+pem_cache(_, _, {Socket, _}) ->
+ ssl:close(Socket).
+
msg() ->
<<"Hello",
0:(512*8),
@@ -327,13 +385,6 @@ start_profile(fprof, Procs) ->
fprof:trace([start, {procs, Procs}]),
io:format("(F)Profiling ...",[]).
-stop_profile(percept, File) ->
- percept:stop_profile(),
- percept:analyze(File),
- {started, _Host, Port} = percept:start_webserver(),
- wx:new(),
- wx_misc:launchDefaultBrowser("http://" ++ net_adm:localhost() ++ ":" ++ integer_to_list(Port)),
- ok;
stop_profile(eprof, File) ->
profiling_stopped = eprof:stop_profiling(),
eprof:log(File),
@@ -352,16 +403,49 @@ stop_profile(fprof, File) ->
ssl_opts(listen) ->
[{backlog, 500} | ssl_opts("server")];
ssl_opts(connect) ->
- [{verify, verify_peer}
- | ssl_opts("client")];
+ [{verify, verify_peer} | ssl_opts("client")];
+ssl_opts(listen_der) ->
+ [{backlog, 500} | ssl_opts("server_der")];
+ssl_opts(connect_der) ->
+ [{verify, verify_peer} | ssl_opts("client_der")];
ssl_opts(Role) ->
+ CertData = cert_data(Role),
+ Opts = [{active, false},
+ {depth, 2},
+ {reuseaddr, true},
+ {mode,binary},
+ {nodelay, true},
+ {ciphers, [{dhe_rsa,aes_256_cbc,sha}]}
+ |CertData],
+ case Role of
+ "client" ++ _ ->
+ [{server_name_indication, disable} | Opts];
+ "server" ++ _ ->
+ Opts
+ end.
+
+cert_data(Der) when Der =:= "server_der"; Der =:= "client_der" ->
+ [Role,_] = string:tokens(Der, "_"),
Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
- [{active, false},
- {depth, 2},
- {reuseaddr, true},
- {mode,binary},
- {nodelay, true},
- {ciphers, [{dhe_rsa,aes_256_cbc,sha}]},
- {cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
+ {ok, CaCert0} = file:read_file(filename:join([Dir, Role, "cacerts.pem"])),
+ {ok, Cert0} = file:read_file(filename:join([Dir, Role, "cert.pem"])),
+ {ok, Key0} = file:read_file(filename:join([Dir, Role, "key.pem"])),
+ [{_, Cert, _}] = public_key:pem_decode(Cert0),
+ CaCert1 = public_key:pem_decode(CaCert0),
+ CaCert = [CCert || {_, CCert, _} <- CaCert1],
+ [{KeyType, Key, _}] = public_key:pem_decode(Key0),
+ [{cert, Cert},
+ {cacerts, CaCert},
+ {key, {KeyType, Key}}];
+cert_data(Role) ->
+ Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
+ [{cacertfile, filename:join([Dir, Role, "cacerts.pem"])},
{certfile, filename:join([Dir, Role, "cert.pem"])},
{keyfile, filename:join([Dir, Role, "key.pem"])}].
+
+bypass_pem_cache_supported() ->
+ %% This function is currently critical to support cache bypass
+ %% and did not exist in prior versions.
+ catch ssl_pkix_db:module_info(), % ensure module is loaded
+ erlang:function_exported(ssl_pkix_db, extract_trusted_certs, 1).
+
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 20165c70f0..1de4c89d7f 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -39,23 +39,41 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() ->
- [{group, active},
- {group, passive},
- {group, active_once},
- {group, error_handling}].
-
+ [
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
groups() ->
- [{active, [], tests()},
+ [
+ {'tlsv1.2', [], all_protocol_groups()},
+ {'tlsv1.1', [], all_protocol_groups()},
+ {'tlsv1', [], all_protocol_groups()},
+ {'sslv3', [], all_protocol_groups()},
+ {'dtlsv1.2', [], all_protocol_groups()},
+ {'dtlsv1', [], all_protocol_groups()},
+ {active, [], tests()},
{active_once, [], tests()},
{passive, [], tests()},
- {error_handling, [],error_handling_tests()}].
+ {error_handling, [],error_handling_tests()}
+ ].
+
+all_protocol_groups() ->
+ [{group, active},
+ {group, passive},
+ {group, active_once},
+ {group, error_handling}].
tests() ->
[verify_peer,
verify_none,
server_require_peer_cert_ok,
server_require_peer_cert_fail,
+ server_require_peer_cert_empty_ok,
server_require_peer_cert_partial_chain,
server_require_peer_cert_allow_partial_chain,
server_require_peer_cert_do_not_allow_partial_chain,
@@ -65,9 +83,10 @@ tests() ->
cert_expired,
invalid_signature_client,
invalid_signature_server,
- extended_key_usage_verify_peer,
- extended_key_usage_verify_none,
- critical_extension_verify_peer,
+ extended_key_usage_verify_both,
+ extended_key_usage_verify_server,
+ critical_extension_verify_client,
+ critical_extension_verify_server,
critical_extension_verify_none].
error_handling_tests()->
@@ -78,18 +97,14 @@ error_handling_tests()->
unknown_server_ca_accept_verify_peer,
unknown_server_ca_accept_backwardscompatibility,
no_authority_key_identifier,
- no_authority_key_identifier_and_nonstandard_encoding].
+ no_authority_key_identifier_keyEncipherment].
-init_per_suite(Config0) ->
+init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
- %% make rsa certs using oppenssl
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- Config = ssl_test_lib:make_dsa_cert(Config0),
- ssl_test_lib:cert_options(Config)
+ ssl_test_lib:clean_start(),
+ ssl_test_lib:make_rsa_cert(Config)
catch _:_ ->
{skip, "Crypto did not start"}
end.
@@ -99,31 +114,37 @@ end_per_suite(_Config) ->
application:stop(crypto).
init_per_group(active, Config) ->
- [{active, true}, {receive_function, send_recv_result_active} | Config];
+ [{active, true}, {receive_function, send_recv_result_active} | Config];
init_per_group(active_once, Config) ->
- [{active, once}, {receive_function, send_recv_result_active_once} | Config];
+ [{active, once}, {receive_function, send_recv_result_active_once} | Config];
init_per_group(passive, Config) ->
- [{active, false}, {receive_function, send_recv_result} | Config];
-init_per_group(_, Config) ->
- Config.
+ [{active, false}, {receive_function, send_recv_result} | Config];
+init_per_group(error_handling, Config) ->
+ [{active, false}, {receive_function, send_recv_result} | Config];
+init_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:sufficient_crypto_support(GroupName) of
+ true ->
+ [{version, GroupName} | ssl_test_lib:init_tls_version(GroupName, Config)];
+ false ->
+ {skip, "Missing crypto support"}
+ end
+ end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
-init_per_testcase(TestCase, Config) when TestCase == cert_expired;
- TestCase == invalid_signature_client;
- TestCase == invalid_signature_server;
- TestCase == extended_key_usage_verify_none;
- TestCase == extended_key_usage_verify_peer;
- TestCase == critical_extension_verify_none;
- TestCase == critical_extension_verify_peer;
- TestCase == no_authority_key_identifier;
- TestCase == no_authority_key_identifier_and_nonstandard_encoding->
- ssl:clear_pem_cache(),
- init_per_testcase(common, Config);
init_per_testcase(_TestCase, Config) ->
+ ssl:stop(),
+ ssl:start(),
ssl_test_lib:ct_log_supported_protocol_versions(Config),
- ct:timetrap({seconds, 5}),
+ ct:timetrap({seconds, 10}),
Config.
end_per_testcase(_TestCase, Config) ->
@@ -136,23 +157,23 @@ end_per_testcase(_TestCase, Config) ->
verify_peer() ->
[{doc,"Test option verify_peer"}].
verify_peer(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{active, Active}, {verify, verify_peer}
- | ServerOpts]}]),
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active}, {verify, verify_peer}
+ | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{active, Active} | ClientOpts]}]),
-
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active}, {verify, verify_peer} | ClientOpts]}]),
+
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
@@ -162,23 +183,24 @@ verify_none() ->
[{doc,"Test option verify_none"}].
verify_none(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
- {mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{active, Active}, {verify, verify_none}
- | ServerOpts]}]),
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active}, {verify, verify_none}
+ | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
- {from, self()},
- {mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{active, Active} | ClientOpts]}]),
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active},
+ {verify, verify_none} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
@@ -190,8 +212,8 @@ server_verify_client_once() ->
[{doc,"Test server option verify_client_once"}].
server_verify_client_once(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, []),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
@@ -207,7 +229,7 @@ server_verify_client_once(Config) when is_list(Config) ->
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{active, Active} | ClientOpts]}]),
+ {options, [{active, Active} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client0, ok),
Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
@@ -229,8 +251,8 @@ server_require_peer_cert_ok() ->
server_require_peer_cert_ok(Config) when is_list(Config) ->
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_verification_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -258,20 +280,21 @@ server_require_peer_cert_fail() ->
server_require_peer_cert_fail(Config) when is_list(Config) ->
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_verification_opts, Config)],
- BadClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+ BadClientOpts = ssl_test_lib:ssl_options(empty_client_opts, Config),
+ Active = proplists:get_value(active, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
- {options, [{active, false} | ServerOpts]}]),
+ {options, [{active, Active} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
- {options, [{active, false} | BadClientOpts]}]),
+ {options, [{active, Active} | BadClientOpts]}]),
receive
{Server, {error, {tls_alert, "handshake failure"}}} ->
receive
@@ -283,30 +306,60 @@ server_require_peer_cert_fail(Config) when is_list(Config) ->
end.
%%--------------------------------------------------------------------
+server_require_peer_cert_empty_ok() ->
+ [{doc,"Test server option fail_if_no_peer_cert when peer sends cert"}].
+
+server_require_peer_cert_empty_ok(Config) when is_list(Config) ->
+ ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, false}
+ | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ Active = proplists:get_value(active, Config),
+ ReceiveFunction = proplists:get_value(receive_function, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ ClientOpts = proplists:delete(keyfile, proplists:delete(certfile, ClientOpts0)),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active} | ClientOpts]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+%%--------------------------------------------------------------------
server_require_peer_cert_partial_chain() ->
[{doc, "Client sends an incompleate chain, by default not acceptable."}].
server_require_peer_cert_partial_chain(Config) when is_list(Config) ->
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_verification_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ Active = proplists:get_value(active, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
{ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts)),
- [{_,RootCA,_}, {_, _, _}] = public_key:pem_decode(ClientCAs),
+ [{_,RootCA,_} | _] = public_key:pem_decode(ClientCAs),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, [{active, false} | ServerOpts]}]),
+ {options, [{active, Active} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, [{active, false},
+ {options, [{active, Active},
{cacerts, [RootCA]} |
proplists:delete(cacertfile, ClientOpts)]}]),
receive
@@ -324,14 +377,14 @@ server_require_peer_cert_allow_partial_chain() ->
server_require_peer_cert_allow_partial_chain(Config) when is_list(Config) ->
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_verification_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
- {ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts)),
- [{_,_,_}, {_, IntermidiateCA, _}] = public_key:pem_decode(ServerCAs),
+ {ok, ClientCAs} = file:read_file(proplists:get_value(cacertfile, ClientOpts)),
+ [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ClientCAs),
PartialChain = fun(CertChain) ->
case lists:member(IntermidiateCA, CertChain) of
@@ -366,12 +419,12 @@ server_require_peer_cert_do_not_allow_partial_chain() ->
server_require_peer_cert_do_not_allow_partial_chain(Config) when is_list(Config) ->
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_verification_opts, Config)],
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
{ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts)),
- [{_,_,_}, {_, IntermidiateCA, _}] = public_key:pem_decode(ServerCAs),
+ [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
PartialChain = fun(_CertChain) ->
unknown_ca
@@ -407,15 +460,15 @@ server_require_peer_cert_partial_chain_fun_fail() ->
server_require_peer_cert_partial_chain_fun_fail(Config) when is_list(Config) ->
ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true}
- | ssl_test_lib:ssl_options(server_verification_opts, Config)],
- ClientOpts = proplists:get_value(client_verification_opts, Config),
+ | ssl_test_lib:ssl_options(server_rsa_opts, Config)],
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
{ok, ServerCAs} = file:read_file(proplists:get_value(cacertfile, ServerOpts)),
- [{_,_,_}, {_, IntermidiateCA, _}] = public_key:pem_decode(ServerCAs),
+ [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs),
PartialChain = fun(_CertChain) ->
- ture = false %% crash on purpose
+ ture = false %% crash on purpose
end,
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
@@ -447,8 +500,8 @@ verify_fun_always_run_client() ->
[{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}].
verify_fun_always_run_client(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
@@ -492,8 +545,8 @@ verify_fun_always_run_client(Config) when is_list(Config) ->
verify_fun_always_run_server() ->
[{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}].
verify_fun_always_run_server(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
%% If user verify fun is called correctly we fail the connection.
@@ -524,9 +577,7 @@ verify_fun_always_run_server(Config) when is_list(Config) ->
{from, self()},
{mfa, {ssl_test_lib,
no_result, []}},
- {options,
- [{verify, verify_peer}
- | ClientOpts]}]),
+ {options, ClientOpts}]),
%% Client error may be {tls_alert, "handshake failure" } or closed depending on timing
%% this is not a bug it is a circumstance of how tcp works!
@@ -543,63 +594,31 @@ cert_expired() ->
[{doc,"Test server with expired certificate"}].
cert_expired(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
-
- KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
-
- ServerCertFile = proplists:get_value(certfile, ServerOpts),
- NewServerCertFile = filename:join(PrivDir, "server/expired_cert.pem"),
- [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
- OTPCert = public_key:pkix_decode_cert(DerCert, otp),
- OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate,
-
{Year, Month, Day} = date(),
- {Hours, Min, Sec} = time(),
- NotBeforeStr = lists:flatten(io_lib:format("~p~s~s~s~s~sZ",[Year-2,
- two_digits_str(Month),
- two_digits_str(Day),
- two_digits_str(Hours),
- two_digits_str(Min),
- two_digits_str(Sec)])),
- NotAfterStr = lists:flatten(io_lib:format("~p~s~s~s~s~sZ",[Year-1,
- two_digits_str(Month),
- two_digits_str(Day),
- two_digits_str(Hours),
- two_digits_str(Min),
- two_digits_str(Sec)])),
- NewValidity = {'Validity', {generalTime, NotBeforeStr}, {generalTime, NotAfterStr}},
-
- ct:log("Validity: ~p ~n NewValidity: ~p ~n",
- [OTPTbsCert#'OTPTBSCertificate'.validity, NewValidity]),
-
- NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{validity = NewValidity},
- NewServerDerCert = public_key:pkix_sign(NewOTPTbsCert, Key),
- ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]),
- NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
-
+ Active = proplists:get_value(active, Config),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],
+ [{validity, {{Year-2, Month, Day},
+ {Year-1, Month, Day}}}],
+ []
+ ]}],
+ Config, "_expired"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
+
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
- {options, NewServerOpts}]),
+ {options, [{active, Active}| 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]}]),
- receive
- {Client, {error, {tls_alert, "certificate expired"}}} ->
- receive
- {Server, {error, {tls_alert, "certificate expired"}}} ->
- ok;
- {Server, {error, closed}} ->
- ok
- end
- end.
+ {options, [{verify, verify_peer}, {active, Active} | ClientOpts]}]),
+
+ tcp_delivery_workaround(Server, {error, {tls_alert, "certificate expired"}},
+ Client, {error, {tls_alert, "certificate expired"}}).
two_digits_str(N) when N < 10 ->
lists:flatten(io_lib:format("0~p", [N]));
@@ -607,61 +626,33 @@ two_digits_str(N) ->
lists:flatten(io_lib:format("~p", [N])).
%%--------------------------------------------------------------------
-extended_key_usage_verify_peer() ->
- [{doc,"Test cert that has a critical extended_key_usage extension in verify_peer mode"}].
-
-extended_key_usage_verify_peer(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
+extended_key_usage_verify_server() ->
+ [{doc,"Test cert that has a critical extended_key_usage extension in server cert"}].
+
+extended_key_usage_verify_server(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{?'id-ce-extKeyUsage',
+ [?'id-kp-serverAuth'], true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],[], [{extensions, Ext}]]}], Config,
+ "_keyusage_server"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
- KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
-
- ServerCertFile = proplists:get_value(certfile, ServerOpts),
- NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"),
- [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
- ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp),
- ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']},
- ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate,
- ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions,
- NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions =
- [ServerExtKeyUsageExt |
- ServerExtensions]},
- NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key),
- ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]),
- NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
-
- ClientCertFile = proplists:get_value(certfile, ClientOpts),
- NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"),
- [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile),
- ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp),
- ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']},
- ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate,
- ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions,
- NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions =
- [ClientExtKeyUsageExt |
- ClientExtensions]},
- NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key),
- ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]),
- NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)],
-
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{verify, verify_peer}, {active, Active} | NewServerOpts]}]),
+ {options, [{verify, verify_none}, {active, Active} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
{options, [{verify, verify_peer}, {active, Active} |
- NewClientOpts]}]),
+ ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
@@ -669,60 +660,34 @@ extended_key_usage_verify_peer(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-extended_key_usage_verify_none() ->
- [{doc,"Test cert that has a critical extended_key_usage extension in verify_none mode"}].
-
-extended_key_usage_verify_none(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
+extended_key_usage_verify_both() ->
+ [{doc,"Test cert that has a critical extended_key_usage extension in client verify_peer mode"}].
+
+extended_key_usage_verify_both(Config) when is_list(Config) ->
+ ServerExt = x509_test:extensions([{?'id-ce-extKeyUsage',
+ [?'id-kp-serverAuth'], true}]),
+ ClientExt = x509_test:extensions([{?'id-ce-extKeyUsage',
+ [?'id-kp-clientAuth'], true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, [[],[],[{extensions, ClientExt}]]},
+ {server_chain, [[],[],[{extensions, ServerExt}]]}],
+ Config, "_keyusage_both"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
- KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
-
- ServerCertFile = proplists:get_value(certfile, ServerOpts),
- NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"),
- [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
- ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp),
- ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']},
- ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate,
- ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions,
- NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions =
- [ServerExtKeyUsageExt |
- ServerExtensions]},
- NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key),
- ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]),
- NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
-
- ClientCertFile = proplists:get_value(certfile, ClientOpts),
- NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"),
- [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile),
- ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp),
- ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']},
- ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate,
- ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions,
- NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions =
- [ClientExtKeyUsageExt |
- ClientExtensions]},
- NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key),
- ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]),
- NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)],
-
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{verify, verify_none}, {active, Active} | NewServerOpts]}]),
+ {options, [{verify, verify_peer}, {active, Active} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{verify, verify_none}, {active, Active} | NewClientOpts]}]),
+ {options, [{verify, verify_peer}, {active, Active} | ClientOpts]}]),
ssl_test_lib:check_result(Server, ok, Client, ok),
@@ -730,28 +695,55 @@ extended_key_usage_verify_none(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
-critical_extension_verify_peer() ->
+critical_extension_verify_server() ->
[{doc,"Test cert that has a critical unknown extension in verify_peer mode"}].
-critical_extension_verify_peer(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
+critical_extension_verify_server(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain,
+ [[],[], [{extensions, Ext}]]}],
+ Config, "_client_unknown_extension"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
- KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- NewCertName = integer_to_list(erlang:unique_integer()) ++ ".pem",
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
- ServerCertFile = proplists:get_value(certfile, ServerOpts),
- NewServerCertFile = filename:join([PrivDir, "server", NewCertName]),
- add_critical_netscape_cert_type(ServerCertFile, NewServerCertFile, KeyFile),
- NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
+ Server = ssl_test_lib:start_server_error(
+ [{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{verify, verify_peer}, {active, Active} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client_error(
+ [{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{verify, verify_none}, {active, Active} | ClientOpts]}]),
- ClientCertFile = proplists:get_value(certfile, ClientOpts),
- NewClientCertFile = filename:join([PrivDir, "client", NewCertName]),
- add_critical_netscape_cert_type(ClientCertFile, NewClientCertFile, KeyFile),
- NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)],
+ %% This certificate has a critical extension that we don't
+ %% understand. Therefore, verification should fail.
+
+ tcp_delivery_workaround(Server, {error, {tls_alert, "unsupported certificate"}},
+ Client, {error, {tls_alert, "unsupported certificate"}}),
+
+ ssl_test_lib:close(Server).
+%%--------------------------------------------------------------------
+
+critical_extension_verify_client() ->
+ [{doc,"Test cert that has a critical unknown extension in verify_peer mode"}].
+
+critical_extension_verify_client(Config) when is_list(Config) ->
+ Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],[],[{extensions, Ext}]]}],
+ Config, "_server_unknown_extensions"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
+ Active = proplists:get_value(active, Config),
+ ReceiveFunction = proplists:get_value(receive_function, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -759,61 +751,50 @@ critical_extension_verify_peer(Config) when is_list(Config) ->
[{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{verify, verify_peer}, {active, Active} | NewServerOpts]}]),
+ {options, [{verify, verify_none}, {active, Active} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client_error(
[{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{verify, verify_peer}, {active, Active} | NewClientOpts]}]),
+ {options, [{verify, verify_peer}, {active, Active} | ClientOpts]}]),
%% This certificate has a critical extension that we don't
%% understand. Therefore, verification should fail.
- tcp_delivery_workaround(Server, {error, {tls_alert, "unsupported certificate"}},
- Client, {error, {tls_alert, "unsupported certificate"}}),
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "unsupported certificate"}},
+ Client, {error, {tls_alert, "unsupported certificate"}}),
- ssl_test_lib:close(Server),
- ok.
+ ssl_test_lib:close(Server).
%%--------------------------------------------------------------------
critical_extension_verify_none() ->
[{doc,"Test cert that has a critical unknown extension in verify_none mode"}].
critical_extension_verify_none(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
+ Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain,
+ [[],[], [{extensions, Ext}]]}],
+ Config, "_unknown_extensions"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
Active = proplists:get_value(active, Config),
ReceiveFunction = proplists:get_value(receive_function, Config),
- KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- NewCertName = integer_to_list(erlang:unique_integer()) ++ ".pem",
-
- ServerCertFile = proplists:get_value(certfile, ServerOpts),
- NewServerCertFile = filename:join([PrivDir, "server", NewCertName]),
- add_critical_netscape_cert_type(ServerCertFile, NewServerCertFile, KeyFile),
- NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)],
-
- ClientCertFile = proplists:get_value(certfile, ClientOpts),
- NewClientCertFile = filename:join([PrivDir, "client", NewCertName]),
- add_critical_netscape_cert_type(ClientCertFile, NewClientCertFile, KeyFile),
- NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)],
-
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server(
[{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{verify, verify_none}, {active, Active} | NewServerOpts]}]),
+ {options, [{verify, verify_none}, {active, Active} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client(
[{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
{mfa, {ssl_test_lib, ReceiveFunction, []}},
- {options, [{verify, verify_none}, {active, Active} | NewClientOpts]}]),
+ {options, [{verify, verify_none}, {active, Active} | ClientOpts]}]),
%% This certificate has a critical extension that we don't
%% understand. But we're using `verify_none', so verification
@@ -821,28 +802,7 @@ critical_extension_verify_none(Config) when is_list(Config) ->
ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
- ssl_test_lib:close(Client),
- ok.
-
-add_critical_netscape_cert_type(CertFile, NewCertFile, KeyFile) ->
- [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
-
- [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile),
- OTPCert = public_key:pkix_decode_cert(DerCert, otp),
- %% This is the "Netscape Cert Type" extension, telling us that the
- %% certificate can be used for SSL clients and SSL servers.
- NetscapeCertTypeExt = #'Extension'{
- extnID = {2,16,840,1,113730,1,1},
- critical = true,
- extnValue = <<3,2,6,192>>},
- OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate,
- Extensions = OTPTbsCert#'OTPTBSCertificate'.extensions,
- NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{
- extensions = [NetscapeCertTypeExt] ++ Extensions},
- NewDerCert = public_key:pkix_sign(NewOTPTbsCert, Key),
- ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]),
- ok.
+ ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
no_authority_key_identifier() ->
@@ -850,35 +810,16 @@ no_authority_key_identifier() ->
" but are present in trusted certs db."}].
no_authority_key_identifier(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
-
- KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
-
- CertFile = proplists:get_value(certfile, ServerOpts),
- NewCertFile = filename:join(PrivDir, "server/new_cert.pem"),
- [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile),
- OTPCert = public_key:pkix_decode_cert(DerCert, otp),
- OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate,
- Extensions = OTPTbsCert#'OTPTBSCertificate'.extensions,
- NewExtensions = delete_authority_key_extension(Extensions, []),
- NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{extensions = NewExtensions},
-
- ct:log("Extensions ~p~n, NewExtensions: ~p~n", [Extensions, NewExtensions]),
-
- NewDerCert = public_key:pkix_sign(NewOTPTbsCert, Key),
- ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]),
- NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)],
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([], Config, "_peer_no_auth_key_id"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib, send_recv_result_active, []}},
- {options, NewServerOpts}]),
+ {options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -894,53 +835,31 @@ no_authority_key_identifier(Config) when is_list(Config) ->
delete_authority_key_extension([], Acc) ->
lists:reverse(Acc);
delete_authority_key_extension([#'Extension'{extnID = ?'id-ce-authorityKeyIdentifier'} | Rest],
- Acc) ->
+ Acc) ->
delete_authority_key_extension(Rest, Acc);
delete_authority_key_extension([Head | Rest], Acc) ->
delete_authority_key_extension(Rest, [Head | Acc]).
%%--------------------------------------------------------------------
-no_authority_key_identifier_and_nonstandard_encoding() ->
- [{doc, "Test cert with nonstandard encoding that does not have"
- " authorityKeyIdentifier extension but are present in trusted certs db."}].
-
-no_authority_key_identifier_and_nonstandard_encoding(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
-
- KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"),
- [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
- Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
-
- CertFile = proplists:get_value(certfile, ServerOpts),
- NewCertFile = filename:join(PrivDir, "server/new_cert.pem"),
- [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile),
- ServerCert = public_key:pkix_decode_cert(DerCert, plain),
- ServerTbsCert = ServerCert#'Certificate'.tbsCertificate,
- Extensions0 = ServerTbsCert#'TBSCertificate'.extensions,
- %% need to remove authorityKeyIdentifier extension to cause DB lookup by signature
- Extensions = delete_authority_key_extension(Extensions0, []),
- NewExtensions = replace_key_usage_extension(Extensions, []),
- NewServerTbsCert = ServerTbsCert#'TBSCertificate'{extensions = NewExtensions},
-
- ct:log("Extensions ~p~n, NewExtensions: ~p~n", [Extensions, NewExtensions]),
-
- TbsDer = public_key:pkix_encode('TBSCertificate', NewServerTbsCert, plain),
- Sig = public_key:sign(TbsDer, md5, Key),
- NewServerCert = ServerCert#'Certificate'{tbsCertificate = NewServerTbsCert, signature = Sig},
- NewDerCert = public_key:pkix_encode('Certificate', NewServerCert, plain),
- ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]),
- NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)],
-
+no_authority_key_identifier_keyEncipherment() ->
+ [{doc, "Test cert with keyEncipherment key_usage an no"
+ " authorityKeyIdentifier extension, but are present in trusted certs db."}].
+
+no_authority_key_identifier_keyEncipherment(Config) when is_list(Config) ->
+ ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain,
+ [[],[],[{extensions, ClientExt}]]}],
+ Config, "_peer_keyEncipherment"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib,
send_recv_result_active, []}},
- {options, [{active, true} | NewServerOpts]}]),
+ {options, [{active, true} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -952,14 +871,6 @@ no_authority_key_identifier_and_nonstandard_encoding(Config) when is_list(Config
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
-replace_key_usage_extension([], Acc) ->
- lists:reverse(Acc);
-replace_key_usage_extension([#'Extension'{extnID = ?'id-ce-keyUsage'} = E | Rest], Acc) ->
- %% A nonstandard DER encoding of [digitalSignature, keyEncipherment]
- Val = <<3, 2, 0, 16#A0>>,
- replace_key_usage_extension(Rest, [E#'Extension'{extnValue = Val} | Acc]);
-replace_key_usage_extension([Head | Rest], Acc) ->
- replace_key_usage_extension(Rest, [Head | Acc]).
%%--------------------------------------------------------------------
@@ -967,16 +878,16 @@ invalid_signature_server() ->
[{doc,"Test client with invalid signature"}].
invalid_signature_server(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
PrivDir = proplists:get_value(priv_dir, Config),
- KeyFile = filename:join(PrivDir, "server/key.pem"),
+ KeyFile = proplists:get_value(keyfile, ServerOpts),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ServerCertFile = proplists:get_value(certfile, ServerOpts),
- NewServerCertFile = filename:join(PrivDir, "server/invalid_cert.pem"),
+ NewServerCertFile = filename:join(PrivDir, "server_invalid_cert.pem"),
[{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile),
ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp),
ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate,
@@ -995,8 +906,8 @@ invalid_signature_server(Config) when is_list(Config) ->
{from, self()},
{options, [{verify, verify_peer} | ClientOpts]}]),
- tcp_delivery_workaround(Server, {error, {tls_alert, "bad certificate"}},
- Client, {error, {tls_alert, "bad certificate"}}).
+ tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}},
+ Client, {error, {tls_alert, "unknown ca"}}).
%%--------------------------------------------------------------------
@@ -1004,16 +915,16 @@ invalid_signature_client() ->
[{doc,"Test server with invalid signature"}].
invalid_signature_client(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
PrivDir = proplists:get_value(priv_dir, Config),
- KeyFile = filename:join(PrivDir, "client/key.pem"),
+ KeyFile = proplists:get_value(keyfile, ClientOpts),
[KeyEntry] = ssl_test_lib:pem_to_der(KeyFile),
Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)),
ClientCertFile = proplists:get_value(certfile, ClientOpts),
- NewClientCertFile = filename:join(PrivDir, "client/invalid_cert.pem"),
+ NewClientCertFile = filename:join(PrivDir, "client_invalid_cert.pem"),
[{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile),
ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp),
ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate,
@@ -1032,8 +943,8 @@ invalid_signature_client(Config) when is_list(Config) ->
{from, self()},
{options, NewClientOpts}]),
- tcp_delivery_workaround(Server, {error, {tls_alert, "bad certificate"}},
- Client, {error, {tls_alert, "bad certificate"}}).
+ tcp_delivery_workaround(Server, {error, {tls_alert, "unknown ca"}},
+ Client, {error, {tls_alert, "unknown ca"}}).
%%--------------------------------------------------------------------
@@ -1042,15 +953,22 @@ client_with_cert_cipher_suites_handshake() ->
[{doc, "Test that client with a certificate without keyEncipherment usage "
" extension can connect to a server with restricted cipher suites "}].
client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts_digital_signature_only, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain,
+ [[], [], [{extensions, Ext}]]}],
+ Config, "_sign_only_extensions"),
+ ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config),
+ ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config),
+ TLSVersion = ssl_test_lib:protocol_version(Config, tuple),
+
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
{mfa, {ssl_test_lib,
send_recv_result_active, []}},
{options, [{active, true},
- {ciphers, ssl_test_lib:rsa_non_signed_suites()}
+ {ciphers,
+ ssl_test_lib:rsa_non_signed_suites(TLSVersion)}
| ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
@@ -1070,7 +988,7 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
server_verify_no_cacerts() ->
[{doc,"Test server must have cacerts if it wants to verify client"}].
server_verify_no_cacerts(Config) when is_list(Config) ->
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = proplists:delete(cacertfile, ssl_test_lib:ssl_options(server_rsa_opts, Config)),
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
@@ -1084,8 +1002,8 @@ server_verify_no_cacerts(Config) when is_list(Config) ->
unknown_server_ca_fail() ->
[{doc,"Test that the client fails if the ca is unknown in verify_peer mode"}].
unknown_server_ca_fail(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(empty_client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
@@ -1128,8 +1046,8 @@ unknown_server_ca_fail(Config) when is_list(Config) ->
unknown_server_ca_accept_verify_none() ->
[{doc,"Test that the client succeds if the ca is unknown in verify_none mode"}].
unknown_server_ca_accept_verify_none(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(empty_client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
@@ -1153,8 +1071,8 @@ unknown_server_ca_accept_verify_peer() ->
[{doc, "Test that the client succeds if the ca is unknown in verify_peer mode"
" with a verify_fun that accepts the unknown ca error"}].
unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(empty_client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
@@ -1192,8 +1110,8 @@ unknown_server_ca_accept_verify_peer(Config) when is_list(Config) ->
unknown_server_ca_accept_backwardscompatibility() ->
[{doc,"Test that old style verify_funs will work"}].
unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) ->
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(empty_client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()},
diff --git a/lib/ssl/test/ssl_crl_SUITE.erl b/lib/ssl/test/ssl_crl_SUITE.erl
index 00636e5660..668c76e38d 100644
--- a/lib/ssl/test/ssl_crl_SUITE.erl
+++ b/lib/ssl/test/ssl_crl_SUITE.erl
@@ -72,7 +72,7 @@ init_per_suite(Config) ->
false ->
{skip, io_lib:format("Bad openssl version: ~p",[OpenSSL_version])};
_ ->
- catch crypto:stop(),
+ end_per_suite(Config),
try crypto:start() of
ok ->
{ok, Hostname0} = inet:gethostname(),
@@ -99,32 +99,37 @@ init_per_group(check_peer, Config) ->
init_per_group(check_best_effort, Config) ->
[{crl_check, best_effort} | Config];
init_per_group(Group, Config0) ->
- case is_idp(Group) of
- true ->
- [{idp_crl, true} | Config0];
- false ->
- DataDir = proplists:get_value(data_dir, Config0),
- CertDir = filename:join(proplists:get_value(priv_dir, Config0), Group),
- {CertOpts, Config} = init_certs(CertDir, Group, Config0),
- {ok, _} = make_certs:all(DataDir, CertDir, CertOpts),
- case Group of
- crl_hash_dir ->
- CrlDir = filename:join(CertDir, "crls"),
- %% Copy CRLs to their hashed filenames.
- %% Find the hashes with 'openssl crl -noout -hash -in crl.pem'.
- populate_crl_hash_dir(CertDir, CrlDir,
- [{"erlangCA", "d6134ed3"},
- {"otpCA", "d4c8d7e5"}],
- replace),
- CrlCacheOpts = [{crl_cache,
- {ssl_crl_hash_dir,
- {internal, [{dir, CrlDir}]}}}];
- _ ->
- CrlCacheOpts = []
- end,
- [{crl_cache_opts, CrlCacheOpts},
- {cert_dir, CertDir},
- {idp_crl, false} | Config]
+ try
+ case is_idp(Group) of
+ true ->
+ [{idp_crl, true} | Config0];
+ false ->
+ DataDir = proplists:get_value(data_dir, Config0),
+ CertDir = filename:join(proplists:get_value(priv_dir, Config0), Group),
+ {CertOpts, Config} = init_certs(CertDir, Group, Config0),
+ {ok, _} = make_certs:all(DataDir, CertDir, CertOpts),
+ CrlCacheOpts = case Group of
+ crl_hash_dir ->
+ CrlDir = filename:join(CertDir, "crls"),
+ %% Copy CRLs to their hashed filenames.
+ %% Find the hashes with 'openssl crl -noout -hash -in crl.pem'.
+ populate_crl_hash_dir(CertDir, CrlDir,
+ [{"erlangCA", "d6134ed3"},
+ {"otpCA", "d4c8d7e5"}],
+ replace),
+ [{crl_cache,
+ {ssl_crl_hash_dir,
+ {internal, [{dir, CrlDir}]}}}];
+ _ ->
+ []
+ end,
+ [{crl_cache_opts, CrlCacheOpts},
+ {cert_dir, CertDir},
+ {idp_crl, false} | Config]
+ end
+ catch
+ _:_ ->
+ {skip, "Unable to create crls"}
end.
end_per_group(_GroupName, Config) ->
@@ -136,7 +141,7 @@ init_per_testcase(Case, Config0) ->
true ->
end_per_testcase(Case, Config0),
inets:start(),
- ssl:start(),
+ ssl_test_lib:clean_start(),
ServerRoot = make_dir_path([proplists:get_value(priv_dir, Config0), idp_crl, tmp]),
%% start a HTTP server to serve the CRLs
{ok, Httpd} = inets:start(httpd, [{ipfamily, proplists:get_value(ipfamily, Config0)},
@@ -150,12 +155,18 @@ init_per_testcase(Case, Config0) ->
DataDir = proplists:get_value(data_dir, Config),
CertDir = filename:join(proplists:get_value(priv_dir, Config0), idp_crl),
{CertOpts, Config} = init_certs(CertDir, idp_crl, Config),
- {ok, _} = make_certs:all(DataDir, CertDir, CertOpts),
- ct:timetrap({seconds, 6}),
- [{cert_dir, CertDir} | Config];
+ case make_certs:all(DataDir, CertDir, CertOpts) of
+ {ok, _} ->
+ ct:timetrap({seconds, 6}),
+ [{cert_dir, CertDir} | Config];
+ _ ->
+ end_per_testcase(Case, Config0),
+ ssl_test_lib:clean_start(),
+ {skip, "Unable to create IDP crls"}
+ end;
false ->
end_per_testcase(Case, Config0),
- ssl:start(),
+ ssl_test_lib:clean_start(),
Config0
end.
@@ -187,7 +198,7 @@ crl_verify_valid(Config) when is_list(Config) ->
{crl_cache, {ssl_crl_cache, {internal, [{http, 5000}]}}},
{verify, verify_peer}];
false ->
- ?config(crl_cache_opts, Config) ++
+ proplists:get_value(crl_cache_opts, Config) ++
[{cacertfile, filename:join([PrivDir, "server", "cacerts.pem"])},
{crl_check, Check},
{verify, verify_peer}]
@@ -220,7 +231,7 @@ crl_verify_revoked(Config) when is_list(Config) ->
{crl_check, Check},
{verify, verify_peer}];
false ->
- ?config(crl_cache_opts, Config) ++
+ proplists:get_value(crl_cache_opts, Config) ++
[{cacertfile, filename:join([PrivDir, "revoked", "cacerts.pem"])},
{crl_check, Check},
{verify, verify_peer}]
@@ -279,8 +290,8 @@ crl_verify_no_crl(Config) when is_list(Config) ->
crl_hash_dir_collision() ->
[{doc,"Verify ssl_crl_hash_dir behaviour with hash collisions"}].
crl_hash_dir_collision(Config) when is_list(Config) ->
- PrivDir = ?config(cert_dir, Config),
- Check = ?config(crl_check, Config),
+ PrivDir = proplists:get_value(cert_dir, Config),
+ Check = proplists:get_value(crl_check, Config),
%% Create two CAs whose names hash to the same value
CA1 = "hash-collision-0000000000",
@@ -307,13 +318,17 @@ crl_hash_dir_collision(Config) when is_list(Config) ->
{CA2, "b68fc624"}],
replace),
- ClientOpts = ?config(crl_cache_opts, Config) ++
- [{cacertfile, filename:join([PrivDir, "erlangCA", "cacerts.pem"])},
+ NewCA = new_ca(filename:join([PrivDir, "new_ca"]),
+ filename:join([PrivDir, "erlangCA", "cacerts.pem"]),
+ filename:join([PrivDir, "server", "cacerts.pem"])),
+
+ ClientOpts = proplists:get_value(crl_cache_opts, Config) ++
+ [{cacertfile, NewCA},
{crl_check, Check},
{verify, verify_peer}],
-
+
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
+
%% Neither certificate revoked; both succeed.
crl_verify_valid(Hostname, ServerNode, ServerOpts1, ClientNode, ClientOpts),
crl_verify_valid(Hostname, ServerNode, ServerOpts2, ClientNode, ClientOpts),
@@ -346,8 +361,8 @@ crl_hash_dir_collision(Config) when is_list(Config) ->
crl_hash_dir_expired() ->
[{doc,"Verify ssl_crl_hash_dir behaviour with expired CRLs"}].
crl_hash_dir_expired(Config) when is_list(Config) ->
- PrivDir = ?config(cert_dir, Config),
- Check = ?config(crl_check, Config),
+ PrivDir = proplists:get_value(cert_dir, Config),
+ Check = proplists:get_value(crl_check, Config),
CA = "CRL-maybe-expired-CA",
%% Add "issuing distribution point", to ensure that verification
@@ -362,7 +377,7 @@ crl_hash_dir_expired(Config) when is_list(Config) ->
ServerOpts = [{keyfile, filename:join([PrivDir, EndUser, "key.pem"])},
{certfile, filename:join([PrivDir, EndUser, "cert.pem"])},
{cacertfile, filename:join([PrivDir, EndUser, "cacerts.pem"])}],
- ClientOpts = ?config(crl_cache_opts, Config) ++
+ ClientOpts = proplists:get_value(crl_cache_opts, Config) ++
[{cacertfile, filename:join([PrivDir, CA, "cacerts.pem"])},
{crl_check, Check},
{verify, verify_peer}],
@@ -492,3 +507,12 @@ find_free_name(CrlDir, Hash, N) ->
false ->
Name
end.
+
+new_ca(FileName, CA1, CA2) ->
+ {ok, P1} = file:read_file(CA1),
+ E1 = public_key:pem_decode(P1),
+ {ok, P2} = file:read_file(CA2),
+ E2 = public_key:pem_decode(P2),
+ Pem = public_key:pem_encode(E1 ++E2),
+ file:write_file(FileName, Pem),
+ FileName.
diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl
index 5ebf9bb2de..8740e8c8f0 100644
--- a/lib/ssl/test/ssl_dist_SUITE.erl
+++ b/lib/ssl/test/ssl_dist_SUITE.erl
@@ -109,11 +109,11 @@ common_end(_, _Config) ->
basic() ->
[{doc,"Test that two nodes can connect via ssl distribution"}].
basic(Config) when is_list(Config) ->
- NH1 = start_ssl_node(Config),
+ gen_dist_test(basic_test, Config).
+
+basic_test(NH1, NH2, _) ->
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node(Config),
Node2 = NH2#node_handle.nodename,
-
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
@@ -161,18 +161,16 @@ basic(Config) when is_list(Config) ->
ok
end
end)
- end,
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
+ end.
%%--------------------------------------------------------------------
payload() ->
[{doc,"Test that send a lot of data between the ssl distributed noes"}].
payload(Config) when is_list(Config) ->
- NH1 = start_ssl_node(Config),
+ gen_dist_test(payload_test, Config).
+
+payload_test(NH1, NH2, _) ->
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node(Config),
Node2 = NH2#node_handle.nodename,
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
@@ -204,10 +202,8 @@ payload(Config) when is_list(Config) ->
ok
end
end)
- end,
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
+ end.
+
%%--------------------------------------------------------------------
plain_options() ->
[{doc,"Test specifying additional options"}].
@@ -218,20 +214,17 @@ plain_options(Config) when is_list(Config) ->
"client_verify verify_none server_verify verify_none "
"server_depth 1 client_depth 1 "
"server_hibernate_after 500 client_hibernate_after 500",
+ gen_dist_test(plain_options_test, [{additional_dist_opts, DistOpts} | Config]).
- NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+plain_options_test(NH1, NH2, _) ->
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
Node2 = NH2#node_handle.nodename,
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end).
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
%%--------------------------------------------------------------------
plain_verify_options() ->
[{doc,"Test specifying additional options"}].
@@ -240,20 +233,18 @@ plain_verify_options(Config) when is_list(Config) ->
"client_secure_renegotiate true "
"server_reuse_sessions true client_reuse_sessions true "
"server_hibernate_after 500 client_hibernate_after 500",
+ gen_dist_test(plain_verify_options_test, [{additional_dist_opts, DistOpts} | Config]).
- NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+plain_verify_options_test(NH1, NH2, _) ->
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
Node2 = NH2#node_handle.nodename,
-
+
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
-
+
[Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end).
+
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
%%--------------------------------------------------------------------
nodelay_option() ->
[{doc,"Test specifying dist_nodelay option"}].
@@ -265,6 +256,7 @@ nodelay_option(Config) ->
after
application:unset_env(kernel, dist_nodelay)
end.
+%%--------------------------------------------------------------------
listen_port_options() ->
[{doc, "Test specifying listening ports"}].
@@ -285,32 +277,39 @@ listen_port_options(Config) when is_list(Config) ->
#node_handle{} ->
%% If the node was able to start, it didn't take the port
%% option into account.
+ stop_ssl_node(NH1),
exit(unexpected_success)
catch
exit:{accept_failed, timeout} ->
%% The node failed to start, as expected.
ok
end,
-
+
%% Try again, now specifying a high max port.
PortOpt2 = "-kernel inet_dist_listen_min " ++ integer_to_list(Port1) ++
- " inet_dist_listen_max 65535",
+ " inet_dist_listen_max 65535",
NH2 = start_ssl_node([{additional_dist_opts, PortOpt2} | Config]),
- Node2 = NH2#node_handle.nodename,
- Name2 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node2)),
- {ok, NodesPorts2} = apply_on_ssl_node(NH2, fun net_adm:names/0),
- {Name2, Port2} = lists:keyfind(Name2, 1, NodesPorts2),
-
- %% The new port should be higher:
- if Port2 > Port1 ->
- ok;
- true ->
- error({port, Port2, not_higher_than, Port1})
+
+ try
+ Node2 = NH2#node_handle.nodename,
+ Name2 = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node2)),
+ {ok, NodesPorts2} = apply_on_ssl_node(NH2, fun net_adm:names/0),
+ {Name2, Port2} = lists:keyfind(Name2, 1, NodesPorts2),
+
+ %% The new port should be higher:
+ if Port2 > Port1 ->
+ ok;
+ true ->
+ error({port, Port2, not_higher_than, Port1})
+ end
+ catch
+ _:Reason ->
+ stop_ssl_node(NH2),
+ ct:fail(Reason)
end,
-
- stop_ssl_node(NH1),
stop_ssl_node(NH2),
success(Config).
+
%%--------------------------------------------------------------------
listen_options() ->
[{doc, "Test inet_dist_listen_options"}].
@@ -329,28 +328,25 @@ do_listen_options(Prio, Config) ->
end,
Options = "-kernel inet_dist_listen_options " ++ PriorityString,
-
- NH1 = start_ssl_node([{additional_dist_opts, Options} | Config]),
- NH2 = start_ssl_node([{additional_dist_opts, Options} | Config]),
- Node2 = NH2#node_handle.nodename,
-
+ gen_dist_test(listen_options_test, [{prio, Prio}, {additional_dist_opts, Options} | Config]).
+
+listen_options_test(NH1, NH2, Config) ->
+ Prio = proplists:get_value(prio, Config),
+ Node2 = NH2#node_handle.nodename,
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
PrioritiesNode1 =
apply_on_ssl_node(NH1, fun get_socket_priorities/0),
PrioritiesNode2 =
apply_on_ssl_node(NH2, fun get_socket_priorities/0),
-
+
Elevated1 = [P || P <- PrioritiesNode1, P =:= Prio],
- ?t:format("Elevated1: ~p~n", [Elevated1]),
+ ct:pal("Elevated1: ~p~n", [Elevated1]),
Elevated2 = [P || P <- PrioritiesNode2, P =:= Prio],
- ?t:format("Elevated2: ~p~n", [Elevated2]),
+ ct:pal("Elevated2: ~p~n", [Elevated2]),
[_|_] = Elevated1,
- [_|_] = Elevated2,
+ [_|_] = Elevated2.
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
%%--------------------------------------------------------------------
connect_options() ->
[{doc, "Test inet_dist_connect_options"}].
@@ -369,9 +365,11 @@ do_connect_options(Prio, Config) ->
end,
Options = "-kernel inet_dist_connect_options " ++ PriorityString,
+ gen_dist_test(connect_options_test,
+ [{prio, Prio}, {additional_dist_opts, Options} | Config]).
- NH1 = start_ssl_node([{additional_dist_opts, Options} | Config]),
- NH2 = start_ssl_node([{additional_dist_opts, Options} | Config]),
+connect_options_test(NH1, NH2, Config) ->
+ Prio = proplists:get_value(prio, Config),
Node2 = NH2#node_handle.nodename,
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
@@ -382,17 +380,14 @@ do_connect_options(Prio, Config) ->
apply_on_ssl_node(NH2, fun get_socket_priorities/0),
Elevated1 = [P || P <- PrioritiesNode1, P =:= Prio],
- ?t:format("Elevated1: ~p~n", [Elevated1]),
+ ct:pal("Elevated1: ~p~n", [Elevated1]),
Elevated2 = [P || P <- PrioritiesNode2, P =:= Prio],
- ?t:format("Elevated2: ~p~n", [Elevated2]),
+ ct:pal("Elevated2: ~p~n", [Elevated2]),
%% Node 1 will have a socket with elevated priority.
[_|_] = Elevated1,
%% Node 2 will not, since it only applies to outbound connections.
- [] = Elevated2,
+ [] = Elevated2.
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
%%--------------------------------------------------------------------
use_interface() ->
[{doc, "Test inet_dist_use_interface"}].
@@ -403,22 +398,28 @@ use_interface(Config) when is_list(Config) ->
%% Start a node, and get the port number it's listening on.
NH1 = start_ssl_node([{additional_dist_opts, Options} | Config]),
- Node1 = NH1#node_handle.nodename,
- Name = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node1)),
- {ok, NodesPorts} = apply_on_ssl_node(NH1, fun net_adm:names/0),
- {Name, Port} = lists:keyfind(Name, 1, NodesPorts),
-
- %% Now find the socket listening on that port, and check its sockname.
- Sockets = apply_on_ssl_node(
- NH1,
- fun() ->
- [inet:sockname(P) ||
- P <- inet_ports(),
- {ok, Port} =:= (catch inet:port(P))]
- end),
- %% And check that it's actually listening on localhost.
- [{ok,{{127,0,0,1},Port}}] = Sockets,
-
+
+ try
+ Node1 = NH1#node_handle.nodename,
+ Name = lists:takewhile(fun(C) -> C =/= $@ end, atom_to_list(Node1)),
+ {ok, NodesPorts} = apply_on_ssl_node(NH1, fun net_adm:names/0),
+ {Name, Port} = lists:keyfind(Name, 1, NodesPorts),
+
+ %% Now find the socket listening on that port, and check its sockname.
+ Sockets = apply_on_ssl_node(
+ NH1,
+ fun() ->
+ [inet:sockname(P) ||
+ P <- inet_ports(),
+ {ok, Port} =:= (catch inet:port(P))]
+ end),
+ %% And check that it's actually listening on localhost.
+ [{ok,{{127,0,0,1},Port}}] = Sockets
+ catch
+ _:Reason ->
+ stop_ssl_node(NH1),
+ ct:fail(Reason)
+ end,
stop_ssl_node(NH1),
success(Config).
%%--------------------------------------------------------------------
@@ -430,11 +431,11 @@ verify_fun_fail(Config) when is_list(Config) ->
"\"{ssl_dist_SUITE,verify_fail_always,{}}\" "
"client_verify verify_peer client_verify_fun "
"\"{ssl_dist_SUITE,verify_fail_always,{}}\" ",
+ gen_dist_test(verify_fun_fail_test, [{additional_dist_opts, DistOpts} | Config]).
- NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
- NH2 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+verify_fun_fail_test(NH1, NH2, _) ->
Node2 = NH2#node_handle.nodename,
-
+
pang = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[] = apply_on_ssl_node(NH1, fun () -> nodes() end),
@@ -446,25 +447,9 @@ verify_fun_fail(Config) when is_list(Config) ->
%% On the server node, it wouldn't run, because the server didn't
%% request a certificate from the client.
undefined =
- apply_on_ssl_node(NH2, fun () -> ets:info(verify_fun_ran) end),
+ apply_on_ssl_node(NH2, fun () -> ets:info(verify_fun_ran) end).
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
-verify_fail_always(_Certificate, _Event, _State) ->
- %% Create an ETS table, to record the fact that the verify function ran.
- %% Spawn a new process, to avoid the ETS table disappearing.
- Parent = self(),
- spawn(
- fun() ->
- ets:new(verify_fun_ran, [public, named_table]),
- ets:insert(verify_fun_ran, {verify_fail_always_ran, true}),
- Parent ! go_ahead,
- timer:sleep(infinity)
- end),
- receive go_ahead -> ok end,
- {fail, bad_certificate}.
%%--------------------------------------------------------------------
verify_fun_pass() ->
@@ -476,10 +461,10 @@ verify_fun_pass(Config) when is_list(Config) ->
"server_fail_if_no_peer_cert true "
"client_verify verify_peer client_verify_fun "
"\"{ssl_dist_SUITE,verify_pass_always,{}}\" ",
+ gen_dist_test(verify_fun_pass_test, [{additional_dist_opts, DistOpts} | Config]).
- NH1 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
+verify_fun_pass_test(NH1, NH2, _) ->
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node([{additional_dist_opts, DistOpts} | Config]),
Node2 = NH2#node_handle.nodename,
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
@@ -494,25 +479,8 @@ verify_fun_pass(Config) when is_list(Config) ->
%% requested and verified the client's certificate because we
%% passed fail_if_no_peer_cert.
[{verify_pass_always_ran, true}] =
- apply_on_ssl_node(NH2, fun () -> ets:tab2list(verify_fun_ran) end),
+ apply_on_ssl_node(NH2, fun () -> ets:tab2list(verify_fun_ran) end).
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
-
-verify_pass_always(_Certificate, _Event, State) ->
- %% Create an ETS table, to record the fact that the verify function ran.
- %% Spawn a new process, to avoid the ETS table disappearing.
- Parent = self(),
- spawn(
- fun() ->
- ets:new(verify_fun_ran, [public, named_table]),
- ets:insert(verify_fun_ran, {verify_pass_always_ran, true}),
- Parent ! go_ahead,
- timer:sleep(infinity)
- end),
- receive go_ahead -> ok end,
- {valid, State}.
%%--------------------------------------------------------------------
crl_check_pass() ->
[{doc,"Test crl_check with non-revoked certificate"}].
@@ -520,10 +488,10 @@ crl_check_pass(Config) when is_list(Config) ->
DistOpts = "-ssl_dist_opt client_crl_check true",
NewConfig =
[{many_verify_opts, true}, {additional_dist_opts, DistOpts}] ++ Config,
+ gen_dist_test(crl_check_pass_test, NewConfig).
- NH1 = start_ssl_node(NewConfig),
+crl_check_pass_test(NH1, NH2, Config) ->
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node(NewConfig),
Node2 = NH2#node_handle.nodename,
PrivDir = ?config(priv_dir, Config),
@@ -533,11 +501,7 @@ crl_check_pass(Config) when is_list(Config) ->
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
-
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end).
%%--------------------------------------------------------------------
crl_check_fail() ->
@@ -549,10 +513,9 @@ crl_check_fail(Config) when is_list(Config) ->
%% The server uses a revoked certificate.
{server_cert_dir, "revoked"},
{additional_dist_opts, DistOpts}] ++ Config,
+ gen_dist_test(crl_check_fail_test, NewConfig).
- NH1 = start_ssl_node(NewConfig),
- %%Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node(NewConfig),
+crl_check_fail_test(NH1, NH2, Config) ->
Node2 = NH2#node_handle.nodename,
PrivDir = ?config(priv_dir, Config),
@@ -562,11 +525,7 @@ crl_check_fail(Config) when is_list(Config) ->
pang = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- [] = apply_on_ssl_node(NH2, fun () -> nodes() end),
-
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
+ [] = apply_on_ssl_node(NH2, fun () -> nodes() end).
%%--------------------------------------------------------------------
crl_check_best_effort() ->
@@ -576,22 +535,18 @@ crl_check_best_effort(Config) when is_list(Config) ->
"server_verify verify_peer server_crl_check best_effort",
NewConfig =
[{many_verify_opts, true}, {additional_dist_opts, DistOpts}] ++ Config,
+ gen_dist_test(crl_check_best_effort_test, NewConfig).
+crl_check_best_effort_test(NH1, NH2, _Config) ->
%% We don't have the correct CRL at hand, but since crl_check is
%% best_effort, we accept it anyway.
- NH1 = start_ssl_node(NewConfig),
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node(NewConfig),
Node2 = NH2#node_handle.nodename,
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
-
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end).
%%--------------------------------------------------------------------
crl_cache_check_pass() ->
@@ -605,20 +560,16 @@ crl_cache_check_pass(Config) when is_list(Config) ->
"\"{ssl_dist_SUITE,{\\\"" ++ NodeDir ++ "\\\",[]}}\"",
NewConfig =
[{many_verify_opts, true}, {additional_dist_opts, DistOpts}] ++ Config,
+ gen_dist_test(crl_cache_check_pass_test, NewConfig).
- NH1 = start_ssl_node(NewConfig),
+crl_cache_check_pass_test(NH1, NH2, _) ->
Node1 = NH1#node_handle.nodename,
- NH2 = start_ssl_node(NewConfig),
Node2 = NH2#node_handle.nodename,
pong = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[Node2] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end),
-
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
+ [Node1] = apply_on_ssl_node(NH2, fun () -> nodes() end).
%%--------------------------------------------------------------------
crl_cache_check_fail() ->
@@ -636,44 +587,31 @@ crl_cache_check_fail(Config) when is_list(Config) ->
{server_cert_dir, "revoked"},
{additional_dist_opts, DistOpts}] ++ Config,
- NH1 = start_ssl_node(NewConfig),
- NH2 = start_ssl_node(NewConfig),
- Node2 = NH2#node_handle.nodename,
+ gen_dist_test(crl_cache_check_fail_test, NewConfig).
+crl_cache_check_fail_test(NH1, NH2, _) ->
+ Node2 = NH2#node_handle.nodename,
pang = apply_on_ssl_node(NH1, fun () -> net_adm:ping(Node2) end),
[] = apply_on_ssl_node(NH1, fun () -> nodes() end),
- [] = apply_on_ssl_node(NH2, fun () -> nodes() end),
-
- stop_ssl_node(NH1),
- stop_ssl_node(NH2),
- success(Config).
-
-%% ssl_crl_cache_api callbacks
-lookup(_DistributionPoint, _DbHandle) ->
- not_available.
-
-select({rdnSequence, NameParts}, {NodeDir, _}) ->
- %% Extract the CN from the issuer name...
- [CN] = [CN ||
- [#'AttributeTypeAndValue'{
- type = ?'id-at-commonName',
- value = <<_, _, CN/binary>>}] <- NameParts],
- %% ...and use that as the directory name to find the CRL.
- error_logger:info_report([{found_cn, CN}]),
- CRLFile = filename:join([NodeDir, CN, "crl.pem"]),
- {ok, PemBin} = file:read_file(CRLFile),
- PemEntries = public_key:pem_decode(PemBin),
- CRLs = [ CRL || {'CertificateList', CRL, not_encrypted}
- <- PemEntries],
- CRLs.
-
-fresh_crl(_DistributionPoint, CRL) ->
- CRL.
-
+ [] = apply_on_ssl_node(NH2, fun () -> nodes() end).
%%--------------------------------------------------------------------
%%% Internal functions -----------------------------------------------
%%--------------------------------------------------------------------
+gen_dist_test(Test, Config) ->
+ NH1 = start_ssl_node(Config),
+ NH2 = start_ssl_node(Config),
+ try
+ ?MODULE:Test(NH1, NH2, Config)
+ catch
+ _:Reason ->
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ ct:fail(Reason)
+ end,
+ stop_ssl_node(NH1),
+ stop_ssl_node(NH2),
+ success(Config).
%% ssl_node side api
%%
@@ -742,13 +680,15 @@ stop_ssl_node(#node_handle{connection_handler = Handler,
receive
{'DOWN', Mon, process, Handler, Reason} ->
case Reason of
- normal -> ok;
- _ -> exit(Reason)
+ normal ->
+ ok;
+ _ ->
+ ct:pal("Down ~p ~n", [Reason])
end
end;
Error ->
erlang:demonitor(Mon, [flush]),
- exit(Error)
+ ct:pal("Warning ~p ~n", [Error])
end.
start_ssl_node(Config) ->
@@ -1226,3 +1166,53 @@ vsn(App) ->
after
application:stop(ssl)
end.
+
+verify_fail_always(_Certificate, _Event, _State) ->
+ %% Create an ETS table, to record the fact that the verify function ran.
+ %% Spawn a new process, to avoid the ETS table disappearing.
+ Parent = self(),
+ spawn(
+ fun() ->
+ ets:new(verify_fun_ran, [public, named_table]),
+ ets:insert(verify_fun_ran, {verify_fail_always_ran, true}),
+ Parent ! go_ahead,
+ timer:sleep(infinity)
+ end),
+ receive go_ahead -> ok end,
+ {fail, bad_certificate}.
+
+verify_pass_always(_Certificate, _Event, State) ->
+ %% Create an ETS table, to record the fact that the verify function ran.
+ %% Spawn a new process, to avoid the ETS table disappearing.
+ Parent = self(),
+ spawn(
+ fun() ->
+ ets:new(verify_fun_ran, [public, named_table]),
+ ets:insert(verify_fun_ran, {verify_pass_always_ran, true}),
+ Parent ! go_ahead,
+ timer:sleep(infinity)
+ end),
+ receive go_ahead -> ok end,
+ {valid, State}.
+
+%% ssl_crl_cache_api callbacks
+lookup(_DistributionPoint, _DbHandle) ->
+ not_available.
+
+select({rdnSequence, NameParts}, {NodeDir, _}) ->
+ %% Extract the CN from the issuer name...
+ [CN] = [CN ||
+ [#'AttributeTypeAndValue'{
+ type = ?'id-at-commonName',
+ value = <<_, _, CN/binary>>}] <- NameParts],
+ %% ...and use that as the directory name to find the CRL.
+ error_logger:info_report([{found_cn, CN}]),
+ CRLFile = filename:join([NodeDir, CN, "crl.pem"]),
+ {ok, PemBin} = file:read_file(CRLFile),
+ PemEntries = public_key:pem_decode(PemBin),
+ CRLs = [ CRL || {'CertificateList', CRL, not_encrypted}
+ <- PemEntries],
+ CRLs.
+
+fresh_crl(_DistributionPoint, CRL) ->
+ CRL.
diff --git a/lib/ssl/test/ssl_engine_SUITE.erl b/lib/ssl/test/ssl_engine_SUITE.erl
new file mode 100644
index 0000000000..8025e4e0ed
--- /dev/null
+++ b/lib/ssl/test/ssl_engine_SUITE.erl
@@ -0,0 +1,162 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(ssl_engine_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+all() ->
+ [
+ private_key
+ ].
+
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ case crypto:info_lib() of
+ [{_,_, <<"OpenSSL 1.0.1s-freebsd 1 Mar 2016">>}] ->
+ {skip, "Problem with engine on OpenSSL 1.0.1s-freebsd"};
+ _ ->
+ ssl_test_lib:clean_start(),
+ case crypto:get_test_engine() of
+ {ok, EngineName} ->
+ try crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, EngineName},
+ <<"LOAD">>],
+ []) of
+ {ok, Engine} ->
+ [{engine, Engine} |Config];
+ {error, Reason} ->
+ ct:pal("Reason ~p", [Reason]),
+ {skip, "No dynamic engine support"}
+ catch error:notsup ->
+ {skip, "No engine support in OpenSSL"}
+ end;
+ {error, notexist} ->
+ {skip, "Test engine not found"}
+ end
+ end
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(Config) ->
+ Engine = proplists:get_value(engine, Config),
+ crypto:engine_unload(Engine),
+ ssl:stop(),
+ application:stop(crypto).
+
+
+init_per_testcase(_TestCase, Config) ->
+ ssl:stop(),
+ ssl:start(),
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:timetrap({seconds, 10}),
+ Config.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+private_key(Config) when is_list(Config) ->
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "client_engine"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "server_engine"]),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = GenCertData =
+ 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)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ [{server_config, FileServerConf},
+ {client_config, FileClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+
+ Engine = proplists:get_value(engine, Config),
+
+ ClientKey = engine_key(FileClientConf),
+ ServerKey = engine_key(FileServerConf),
+
+ EngineClientConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ClientKey}} | proplists:delete(key, ClientConf)],
+
+ EngineServerConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ServerKey}} | proplists:delete(key, ServerConf)],
+
+ EngineFileClientConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ClientKey}} |
+ proplists:delete(keyfile, FileClientConf)],
+
+ EngineFileServerConf = [{key, #{algorithm => rsa,
+ engine => Engine,
+ key_id => ServerKey}} |
+ proplists:delete(keyfile, FileServerConf)],
+
+ %% Test with engine
+ test_tls_connection(EngineServerConf, EngineClientConf, Config),
+
+ %% Test with engine and present file arugments
+ test_tls_connection(EngineFileServerConf, EngineFileClientConf, Config),
+
+ %% Test that sofware fallback is available
+ test_tls_connection(ServerConf, [{reuse_sessions, false} |ClientConf], Config).
+
+engine_key(Conf) ->
+ FileStr = proplists:get_value(keyfile, Conf),
+ list_to_binary(FileStr).
+
+
+test_tls_connection(ServerConf, ClientConf, Config) ->
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{verify, verify_peer}
+ | ServerConf]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, [{verify, verify_peer} | ClientConf]}]),
+
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index a671e3e307..c492c54066 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
all() -> [decode_hello_handshake,
+ decode_hello_handshake_version_confusion,
decode_single_hello_extension_correctly,
decode_supported_elliptic_curves_hello_extension_correctly,
decode_unknown_hello_extension_correctly,
@@ -60,7 +61,7 @@ init_per_testcase(ignore_hassign_extension_pre_tls_1_2, Config0) ->
ok ->
case is_supported(sha512) of
true ->
- ssl:start(),
+ ssl_test_lib:clean_start(),
%% make rsa certs using oppenssl
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
proplists:get_value(priv_dir, Config0)),
@@ -106,6 +107,14 @@ decode_hello_handshake(_Config) ->
#renegotiation_info{renegotiated_connection = <<0>>}
= (Hello#server_hello.extensions)#hello_extensions.renegotiation_info.
+
+decode_hello_handshake_version_confusion(_) ->
+ HelloPacket = <<3,3,0,0,0,0,0,63,210,235,149,6,244,140,108,13,177,74,16,218,33,108,219,41,73,228,3,82,132,123,73,144,118,100,0,0,32,192,4,0,10,192,45,192,38,0,47,192,18,0,163,0,22,0,165,192,29,192,18,192,30,0,103,0,57,192,48,0,47,1,0>>,
+ Version = {3,3},
+ ClientHello = 1,
+ Hello = tls_handshake:decode_handshake({3,3}, ClientHello, HelloPacket, false),
+ Hello = tls_handshake:decode_handshake({3,3}, ClientHello, HelloPacket, true).
+
decode_single_hello_extension_correctly(_Config) ->
Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
Extensions = ssl_handshake:decode_hello_extensions(Renegotiation),
@@ -148,7 +157,7 @@ decode_single_hello_sni_extension_correctly(_Config) ->
Exts = Decoded.
decode_empty_server_sni_correctly(_Config) ->
- Exts = #hello_extensions{sni = ""},
+ Exts = #hello_extensions{sni = #sni{hostname = ""}},
SNI = <<?UINT16(?SNI_EXT),?UINT16(0)>>,
Decoded = ssl_handshake:decode_hello_extensions(SNI),
Exts = Decoded.
diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
index c55fa73cfb..6bf2aa2786 100644
--- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_handshake_SUITE.erl
@@ -68,7 +68,7 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
+ ssl_test_lib:clean_start(),
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config),
proplists:get_value(priv_dir, Config)),
ssl_test_lib:cert_options(Config)
@@ -95,8 +95,13 @@ init_per_group(GroupName, Config) ->
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
diff --git a/lib/ssl/test/ssl_npn_hello_SUITE.erl b/lib/ssl/test/ssl_npn_hello_SUITE.erl
index 00eb9fee4f..35af666e9e 100644
--- a/lib/ssl/test/ssl_npn_hello_SUITE.erl
+++ b/lib/ssl/test/ssl_npn_hello_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,6 +41,19 @@ all() ->
create_server_hello_with_advertised_protocols_test,
create_server_hello_with_no_advertised_protocols_test].
+init_per_suite(Config) ->
+ catch crypto:stop(),
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+
+end_per_suite(_Config) ->
+ %% This function is required since init_per_suite/1 exists.
+ ok.
+
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:timetrap({seconds, 5}),
@@ -126,15 +139,12 @@ create_server_handshake(Npn) ->
}, Vsn).
create_connection_states() ->
- #connection_states{
- pending_read = #connection_state{
- security_parameters = #security_parameters{
+ #{pending_read => #{security_parameters => #security_parameters{
server_random = <<1:256>>,
compression_algorithm = 1,
cipher_suite = ?TLS_DHE_DSS_WITH_DES_CBC_SHA
}
- },
- current_read = #connection_state {
- secure_renegotiation = false
- }
- }.
+ },
+ current_read => #{secure_renegotiation => false
+ }
+ }.
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index e49d432c21..3261244ace 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -41,9 +41,9 @@
-define(MANY, 1000).
-define(SOME, 50).
--define(BASE_TIMEOUT_SECONDS, 15).
--define(SOME_SCALE, 20).
--define(MANY_SCALE, 20).
+-define(BASE_TIMEOUT_SECONDS, 5).
+-define(SOME_SCALE, 2).
+-define(MANY_SCALE, 3).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
@@ -53,28 +53,36 @@ all() ->
{group, 'tlsv1.2'},
{group, 'tlsv1.1'},
{group, 'tlsv1'},
- {group, 'sslv3'}
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
].
groups() ->
- [{'tlsv1.2', [], packet_tests()},
- {'tlsv1.1', [], packet_tests()},
- {'tlsv1', [], packet_tests()},
- {'sslv3', [], packet_tests()}
+ [{'tlsv1.2', [], socket_packet_tests() ++ protocol_packet_tests()},
+ {'tlsv1.1', [], socket_packet_tests() ++ protocol_packet_tests()},
+ {'tlsv1', [], socket_packet_tests() ++ protocol_packet_tests()},
+ {'sslv3', [], socket_packet_tests() ++ protocol_packet_tests()},
+ %% We will not support any packet types if the transport is
+ %% not reliable. We might support it for DTLS over SCTP in the future
+ {'dtlsv1.2', [], [reject_packet_opt]},
+ {'dtlsv1', [], [reject_packet_opt]}
].
-packet_tests() ->
- active_packet_tests() ++ active_once_packet_tests() ++ passive_packet_tests() ++
- [packet_send_to_large,
- packet_cdr_decode, packet_cdr_decode_list,
+socket_packet_tests() ->
+ socket_active_packet_tests() ++ socket_active_once_packet_tests() ++
+ socket_passive_packet_tests() ++ [packet_send_to_large, packet_tpkt_decode, packet_tpkt_decode_list].
+
+protocol_packet_tests() ->
+ protocol_active_packet_tests() ++ protocol_active_once_packet_tests() ++ protocol_passive_packet_tests() ++
+ [packet_cdr_decode, packet_cdr_decode_list,
packet_http_decode, packet_http_decode_list,
packet_http_bin_decode_multi,
packet_line_decode, packet_line_decode_list,
packet_asn1_decode, packet_asn1_decode_list,
- packet_tpkt_decode, packet_tpkt_decode_list,
packet_sunrm_decode, packet_sunrm_decode_list].
-passive_packet_tests() ->
+socket_passive_packet_tests() ->
[packet_raw_passive_many_small,
packet_0_passive_many_small,
packet_1_passive_many_small,
@@ -85,12 +93,8 @@ passive_packet_tests() ->
packet_1_passive_some_big,
packet_2_passive_some_big,
packet_4_passive_some_big,
- packet_httph_passive,
- packet_httph_bin_passive,
- packet_http_error_passive,
packet_wait_passive,
packet_size_passive,
- packet_baddata_passive,
%% inet header option should be deprecated!
header_decode_one_byte_passive,
header_decode_two_bytes_passive,
@@ -98,7 +102,14 @@ passive_packet_tests() ->
header_decode_two_bytes_one_sent_passive
].
-active_once_packet_tests() ->
+protocol_passive_packet_tests() ->
+ [packet_httph_passive,
+ packet_httph_bin_passive,
+ packet_http_error_passive,
+ packet_baddata_passive
+ ].
+
+socket_active_once_packet_tests() ->
[packet_raw_active_once_many_small,
packet_0_active_once_many_small,
packet_1_active_once_many_small,
@@ -108,12 +119,16 @@ active_once_packet_tests() ->
packet_0_active_once_some_big,
packet_1_active_once_some_big,
packet_2_active_once_some_big,
- packet_4_active_once_some_big,
+ packet_4_active_once_some_big
+ ].
+
+protocol_active_once_packet_tests() ->
+ [
packet_httph_active_once,
packet_httph_bin_active_once
].
-active_packet_tests() ->
+socket_active_packet_tests() ->
[packet_raw_active_many_small,
packet_0_active_many_small,
packet_1_active_many_small,
@@ -124,10 +139,7 @@ active_packet_tests() ->
packet_1_active_some_big,
packet_2_active_some_big,
packet_4_active_some_big,
- packet_httph_active,
- packet_httph_bin_active,
packet_wait_active,
- packet_baddata_active,
packet_size_active,
%% inet header option should be deprecated!
header_decode_one_byte_active,
@@ -136,11 +148,18 @@ active_packet_tests() ->
header_decode_two_bytes_one_sent_active
].
+
+protocol_active_packet_tests() ->
+ [packet_httph_active,
+ packet_httph_bin_active,
+ packet_baddata_active
+ ].
+
init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
+ ssl_test_lib:clean_start(),
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config),
proplists:get_value(priv_dir, Config)),
ssl_test_lib:cert_options(Config)
@@ -162,13 +181,19 @@ init_per_group(GroupName, Config) ->
{skip, "Missing crypto support"}
end;
_ ->
+ ssl:stop(),
ssl:start(),
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
init_per_testcase(_TestCase, Config) ->
ct:timetrap({seconds, ?BASE_TIMEOUT_SECONDS}),
@@ -276,6 +301,7 @@ packet_raw_active_once_many_small() ->
[{doc,"Test packet option {packet, raw} in active once mode."}].
packet_raw_active_once_many_small(Config) when is_list(Config) ->
+ ct:timetrap({seconds, ?BASE_TIMEOUT_SECONDS * ?MANY_SCALE}),
Data = "Packet option is {packet, raw}",
packet(Config, Data, send_raw, active_once_raw, ?MANY, raw, once).
@@ -392,6 +418,7 @@ packet_0_active_some_big() ->
[{doc,"Test packet option {packet, 0} in active mode."}].
packet_0_active_some_big(Config) when is_list(Config) ->
+ ct:timetrap({seconds, ?BASE_TIMEOUT_SECONDS * ?SOME_SCALE}),
Data = lists:append(lists:duplicate(100, "1234567890")),
packet(Config, Data, send, active_raw, ?SOME, 0, true).
@@ -427,6 +454,7 @@ packet_2_active_some_big() ->
[{doc,"Test packet option {packet, 2} in active mode"}].
packet_2_active_some_big(Config) when is_list(Config) ->
+ ct:timetrap({seconds, ?BASE_TIMEOUT_SECONDS * ?SOME_SCALE}),
Data = lists:append(lists:duplicate(100, "1234567890")),
packet(Config, Data, send, active_packet, ?SOME, 2, true).
@@ -1898,8 +1926,52 @@ header_decode_two_bytes_one_sent_passive(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+reject_packet_opt() ->
+ [{doc,"Test packet option is rejected for DTLS over udp"}].
+
+reject_packet_opt(Config) when is_list(Config) ->
+
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+
+ {error,{options,{not_supported,{packet,4}}}} =
+ ssl:listen(9999, [{packet, 4} | ServerOpts]),
+ {error,{options,{not_supported,{packet_size,1}}}} =
+ ssl:listen(9999, [{packet_size, 1} | ServerOpts]),
+ {error,{options,{not_supported,{header,1}}}} =
+ ssl:listen(9999, [{header, 1} | ServerOpts]),
+
+ client_reject_packet_opt(Config, {packet,4}),
+ client_reject_packet_opt(Config, {packet_size, 1}),
+ client_reject_packet_opt(Config, {header, 1}).
+
+%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
+
+packet(Config, Data, Send, Recv, Quantity, Packet, Active) when Packet == 0;
+ Packet == raw ->
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, Send ,[Data, Quantity]}},
+ {options, [{nodelay, true},{packet, Packet} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, Recv, [Data, Quantity]}},
+ {options, [{active, Active}, {nodelay, true},
+ {packet, Packet} |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, ok),
+
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client);
+
packet(Config, Data, Send, Recv, Quantity, Packet, Active) ->
ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
@@ -1944,14 +2016,14 @@ passive_recv_packet(Socket, _, 0) ->
{error, timeout} = ssl:recv(Socket, 0, 500),
ok;
Other ->
- {other, Other, ssl:session_info(Socket), 0}
+ {other, Other, ssl:connection_information(Socket, [session_id, cipher_suite]), 0}
end;
passive_recv_packet(Socket, Data, N) ->
case ssl:recv(Socket, 0) of
{ok, Data} ->
passive_recv_packet(Socket, Data, N-1);
Other ->
- {other, Other, ssl:session_info(Socket), N}
+ {other, Other, ssl:connection_information(Socket, [session_id, cipher_suite]), N}
end.
send(Socket,_, 0) ->
@@ -1982,26 +2054,19 @@ active_once_raw(Socket, Data, N) ->
active_once_raw(_, _, 0, _) ->
ok;
-active_once_raw(Socket, Data, N, Acc) ->
- receive
- {ssl, Socket, Byte} when length(Byte) == 1 ->
- ssl:setopts(Socket, [{active, once}]),
+active_once_raw(Socket, Data, N, Acc0) ->
+ case lists:prefix(Data, Acc0) of
+ true ->
+ DLen = length(Data),
+ Start = DLen + 1,
+ Len = length(Acc0) - DLen,
+ Acc = string:substr(Acc0, Start, Len),
+ active_once_raw(Socket, Data, N-1, Acc);
+ false ->
receive
- {ssl, Socket, _} ->
+ {ssl, Socket, Info} ->
ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N-1, [])
- end;
- {ssl, Socket, Data} ->
- ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N-1, []);
- {ssl, Socket, Other} ->
- case Acc ++ Other of
- Data ->
- ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N-1, []);
- NewAcc ->
- ssl:setopts(Socket, [{active, once}]),
- active_once_raw(Socket, Data, N, NewAcc)
+ active_once_raw(Socket, Data, N, Acc0 ++ Info)
end
end.
@@ -2010,7 +2075,7 @@ active_once_packet(Socket,_, 0) ->
{ssl, Socket, []} ->
ok;
{ssl, Socket, Other} ->
- {other, Other, ssl:session_info(Socket), 0}
+ {other, Other, ssl:connection_information(Socket, [session_id, cipher_suite]), 0}
end;
active_once_packet(Socket, Data, N) ->
receive
@@ -2055,7 +2120,7 @@ active_packet(Socket, _, 0) ->
{ssl, Socket, []} ->
ok;
Other ->
- {other, Other, ssl:session_info(Socket), 0}
+ {other, Other, ssl:connection_information(Socket, [session_id, cipher_suite]), 0}
end;
active_packet(Socket, Data, N) ->
receive
@@ -2067,7 +2132,7 @@ active_packet(Socket, Data, N) ->
{ssl, Socket, Data} ->
active_packet(Socket, Data, N -1);
Other ->
- {other, Other, ssl:session_info(Socket),N}
+ {other, Other, ssl:connection_information(Socket, [session_id, cipher_suite]),N}
end.
assert_packet_opt(Socket, Type) ->
@@ -2201,3 +2266,23 @@ add_tpkt_header(IOList) when is_list(IOList) ->
Binary = list_to_binary(IOList),
L = size(Binary) + 4,
[3, 0, ((L) bsr 8) band 16#ff, (L) band 16#ff , Binary].
+
+
+client_reject_packet_opt(Config, PacketOpt) ->
+ ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result_msg ,[]}},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client_error([{node, ServerNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, no_result_msg, []}},
+ {options, [PacketOpt |
+ ClientOpts]}]),
+
+ ssl_test_lib:check_result(Client, {error, {options, {not_supported, PacketOpt}}}).
diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl
index cb0571d0a7..ef05241759 100644
--- a/lib/ssl/test/ssl_payload_SUITE.erl
+++ b/lib/ssl/test/ssl_payload_SUITE.erl
@@ -70,7 +70,7 @@ init_per_suite(Config) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
+ ssl_test_lib:clean_start(),
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config), proplists:get_value(priv_dir, Config)),
ssl_test_lib:cert_options(Config)
catch _:_ ->
@@ -95,8 +95,13 @@ init_per_group(GroupName, Config) ->
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge;
TestCase == server_echos_active_once_huge;
@@ -104,8 +109,13 @@ init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_huge;
TestCase == client_echos_passive_huge;
TestCase == client_echos_active_once_huge;
TestCase == client_echos_active_huge ->
- ct:timetrap({seconds, 90}),
- Config;
+ case erlang:system_info(system_architecture) of
+ "sparc-sun-solaris2.10" ->
+ {skip,"Will take to long time on an old Sparc"};
+ _ ->
+ ct:timetrap({seconds, 90}),
+ Config
+ end;
init_per_testcase(TestCase, Config) when TestCase == server_echos_passive_big;
TestCase == server_echos_active_once_big;
diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl
index 13b0ce8ed9..96b15d9b51 100644
--- a/lib/ssl/test/ssl_pem_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
+ ssl_test_lib:clean_start(),
%% make rsa certs using oppenssl
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
proplists:get_value(priv_dir, Config0)),
@@ -63,14 +63,15 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(pem_cleanup = Case, Config) ->
- end_per_testcase(Case, Config) ,
application:load(ssl),
+ end_per_testcase(Case, Config) ,
application:set_env(ssl, ssl_pem_cache_clean, ?CLEANUP_INTERVAL),
ssl:start(),
ct:timetrap({minutes, 1}),
Config.
end_per_testcase(_TestCase, Config) ->
+ ssl_test_lib:clean_env(),
ssl:stop(),
Config.
@@ -81,8 +82,8 @@ pem_cleanup() ->
[{doc, "Test pem cache invalidate mechanism"}].
pem_cleanup(Config)when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = proplists:get_value(client_opts, Config),
- ServerOpts = proplists:get_value(server_opts, Config),
+ ClientOpts = proplists:get_value(client_verification_opts, Config),
+ ServerOpts = proplists:get_value(server_verification_opts, Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server =
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index b352844ba0..9862b3ce64 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
+ ssl_test_lib:clean_start(),
%% make rsa certs using
{ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
proplists:get_value(priv_dir, Config0)),
diff --git a/lib/ssl/test/ssl_sni_SUITE.erl b/lib/ssl/test/ssl_sni_SUITE.erl
index 34ef2e6af9..7e78c41444 100644
--- a/lib/ssl/test/ssl_sni_SUITE.erl
+++ b/lib/ssl/test/ssl_sni_SUITE.erl
@@ -25,26 +25,61 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/inet.hrl").
+
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
%%--------------------------------------------------------------------
-all() -> [no_sni_header,
- sni_match,
- sni_no_match,
- no_sni_header_fun,
- sni_match_fun,
- sni_no_match_fun].
+all() ->
+ [{group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}
+ ].
+
+groups() ->
+ [
+ {'tlsv1.2', [], sni_tests()},
+ {'tlsv1.1', [], sni_tests()},
+ {'tlsv1', [], sni_tests()},
+ {'sslv3', [], sni_tests()},
+ {'dtlsv1.2', [], sni_tests()},
+ {'dtlsv1', [], sni_tests()}
+ ].
+
+sni_tests() ->
+ [no_sni_header,
+ sni_match,
+ sni_no_match,
+ no_sni_header_fun,
+ sni_match_fun,
+ sni_no_match_fun,
+ dns_name,
+ ip_fallback,
+ no_ip_fallback,
+ dns_name_reuse].
init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- ssl_test_lib:cert_options(Config0)
+ ssl_test_lib:clean_start(),
+ Config = ssl_test_lib:make_rsa_cert(Config0),
+ RsaOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ [{sni_server_opts, [{sni_hosts, [
+ {"a.server", [
+ {certfile, proplists:get_value(certfile, RsaOpts)},
+ {keyfile, proplists:get_value(keyfile, RsaOpts)}
+ ]},
+ {"b.server", [
+ {certfile, proplists:get_value(certfile, RsaOpts)},
+ {keyfile, proplists:get_value(keyfile, RsaOpts)}
+ ]}
+ ]}]} | Config]
catch _:_ ->
{skip, "Crypto did not start"}
end.
@@ -53,6 +88,13 @@ end_per_suite(_) ->
ssl:stop(),
application:stop(crypto).
+init_per_testcase(TestCase, Config) when TestCase == ip_fallback;
+ TestCase == no_ip_fallback;
+ TestCase == dns_name_reuse ->
+ ssl_test_lib:ct_log_supported_protocol_versions(Config),
+ ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
+ ct:timetrap({seconds, 20}),
+ Config;
init_per_testcase(_TestCase, Config) ->
ssl_test_lib:ct_log_supported_protocol_versions(Config),
ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
@@ -66,24 +108,136 @@ end_per_testcase(_TestCase, Config) ->
%% Test Cases --------------------------------------------------------
%%--------------------------------------------------------------------
no_sni_header(Config) ->
- run_handshake(Config, undefined, undefined, "server").
+ run_handshake(Config, undefined, undefined, "server Peer cert").
no_sni_header_fun(Config) ->
- run_sni_fun_handshake(Config, undefined, undefined, "server").
+ run_sni_fun_handshake(Config, undefined, undefined, "server Peer cert").
sni_match(Config) ->
- run_handshake(Config, "a.server", "a.server", "a.server").
+ run_handshake(Config, "a.server", "a.server", "server Peer cert").
sni_match_fun(Config) ->
- run_sni_fun_handshake(Config, "a.server", "a.server", "a.server").
+ run_sni_fun_handshake(Config, "a.server", "a.server", "server Peer cert").
sni_no_match(Config) ->
- run_handshake(Config, "c.server", undefined, "server").
+ run_handshake(Config, "c.server", undefined, "server Peer cert").
sni_no_match_fun(Config) ->
- run_sni_fun_handshake(Config, "c.server", undefined, "server").
+ run_sni_fun_handshake(Config, "c.server", undefined, "server Peer cert").
+
+dns_name(Config) ->
+ Hostname = "OTP.test.server",
+ #{server_config := ServerConf,
+ client_config := ClientConf} = 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)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false}]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], undefined, Config),
+ successfull_connect(ServerConf, [{verify, verify_peer}, {server_name_indication, Hostname} | ClientConf], undefined, Config),
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer}, {server_name_indication, "foo"} | ClientConf], undefined, Config),
+ successfull_connect(ServerConf, [{verify, verify_peer}, {server_name_indication, disable} | ClientConf], undefined, Config).
+
+ip_fallback(Config) ->
+ Hostname = net_adm:localhost(),
+ {ok, #hostent{h_addr_list = [IP |_]}} = inet:gethostbyname(net_adm:localhost()),
+ IPStr = tuple_to_list(IP),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = 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)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname},
+ {iPAddress, IPStr}],
+ critical = false}]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], Hostname, Config),
+ successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config).
+no_ip_fallback(Config) ->
+ Hostname = net_adm:localhost(),
+ {ok, #hostent{h_addr_list = [IP |_]}} = inet:gethostbyname(net_adm:localhost()),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = 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)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false}]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+ successfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], Hostname, Config),
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], IP, Config).
+dns_name_reuse(Config) ->
+ SNIHostname = "OTP.test.server",
+ #{server_config := ServerConf,
+ client_config := ClientConf} = 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)}]],
+ peer => [{extensions, [#'Extension'{extnID =
+ ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, SNIHostname}],
+ critical = false}
+ ]},
+ {key, ssl_test_lib:hardcode_rsa_key(3)}
+ ]},
+ client_chain =>
+ #{root => [{key, ssl_test_lib:hardcode_rsa_key(4)}],
+ intermediates => [[{key, ssl_test_lib:hardcode_rsa_key(5)}]],
+ peer => [{key, ssl_test_lib:hardcode_rsa_key(6)}]}}),
+
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ unsuccessfull_connect(ServerConf, [{verify, verify_peer} | ClientConf], undefined, Config),
+
+ Server =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {options, ServerConf}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client0 =
+ ssl_test_lib:start_client([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, no_result, []}},
+ {from, self()}, {options, [{verify, verify_peer},
+ {server_name_indication, SNIHostname} | ClientConf]}]),
+ receive
+ {Server, _} ->
+ ok
+ end,
+
+ Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}},
+
+ %% Make sure session is registered
+ ct:sleep(1000),
+
+ Client1 =
+ ssl_test_lib:start_client_error([{node, ClientNode},
+ {port, Port}, {host, Hostname},
+ {mfa, {ssl_test_lib, session_info_result, []}},
+ {from, self()}, {options, [{verify, verify_peer} | ClientConf]}]),
+
+ ssl_test_lib:check_result(Client1, {error, {tls_alert, "handshake failure"}}),
+ ssl_test_lib:close(Client0).
%%--------------------------------------------------------------------
%% Internal Functions ------------------------------------------------
%%--------------------------------------------------------------------
@@ -141,13 +295,13 @@ run_sni_fun_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
[Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
[{sni_hosts, ServerSNIConf}] = proplists:get_value(sni_server_opts, Config),
SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end,
- ServerOptions = proplists:get_value(server_opts, Config) ++ [{sni_fun, SNIFun}],
+ ServerOptions = ssl_test_lib:ssl_options(server_rsa_opts, Config) ++ [{sni_fun, SNIFun}],
ClientOptions =
case SNIHostname of
undefined ->
- proplists:get_value(client_opts, Config);
+ ssl_test_lib:ssl_options(client_rsa_opts, Config);
_ ->
- [{server_name_indication, SNIHostname}] ++ proplists:get_value(client_opts, Config)
+ [{server_name_indication, SNIHostname}] ++ ssl_test_lib:ssl_options(client_rsa_opts, Config)
end,
ct:log("Options: ~p", [[ServerOptions, ClientOptions]]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -167,14 +321,14 @@ run_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
ct:log("Start running handshake, Config: ~p, SNIHostname: ~p, "
"ExpectedSNIHostname: ~p, ExpectedCN: ~p",
[Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
- ServerOptions = proplists:get_value(sni_server_opts, Config) ++ proplists:get_value(server_opts, Config),
+ ServerOptions = proplists:get_value(sni_server_opts, Config) ++ ssl_test_lib:ssl_options(server_rsa_opts, Config),
ClientOptions =
- case SNIHostname of
- undefined ->
- proplists:get_value(client_opts, Config);
- _ ->
- [{server_name_indication, SNIHostname}] ++ proplists:get_value(client_opts, Config)
- end,
+ case SNIHostname of
+ undefined ->
+ ssl_test_lib:ssl_options(client_rsa_opts, Config);
+ _ ->
+ [{server_name_indication, SNIHostname}] ++ ssl_test_lib:ssl_options(client_rsa_opts, Config)
+ end,
ct:log("Options: ~p", [[ServerOptions, ClientOptions]]),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -188,3 +342,37 @@ run_handshake(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
ssl_test_lib:check_result(Server, ExpectedSNIHostname, Client, ExpectedCN),
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+
+successfull_connect(ServerOptions, ClientOptions, Hostname0, Config) ->
+ {ClientNode, ServerNode, Hostname1} = ssl_test_lib:run_where(Config),
+ Hostname = host_name(Hostname0, Hostname1),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()}, {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ServerOptions}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname}, {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result_active, []}},
+ {options, ClientOptions}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+unsuccessfull_connect(ServerOptions, ClientOptions, Hostname0, Config) ->
+ {ClientNode, ServerNode, Hostname1} = ssl_test_lib:run_where(Config),
+ Hostname = host_name(Hostname0, Hostname1),
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOptions}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options, ClientOptions}]),
+
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "handshake failure"}},
+ Client, {error, {tls_alert, "handshake failure"}}).
+host_name(undefined, Hostname) ->
+ Hostname;
+host_name(Hostname, _) ->
+ Hostname.
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 27c670cdc2..3e6c5e8b8a 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,13 +34,13 @@
run_where(_) ->
ClientNode = node(),
ServerNode = node(),
- {ok, Host} = rpc:call(ServerNode, inet, gethostname, []),
+ Host = rpc:call(ServerNode, net_adm, localhost, []),
{ClientNode, ServerNode, Host}.
run_where(_, ipv6) ->
ClientNode = node(),
ServerNode = node(),
- {ok, Host} = rpc:call(ServerNode, inet, gethostname, []),
+ Host = rpc:call(ServerNode, net_adm, localhost, []),
{ClientNode, ServerNode, Host}.
node_to_hostip(Node) ->
@@ -278,8 +278,11 @@ check_result(Server, ServerMsg, Client, ClientMsg) ->
check_result(Server, ServerMsg);
{Port, {data,Debug}} when is_port(Port) ->
- ct:log("~p:~p~nopenssl ~s~n",[?MODULE,?LINE, Debug]),
+ ct:log("~p:~p~n Openssl ~s~n",[?MODULE,?LINE, Debug]),
check_result(Server, ServerMsg, Client, ClientMsg);
+ {Port,closed} when is_port(Port) ->
+ ct:log("~p:~p~n Openssl port ~n",[?MODULE,?LINE]),
+ check_result(Server, ServerMsg, Client, ClientMsg);
Unexpected ->
Reason = {{expected, {Client, ClientMsg}},
{expected, {Server, ServerMsg}}, {got, Unexpected}},
@@ -291,11 +294,11 @@ check_result(Pid, Msg) ->
{Pid, Msg} ->
ok;
{Port, {data,Debug}} when is_port(Port) ->
- ct:log("~p:~p~nopenssl ~s~n",[?MODULE,?LINE, Debug]),
+ ct:log("~p:~p~n Openssl ~s~n",[?MODULE,?LINE, Debug]),
check_result(Pid,Msg);
- %% {Port, {exit_status, Status}} when is_port(Port) ->
- %% ct:log("~p:~p Exit status: ~p~n",[?MODULE,?LINE, Status]),
- %% check_result(Pid, Msg);
+ {Port,closed} when is_port(Port)->
+ ct:log("~p:~p Openssl port closed ~n",[?MODULE,?LINE]),
+ check_result(Pid, Msg);
Unexpected ->
Reason = {{expected, {Pid, Msg}},
{got, Unexpected}},
@@ -381,11 +384,9 @@ cert_options(Config) ->
"badkey.pem"]),
PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
- SNIServerACertFile = filename:join([proplists:get_value(priv_dir, Config), "a.server", "cert.pem"]),
- SNIServerAKeyFile = filename:join([proplists:get_value(priv_dir, Config), "a.server", "key.pem"]),
- SNIServerBCertFile = filename:join([proplists:get_value(priv_dir, Config), "b.server", "cert.pem"]),
- SNIServerBKeyFile = filename:join([proplists:get_value(priv_dir, Config), "b.server", "key.pem"]),
- [{client_opts, []},
+ [{client_opts, [{cacertfile, ClientCaCertFile},
+ {certfile, ClientCertFile},
+ {keyfile, ClientKeyFile}]},
{client_verification_opts, [{cacertfile, ServerCaCertFile},
{certfile, ClientCertFile},
{keyfile, ClientKeyFile},
@@ -394,29 +395,24 @@ cert_options(Config) ->
{certfile, ClientCertFileDigitalSignatureOnly},
{keyfile, ClientKeyFile},
{ssl_imp, new}]},
- {server_opts, [{ssl_imp, new},{reuseaddr, true},
+ {server_opts, [{ssl_imp, new},{reuseaddr, true}, {cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_anon, [{ssl_imp, new},{reuseaddr, true}, {ciphers, anonymous_suites()}]},
- {client_psk, [{ssl_imp, new},{reuseaddr, true},
+ {client_psk, [{ssl_imp, new},
{psk_identity, "Test-User"},
{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
{server_psk, [{ssl_imp, new},{reuseaddr, true},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}},
- {ciphers, psk_suites()}]},
+ {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
{server_psk_hint, [{ssl_imp, new},{reuseaddr, true},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile},
{psk_identity, "HINT"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}},
- {ciphers, psk_suites()}]},
+ {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
{server_psk_anon, [{ssl_imp, new},{reuseaddr, true},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}},
- {ciphers, psk_anon_suites()}]},
+ {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
{server_psk_anon_hint, [{ssl_imp, new},{reuseaddr, true},
{psk_identity, "HINT"},
- {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}},
- {ciphers, psk_anon_suites()}]},
- {client_srp, [{ssl_imp, new},{reuseaddr, true},
+ {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}}]},
+ {client_srp, [{ssl_imp, new},
{srp_identity, {"Test-User", "secret"}}]},
{server_srp, [{ssl_imp, new},{reuseaddr, true},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile},
@@ -445,65 +441,249 @@ cert_options(Config) ->
{server_bad_cert, [{ssl_imp, new},{cacertfile, ServerCaCertFile},
{certfile, BadCertFile}, {keyfile, ServerKeyFile}]},
{server_bad_key, [{ssl_imp, new},{cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, BadKeyFile}]},
- {sni_server_opts, [{sni_hosts, [
- {"a.server", [
- {certfile, SNIServerACertFile},
- {keyfile, SNIServerAKeyFile}
- ]},
- {"b.server", [
- {certfile, SNIServerBCertFile},
- {keyfile, SNIServerBKeyFile}
- ]}
- ]}]}
+ {certfile, ServerCertFile}, {keyfile, BadKeyFile}]}
| Config].
-make_dsa_cert(Config) ->
+make_dsa_cert(Config) ->
+ CryptoSupport = crypto:supports(),
+ case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of
+ true ->
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+
+ [{server_dsa_opts, ServerConf},
+ {server_dsa_verify_opts, [{verify, verify_peer} | ServerConf]},
+ {client_dsa_opts, ClientConf},
+ {server_srp_dsa, [{user_lookup_fun, {fun user_lookup/3, undefined}},
+ {ciphers, srp_dss_suites()} | ServerConf]},
+ {client_srp_dsa, [{srp_identity, {"Test-User", "secret"}}
+ | ClientConf]}
+ | Config];
+ false ->
+ Config
+ end.
+make_rsa_cert_chains(UserConf, Config, Suffix) ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
+
+make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) ->
+ ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
+
+default_cert_chain_conf() ->
+ %% Use only default options
+ [[],[],[]].
+
+gen_conf(mix, mix, UserClient, UserServer) ->
+ ClientTag = conf_tag("client"),
+ ServerTag = conf_tag("server"),
+
+ DefaultClient = default_cert_chain_conf(),
+ DefaultServer = default_cert_chain_conf(),
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, dsa, dsa, ""),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, dsa, dsa, ""),
- [{server_dsa_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_dsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {verify, verify_peer}]},
- {client_dsa_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]},
- {server_srp_dsa, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {user_lookup_fun, {fun user_lookup/3, undefined}},
- {ciphers, srp_dss_suites()}]},
- {client_srp_dsa, [{ssl_imp, new},{reuseaddr, true},
- {srp_identity, {"Test-User", "secret"}},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}
- | Config].
+ ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
+ ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
+
+ new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]);
+gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) ->
+ ClientTag = conf_tag("client"),
+ ServerTag = conf_tag("server"),
+
+ DefaultClient = chain_spec(client, ClientChainType),
+ DefaultServer = chain_spec(server, ServerChainType),
+
+ ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
+ ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
+
+ new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]).
+
+new_format(Conf) ->
+ CConf = proplists:get_value(client_chain, Conf),
+ SConf = proplists:get_value(server_chain, Conf),
+ #{server_chain => proplist_to_map(SConf),
+ client_chain => proplist_to_map(CConf)}.
+
+proplist_to_map([Head | Rest]) ->
+ [Last | Tail] = lists:reverse(Rest),
+ #{root => Head,
+ intermediates => lists:reverse(Tail),
+ peer => Last}.
+
+conf_tag(Role) ->
+ list_to_atom(Role ++ "_chain").
+
+chain_spec(_Role, ecdh_rsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+
+chain_spec(_Role, ecdhe_ecdsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+
+chain_spec(_Role, ecdh_ecdsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+chain_spec(_Role, ecdhe_rsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ [[Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, hardcode_rsa_key(3)}]];
+chain_spec(_Role, ecdsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, {namedCurve, CurveOid}}]];
+chain_spec(_Role, rsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ [[Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, hardcode_rsa_key(3)}]];
+chain_spec(_Role, dsa) ->
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ [[Digest, {key, hardcode_dsa_key(1)}],
+ [Digest, {key, hardcode_dsa_key(2)}],
+ [Digest, {key, hardcode_dsa_key(3)}]].
+
+merge_chain_spec([], [], Acc)->
+ lists:reverse(Acc);
+merge_chain_spec([User| UserRest], [Default | DefaultRest], Acc) ->
+ Merge = merge_spec(User, Default, confs(), []),
+ merge_chain_spec(UserRest, DefaultRest, [Merge | Acc]).
+
+confs() ->
+ [key, digest, validity, extensions].
+
+merge_spec(_, _, [], Acc) ->
+ Acc;
+merge_spec(User, Default, [Conf | Rest], Acc) ->
+ case proplists:get_value(Conf, User, undefined) of
+ undefined ->
+ case proplists:get_value(Conf, Default, undefined) of
+ undefined ->
+ merge_spec(User, Default, Rest, Acc);
+ Value ->
+ merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
+ end;
+ Value ->
+ merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
+ end.
+
+make_mix_cert(Config) ->
+ Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
+ Digest = {digest, appropriate_sha(crypto:supports())},
+ CurveOid = hd(tls_v1:ecc_curves(0)),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix"]),
+ ClientChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(1)}],
+ [Digest, {key, {namedCurve, CurveOid}}, {extensions, Ext}]
+ ],
+ ServerChain = [[Digest, {key, {namedCurve, CurveOid}}],
+ [Digest, {key, hardcode_rsa_key(2)}],
+ [Digest, {key, {namedCurve, CurveOid}},{extensions, Ext}]
+ ],
+ ClientChainType =ServerChainType = mix,
+ CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ {[{verify, verify_peer} | ClientConf],
+ [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
+ }.
make_ecdsa_cert(Config) ->
CryptoSupport = crypto:supports(),
case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of
- true ->
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, ec, ec, ""),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, ec, ec, ""),
- [{server_ecdsa_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_ecdsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {verify, verify_peer}]},
- {client_ecdsa_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}
+ true ->
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]),
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ [{server_ecdsa_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
+
+ {server_ecdsa_verify_opts, [{ssl_imp, new}, {reuseaddr, true},
+ {verify, verify_peer} | ServerConf]},
+ {client_ecdsa_opts, ClientConf}
| Config];
- _ ->
+ false ->
+ Config
+ end.
+make_rsa_cert(Config) ->
+ CryptoSupport = crypto:supports(),
+ case proplists:get_bool(rsa, proplists:get_value(public_keys, CryptoSupport)) of
+ true ->
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]),
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+ [{server_rsa_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
+
+ {server_rsa_verify_opts, [{ssl_imp, new}, {reuseaddr, true},
+ {verify, verify_peer} | ServerConf]},
+ {client_rsa_opts, ClientConf},
+ {client_rsa_verify_opts, [{verify, verify_peer} |ClientConf]}
+ | Config];
+ false ->
Config
end.
+appropriate_sha(CryptoSupport) ->
+ case proplists:get_bool(sha256, CryptoSupport) of
+ true ->
+ sha256;
+ false ->
+ sha1
+ end.
%% RFC 4492, Sect. 2.3. ECDH_RSA
%%
@@ -513,58 +693,28 @@ make_ecdh_rsa_cert(Config) ->
CryptoSupport = crypto:supports(),
case proplists:get_bool(ecdh, proplists:get_value(public_keys, CryptoSupport)) of
true ->
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, rsa, ec, "rsa_"),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, rsa, ec, "rsa_"),
- [{server_ecdh_rsa_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_ecdh_rsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {verify, verify_peer}]},
- {client_ecdh_rsa_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}
- | Config];
+ ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]),
+ ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]),
+ ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
+ ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
+ CertChainConf = gen_conf(ecdh_rsa, ecdh_rsa, ClientChain, ServerChain),
+ GenCertData = public_key:pkix_test_data(CertChainConf),
+ [{server_config, ServerConf},
+ {client_config, ClientConf}] =
+ x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
+
+ [{server_ecdh_rsa_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
+
+ {server_ecdh_rsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
+ {verify, verify_peer} | ServerConf]},
+
+ {client_ecdh_rsa_opts, ClientConf}
+
+ | Config];
_ ->
Config
end.
-make_mix_cert(Config) ->
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, dsa,
- rsa, "mix"),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, dsa,
- rsa, "mix"),
- [{server_mix_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ServerCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
- {server_mix_verify_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ServerCertFile}, {keyfile, ServerKeyFile},
- {verify, verify_peer}]},
- {client_mix_opts, [{ssl_imp, new},{reuseaddr, true},
- {cacertfile, ClientCaCertFile},
- {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}
- | Config].
-
-make_cert_files(RoleStr, Config, Alg1, Alg2, Prefix) ->
- Alg1Str = atom_to_list(Alg1),
- Alg2Str = atom_to_list(Alg2),
- CaInfo = {CaCert, _} = erl_make_certs:make_cert([{key, Alg1}]),
- {Cert, CertKey} = erl_make_certs:make_cert([{key, Alg2}, {issuer, CaInfo}]),
- CaCertFile = filename:join([proplists:get_value(priv_dir, Config),
- RoleStr, Prefix ++ Alg1Str ++ "_cacerts.pem"]),
- CertFile = filename:join([proplists:get_value(priv_dir, Config),
- RoleStr, Prefix ++ Alg2Str ++ "_cert.pem"]),
- KeyFile = filename:join([proplists:get_value(priv_dir, Config),
- RoleStr, Prefix ++ Alg2Str ++ "_key.pem"]),
-
- der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]),
- der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]),
- der_to_pem(KeyFile, [CertKey]),
- {CaCertFile, CertFile, KeyFile}.
-
-
start_upgrade_server(Args) ->
Result = spawn_link(?MODULE, run_upgrade_server, [Args]),
receive
@@ -748,6 +898,159 @@ accepters(Acc, N) ->
{accepter, _, Server} ->
accepters([Server| Acc], N-1)
end.
+basic_test(COpts, SOpts, Config) ->
+ SType = proplists:get_value(server_type, Config),
+ CType = proplists:get_value(client_type, Config),
+ {Server, Port} = start_server(SType, SOpts, Config),
+ Client = start_client(CType, Port, COpts, Config),
+ gen_check_result(Server, SType, Client, CType),
+ stop(Server, Client).
+
+ecc_test(Expect, COpts, SOpts, CECCOpts, SECCOpts, Config) ->
+ {Server, Port} = start_server_ecc(erlang, SOpts, Expect, SECCOpts, Config),
+ Client = start_client_ecc(erlang, Port, COpts, Expect, CECCOpts, Config),
+ check_result(Server, ok, Client, ok),
+ stop(Server, Client).
+
+ecc_test_error(COpts, SOpts, CECCOpts, SECCOpts, Config) ->
+ {Server, Port} = start_server_ecc_error(erlang, SOpts, SECCOpts, Config),
+ Client = start_client_ecc_error(erlang, Port, COpts, CECCOpts, Config),
+ Error = {error, {tls_alert, "insufficient security"}},
+ check_result(Server, Error, Client, Error).
+
+
+start_client(openssl, Port, ClientOpts, Config) ->
+ Cert = proplists:get_value(certfile, ClientOpts),
+ Key = proplists:get_value(keyfile, ClientOpts),
+ CA = proplists:get_value(cacertfile, ClientOpts),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-verify", "2", "-port", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", Cert, "-CAfile", CA,
+ "-key", Key, "-host","localhost", "-msg", "-debug"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, "Hello world"),
+ OpenSslPort;
+
+start_client(erlang, Port, ClientOpts, Config) ->
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ KeyEx = proplists:get_value(check_keyex, Config, false),
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, check_key_exchange_send_active, [KeyEx]}},
+ {options, [{verify, verify_peer} | ClientOpts]}]).
+
+
+start_client_ecc(erlang, Port, ClientOpts, Expect, ECCOpts, Config) ->
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, check_ecc, [client, Expect]}},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ClientOpts]}]).
+
+start_client_ecc_error(erlang, Port, ClientOpts, ECCOpts, Config) ->
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+ ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ClientOpts]}]).
+
+
+start_server(openssl, ServerOpts, Config) ->
+ Cert = proplists:get_value(certfile, ServerOpts),
+ Key = proplists:get_value(keyfile, ServerOpts),
+ CA = proplists:get_value(cacertfile, ServerOpts),
+ Port = inet_port(node()),
+ Version = protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
+ "-verify", "2", "-cert", Cert, "-CAfile", CA,
+ "-key", Key, "-msg", "-debug"],
+ OpenSslPort = portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, "Hello world"),
+ {OpenSslPort, Port};
+start_server(erlang, ServerOpts, Config) ->
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ KeyEx = proplists:get_value(check_keyex, Config, false),
+ Server = start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ check_key_exchange_send_active,
+ [KeyEx]}},
+ {options, [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+start_server_with_raw_key(erlang, ServerOpts, Config) ->
+ {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ Server = start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib,
+ send_recv_result_active,
+ []}},
+ {options,
+ [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+start_server_ecc(erlang, ServerOpts, Expect, ECCOpts, Config) ->
+ {_, ServerNode, _} = run_where(Config),
+ Server = start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, check_ecc, [server, Expect]}},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+start_server_ecc_error(erlang, ServerOpts, ECCOpts, Config) ->
+ {_, ServerNode, _} = run_where(Config),
+ Server = start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options,
+ ECCOpts ++
+ [{verify, verify_peer} | ServerOpts]}]),
+ {Server, inet_port(Server)}.
+
+gen_check_result(Server, erlang, Client, erlang) ->
+ check_result(Server, ok, Client, ok);
+gen_check_result(Server, erlang, _, _) ->
+ check_result(Server, ok);
+gen_check_result(_, _, Client, erlang) ->
+ check_result(Client, ok);
+gen_check_result(_,openssl, _, openssl) ->
+ ok.
+
+stop(Port1, Port2) when is_port(Port1), is_port(Port2) ->
+ close_port(Port1),
+ close_port(Port2);
+stop(Port, Pid) when is_port(Port) ->
+ close_port(Port),
+ close(Pid);
+stop(Pid, Port) when is_port(Port) ->
+ close_port(Port),
+ close(Pid);
+stop(Client, Server) ->
+ close(Server),
+ close(Client).
+
+supported_eccs(Opts) ->
+ ToCheck = proplists:get_value(eccs, Opts, []),
+ Supported = ssl:eccs(),
+ lists:all(fun(Curve) -> lists:member(Curve, Supported) end, ToCheck).
+
+check_ecc(SSL, Role, Expect) ->
+ {ok, Data} = ssl:connection_information(SSL),
+ case lists:keyfind(ecc, 1, Data) of
+ {ecc, {named_curve, Expect}} -> ok;
+ Other -> {error, Role, Expect, Other}
+ end.
inet_port(Pid) when is_pid(Pid)->
receive
@@ -769,18 +1072,18 @@ no_result(_) ->
no_result_msg.
trigger_renegotiate(Socket, [ErlData, N]) ->
- [{session_id, Id} | _ ] = ssl:session_info(Socket),
+ {ok, [{session_id, Id}]} = ssl:connection_information(Socket, [session_id]),
trigger_renegotiate(Socket, ErlData, N, Id).
trigger_renegotiate(Socket, _, 0, Id) ->
ct:sleep(1000),
- case ssl:session_info(Socket) of
- [{session_id, Id} | _ ] ->
+ case ssl:connection_information(Socket, [session_id]) of
+ {ok, [{session_id, Id}]} ->
fail_session_not_renegotiated;
%% Tests that uses this function will not reuse
%% sessions so if we get a new session id the
%% renegotiation has succeeded.
- [{session_id, _} | _ ] ->
+ {ok, [{session_id, _}]} ->
ok;
{error, closed} ->
fail_session_fatal_alert_during_renegotiation;
@@ -805,16 +1108,24 @@ send_selected_port(_,_,_) ->
rsa_suites(CounterPart) ->
ECC = is_sane_ecc(CounterPart),
FIPS = is_fips(CounterPart),
+ CryptoSupport = crypto:supports(),
+ Ciphers = proplists:get_value(ciphers, CryptoSupport),
lists:filter(fun({rsa, des_cbc, sha}) when FIPS == true ->
false;
({dhe_rsa, des_cbc, sha}) when FIPS == true ->
false;
- ({rsa, _, _}) ->
- true;
- ({dhe_rsa, _, _}) ->
- true;
- ({ecdhe_rsa, _, _}) when ECC == true ->
- true;
+ ({rsa, Cipher, _}) ->
+ lists:member(cipher_atom(Cipher), Ciphers);
+ ({dhe_rsa, Cipher, _}) ->
+ lists:member(cipher_atom(Cipher), Ciphers);
+ ({ecdhe_rsa, Cipher, _}) when ECC == true ->
+ lists:member(cipher_atom(Cipher), Ciphers);
+ ({rsa, Cipher, _, _}) ->
+ lists:member(cipher_atom(Cipher), Ciphers);
+ ({dhe_rsa, Cipher, _,_}) ->
+ lists:member(cipher_atom(Cipher), Ciphers);
+ ({ecdhe_rsa, Cipher, _,_}) when ECC == true ->
+ lists:member(cipher_atom(Cipher), Ciphers);
(_) ->
false
end,
@@ -830,48 +1141,47 @@ common_ciphers(openssl) ->
lists:member(ssl_cipher:openssl_suite_name(S), OpenSslSuites)
].
-rsa_non_signed_suites() ->
+available_suites(Version) ->
+ [ssl_cipher:erl_suite_definition(Suite) ||
+ Suite <- ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
+
+
+rsa_non_signed_suites(Version) ->
lists:filter(fun({rsa, _, _}) ->
- true;
+ false;
(_) ->
- false
+ true
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
-dsa_suites() ->
+dsa_suites(Version) ->
lists:filter(fun({dhe_dss, _, _}) ->
true;
(_) ->
false
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
-ecdsa_suites() ->
+ecdsa_suites(Version) ->
lists:filter(fun({ecdhe_ecdsa, _, _}) ->
true;
(_) ->
false
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
-ecdh_rsa_suites() ->
+ecdh_rsa_suites(Version) ->
lists:filter(fun({ecdh_rsa, _, _}) ->
true;
(_) ->
false
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
-openssl_rsa_suites(CounterPart) ->
+openssl_rsa_suites() ->
Ciphers = ssl:cipher_suites(openssl),
- Names = case is_sane_ecc(CounterPart) of
- true ->
- "DSS | ECDSA";
- false ->
- "DSS | ECDHE | ECDH"
- end,
- lists:filter(fun(Str) -> string_regex_filter(Str, Names)
- end, Ciphers).
+ lists:filter(fun(Str) -> string_regex_filter(Str, "RSA")
+ end, Ciphers) -- openssl_ecdh_rsa_suites().
openssl_dsa_suites() ->
Ciphers = ssl:cipher_suites(openssl),
@@ -888,6 +1198,12 @@ openssl_ecdh_rsa_suites() ->
lists:filter(fun(Str) -> string_regex_filter(Str, "ECDH-RSA")
end, Ciphers).
+openssl_filter(FilterStr) ->
+ Ciphers = string:tokens(os:cmd("openssl ciphers"), ":"),
+ lists:filter(fun(Str) -> string_regex_filter(Str, FilterStr)
+ end, Ciphers).
+
+
string_regex_filter(Str, Search) when is_list(Str) ->
case re:run(Str, Search, []) of
nomatch ->
@@ -898,92 +1214,65 @@ string_regex_filter(Str, Search) when is_list(Str) ->
string_regex_filter(_Str, _Search) ->
false.
-anonymous_suites() ->
- Suites =
- [{dh_anon, rc4_128, md5},
- {dh_anon, des_cbc, sha},
- {dh_anon, '3des_ede_cbc', sha},
- {dh_anon, aes_128_cbc, sha},
- {dh_anon, aes_256_cbc, sha},
- {dh_anon, aes_128_gcm, null, sha256},
- {dh_anon, aes_256_gcm, null, sha384},
- {ecdh_anon,rc4_128,sha},
- {ecdh_anon,'3des_ede_cbc',sha},
- {ecdh_anon,aes_128_cbc,sha},
- {ecdh_anon,aes_256_cbc,sha}],
- ssl_cipher:filter_suites(Suites).
-
-psk_suites() ->
- Suites =
- [{psk, rc4_128, sha},
- {psk, '3des_ede_cbc', sha},
- {psk, aes_128_cbc, sha},
- {psk, aes_256_cbc, sha},
- {psk, aes_128_cbc, sha256},
- {psk, aes_256_cbc, sha384},
- {dhe_psk, rc4_128, sha},
- {dhe_psk, '3des_ede_cbc', sha},
- {dhe_psk, aes_128_cbc, sha},
- {dhe_psk, aes_256_cbc, sha},
- {dhe_psk, aes_128_cbc, sha256},
- {dhe_psk, aes_256_cbc, sha384},
- {rsa_psk, rc4_128, sha},
- {rsa_psk, '3des_ede_cbc', sha},
- {rsa_psk, aes_128_cbc, sha},
- {rsa_psk, aes_256_cbc, sha},
- {rsa_psk, aes_128_cbc, sha256},
- {rsa_psk, aes_256_cbc, sha384},
- {psk, aes_128_gcm, null, sha256},
- {psk, aes_256_gcm, null, sha384},
- {dhe_psk, aes_128_gcm, null, sha256},
- {dhe_psk, aes_256_gcm, null, sha384},
- {rsa_psk, aes_128_gcm, null, sha256},
- {rsa_psk, aes_256_gcm, null, sha384}],
- ssl_cipher:filter_suites(Suites).
-
-psk_anon_suites() ->
- Suites =
- [{psk, rc4_128, sha},
- {psk, '3des_ede_cbc', sha},
- {psk, aes_128_cbc, sha},
- {psk, aes_256_cbc, sha},
- {dhe_psk, rc4_128, sha},
- {dhe_psk, '3des_ede_cbc', sha},
- {dhe_psk, aes_128_cbc, sha},
- {dhe_psk, aes_256_cbc, sha}],
- ssl_cipher:filter_suites(Suites).
+ecdh_dh_anonymous_suites(Version) ->
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:anonymous_suites(Version)],
+ [{key_exchange,
+ fun(dh_anon) ->
+ true;
+ (ecdh_anon) ->
+ true;
+ (_) ->
+ false
+ end}]).
+psk_suites(Version) ->
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []).
+
+psk_anon_suites(Version) ->
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
+ [{key_exchange,
+ fun(psk) ->
+ true;
+ (psk_dhe) ->
+ true;
+ (_) ->
+ false
+ end}]).
srp_suites() ->
- Suites =
- [{srp_anon, '3des_ede_cbc', sha},
- {srp_rsa, '3des_ede_cbc', sha},
- {srp_anon, aes_128_cbc, sha},
- {srp_rsa, aes_128_cbc, sha},
- {srp_anon, aes_256_cbc, sha},
- {srp_rsa, aes_256_cbc, sha}],
- ssl_cipher:filter_suites(Suites).
-
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ [{key_exchange,
+ fun(srp_rsa) ->
+ true;
+ (_) ->
+ false
+ end}]).
srp_anon_suites() ->
- Suites =
- [{srp_anon, '3des_ede_cbc', sha},
- {srp_anon, aes_128_cbc, sha},
- {srp_anon, aes_256_cbc, sha}],
- ssl_cipher:filter_suites(Suites).
-
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites_anon()],
+ []).
srp_dss_suites() ->
- Suites =
- [{srp_dss, '3des_ede_cbc', sha},
- {srp_dss, aes_128_cbc, sha},
- {srp_dss, aes_256_cbc, sha}],
- ssl_cipher:filter_suites(Suites).
-
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ [{key_exchange,
+ fun(srp_dss) ->
+ true;
+ (_) ->
+ false
+ end}]).
rc4_suites(Version) ->
- Suites = ssl_cipher:rc4_suites(Version),
- ssl_cipher:filter_suites(Suites).
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <-ssl_cipher:rc4_suites(Version)], []).
des_suites(Version) ->
- Suites = ssl_cipher:des_suites(Version),
- ssl_cipher:filter_suites(Suites).
+ ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <-ssl_cipher:des_suites(Version)], []).
+
+tuple_to_map({Kex, Cipher, Mac}) ->
+ #{key_exchange => Kex,
+ cipher => Cipher,
+ mac => Mac,
+ prf => default_prf};
+tuple_to_map({Kex, Cipher, Mac, Prf}) ->
+ #{key_exchange => Kex,
+ cipher => Cipher,
+ mac => Mac,
+ prf => Prf}.
pem_to_der(File) ->
{ok, PemBin} = file:read_file(File),
@@ -1015,8 +1304,8 @@ cipher_result(Socket, Result) ->
end.
session_info_result(Socket) ->
- ssl:session_info(Socket).
-
+ {ok, Info} = ssl:connection_information(Socket, [session_id, cipher_suite]),
+ Info.
public_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
#'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
@@ -1072,28 +1361,65 @@ init_tls_version(Version, Config)
application:load(ssl),
application:set_env(ssl, dtls_protocol_version, Version),
ssl:start(),
- [{protocol, dtls}, {protocol_opts, [{protocol, dtls}]}|Config];
+ NewConfig = proplists:delete(protocol_opts, proplists:delete(protocol, Config)),
+ [{protocol, dtls}, {protocol_opts, [{protocol, dtls}]} | NewConfig];
init_tls_version(Version, Config) ->
ssl:stop(),
application:load(ssl),
application:set_env(ssl, protocol_version, Version),
ssl:start(),
- [{protocol, tls}|Config].
+ NewConfig = proplists:delete(protocol_opts, proplists:delete(protocol, Config)),
+ [{protocol, tls} | NewConfig].
+clean_tls_version(Config) ->
+ proplists:delete(protocol_opts, proplists:delete(protocol, Config)).
+
sufficient_crypto_support(Version)
when Version == 'tlsv1.2'; Version == 'dtlsv1.2' ->
CryptoSupport = crypto:supports(),
proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport));
-sufficient_crypto_support(Group) when Group == ciphers_ec; %% From ssl_basic_SUITE
- Group == erlang_server; %% From ssl_ECC_SUITE
- Group == erlang_client; %% From ssl_ECC_SUITE
- Group == erlang -> %% From ssl_ECC_SUITE
+sufficient_crypto_support(cipher_ec) ->
CryptoSupport = crypto:supports(),
proplists:get_bool(ecdh, proplists:get_value(public_keys, CryptoSupport));
sufficient_crypto_support(_) ->
true.
+check_key_exchange_send_active(Socket, false) ->
+ send_recv_result_active(Socket);
+check_key_exchange_send_active(Socket, KeyEx) ->
+ {ok, Info} =
+ ssl:connection_information(Socket, [cipher_suite, protocol]),
+ Suite = proplists:get_value(cipher_suite, Info),
+ Version = proplists:get_value(protocol, Info),
+ true = check_key_exchange(Suite, KeyEx, Version),
+ send_recv_result_active(Socket).
+
+check_key_exchange({KeyEx,_, _}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
+ true;
+check_key_exchange({KeyEx,_,_,_}, KeyEx, _) ->
+ ct:pal("Kex: ~p", [KeyEx]),
+ true;
+check_key_exchange(KeyEx1, KeyEx2, Version) ->
+ ct:pal("Kex: ~p ~p", [KeyEx1, KeyEx2]),
+ case Version of
+ 'tlsv1.2' ->
+ v_1_2_check(element(1, KeyEx1), KeyEx2);
+ 'dtlsv1.2' ->
+ v_1_2_check(element(1, KeyEx1), KeyEx2);
+ _ ->
+ ct:pal("Negotiated ~p Expected ~p", [KeyEx1, KeyEx2]),
+ false
+ end.
+
+v_1_2_check(ecdh_ecdsa, ecdh_rsa) ->
+ true;
+v_1_2_check(ecdh_rsa, ecdh_ecdsa) ->
+ true;
+v_1_2_check(_, _) ->
+ false.
+
send_recv_result_active(Socket) ->
ssl:send(Socket, "Hello world"),
receive
@@ -1175,35 +1501,120 @@ is_fips(_) ->
false.
cipher_restriction(Config0) ->
+ Version = protocol_version(Config0, tuple),
case is_sane_ecc(openssl) of
false ->
Opts = proplists:get_value(server_opts, Config0),
Config1 = proplists:delete(server_opts, Config0),
VerOpts = proplists:get_value(server_verification_opts, Config1),
Config = proplists:delete(server_verification_opts, Config1),
- Restricted0 = ssl:cipher_suites() -- ecdsa_suites(),
- Restricted = Restricted0 -- ecdh_rsa_suites(),
+ Restricted0 = ssl:cipher_suites() -- ecdsa_suites(Version),
+ Restricted = Restricted0 -- ecdh_rsa_suites(Version),
[{server_opts, [{ciphers, Restricted} | Opts]}, {server_verification_opts, [{ciphers, Restricted} | VerOpts] } | Config];
true ->
Config0
end.
+openssl_dsa_support() ->
+ case os:cmd("openssl version") of
+ "LibreSSL 2.6.1" ++ _ ->
+ true;
+ "LibreSSL 2.6.2" ++ _ ->
+ true;
+ "LibreSSL 2.6" ++ _ ->
+ false;
+ "LibreSSL 2.4" ++ _ ->
+ true;
+ "LibreSSL 2.3" ++ _ ->
+ true;
+ "LibreSSL 2.2" ++ _ ->
+ true;
+ "LibreSSL 2.1" ++ _ ->
+ true;
+ "LibreSSL 2.0" ++ _ ->
+ true;
+ "LibreSSL" ++ _ ->
+ false;
+ "OpenSSL 1.0.1" ++ Rest ->
+ hd(Rest) >= s;
+ _ ->
+ true
+ end.
+
+%% Acctual support is tested elsewhere, this is to exclude some LibreSSL and OpenSSL versions
+openssl_sane_dtls() ->
+ case os:cmd("openssl version") of
+ "OpenSSL 0." ++ _ ->
+ false;
+ "OpenSSL 1.0.1s-freebsd" ++ _ ->
+ false;
+ "OpenSSL 1.0.2k-freebsd" ++ _ ->
+ false;
+ "OpenSSL 1.0.2d" ++ _ ->
+ false;
+ "OpenSSL 1.0.2n" ++ _ ->
+ false;
+ "OpenSSL 1.0.0" ++ _ ->
+ false;
+ "OpenSSL" ++ _ ->
+ true;
+ "LibreSSL 2.7" ++ _ ->
+ true;
+ _ ->
+ false
+ end.
+openssl_sane_client_cert() ->
+ case os:cmd("openssl version") of
+ "LibreSSL 2.5.2" ++ _ ->
+ true;
+ "LibreSSL 2.4" ++ _ ->
+ false;
+ "LibreSSL 2.3" ++ _ ->
+ false;
+ "LibreSSL 2.1" ++ _ ->
+ false;
+ "LibreSSL 2.0" ++ _ ->
+ false;
+ "LibreSSL 2.0" ++ _ ->
+ false;
+ "OpenSSL 1.0.1s-freebsd" ->
+ false;
+ "OpenSSL 1.0.0" ++ _ ->
+ false;
+ _ ->
+ true
+ end.
+
check_sane_openssl_version(Version) ->
case supports_ssl_tls_version(Version) of
true ->
case {Version, os:cmd("openssl version")} of
+ {'sslv3', "OpenSSL 1.0.2" ++ _} ->
+ false;
+ {'dtlsv1', _} ->
+ not is_fips(openssl);
+ {'dtlsv1.2', _} ->
+ not is_fips(openssl);
{_, "OpenSSL 1.0.2" ++ _} ->
true;
{_, "OpenSSL 1.0.1" ++ _} ->
true;
- {'tlsv1.2', "OpenSSL 1.0" ++ _} ->
+ {'tlsv1.2', "OpenSSL 1.0.0" ++ _} ->
false;
- {'tlsv1.1', "OpenSSL 1.0" ++ _} ->
+ {'tlsv1.1', "OpenSSL 1.0.0" ++ _} ->
+ false;
+ {'dtlsv1.2', "OpenSSL 1.0.2" ++ _} ->
+ false;
+ {'dtlsv1', "OpenSSL 1.0.0" ++ _} ->
false;
{'tlsv1.2', "OpenSSL 0" ++ _} ->
false;
{'tlsv1.1', "OpenSSL 0" ++ _} ->
false;
+ {'dtlsv1', "OpenSSL 0" ++ _} ->
+ false;
+ {'dtlsv1.2', "OpenSSL 0" ++ _} ->
+ false;
{_, _} ->
true
end;
@@ -1213,17 +1624,21 @@ check_sane_openssl_version(Version) ->
enough_openssl_crl_support("OpenSSL 0." ++ _) -> false;
enough_openssl_crl_support(_) -> true.
-wait_for_openssl_server(Port) ->
- wait_for_openssl_server(Port, 10).
-wait_for_openssl_server(_, 0) ->
+wait_for_openssl_server(Port, tls) ->
+ do_wait_for_openssl_tls_server(Port, 10);
+wait_for_openssl_server(_Port, dtls) ->
+ ok. %% No need to wait for DTLS over UDP server
+ %% client will retransmitt until it is up.
+
+do_wait_for_openssl_tls_server(_, 0) ->
exit(failed_to_connect_to_openssl);
-wait_for_openssl_server(Port, N) ->
+do_wait_for_openssl_tls_server(Port, N) ->
case gen_tcp:connect("localhost", Port, []) of
{ok, S} ->
gen_tcp:close(S);
_ ->
ct:sleep(?SLEEP),
- wait_for_openssl_server(Port, N-1)
+ do_wait_for_openssl_tls_server(Port, N-1)
end.
version_flag(tlsv1) ->
@@ -1235,14 +1650,26 @@ version_flag('tlsv1.2') ->
version_flag(sslv3) ->
"-ssl3";
version_flag(sslv2) ->
- "-ssl2".
-
-filter_suites(Ciphers0) ->
- Version = tls_record:highest_protocol_version([]),
+ "-ssl2";
+version_flag('dtlsv1.2') ->
+ "-dtls1_2";
+version_flag('dtlsv1') ->
+ "-dtls1".
+
+filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_list(Cipher)->
+ filter_suites([ssl_cipher:openssl_suite(S) || S <- Ciphers],
+ AtomVersion);
+filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_binary(Cipher)->
+ filter_suites([ssl_cipher:erl_suite_definition(S) || S <- Ciphers],
+ AtomVersion);
+filter_suites(Ciphers0, AtomVersion) ->
+ Version = tls_version(AtomVersion),
Supported0 = ssl_cipher:suites(Version)
++ ssl_cipher:anonymous_suites(Version)
++ ssl_cipher:psk_suites(Version)
+ ++ ssl_cipher:psk_suites_anon(Version)
++ ssl_cipher:srp_suites()
+ ++ ssl_cipher:srp_suites_anon()
++ ssl_cipher:rc4_suites(Version),
Supported1 = ssl_cipher:filter_suites(Supported0),
Supported2 = [ssl_cipher:erl_suite_definition(S) || S <- Supported1],
@@ -1287,32 +1714,55 @@ portable_open_port(Exe, Args) ->
open_port({spawn_executable, AbsPath},
[{args, Args}, stderr_to_stdout]).
+supports_ssl_tls_version(sslv2 = Version) ->
+ case os:cmd("openssl version") of
+ "OpenSSL 1" ++ _ ->
+ false;
+ %% Appears to be broken
+ "OpenSSL 0.9.8.o" ++ _ ->
+ false;
+ _ ->
+ VersionFlag = version_flag(Version),
+ Exe = "openssl",
+ Args = ["s_client", VersionFlag],
+ Port = ssl_test_lib:portable_open_port(Exe, Args),
+ do_supports_ssl_tls_version(Port, "")
+ end;
+
supports_ssl_tls_version(Version) ->
VersionFlag = version_flag(Version),
Exe = "openssl",
Args = ["s_client", VersionFlag],
Port = ssl_test_lib:portable_open_port(Exe, Args),
- do_supports_ssl_tls_version(Port).
+ do_supports_ssl_tls_version(Port, "").
-do_supports_ssl_tls_version(Port) ->
+do_supports_ssl_tls_version(Port, Acc) ->
receive
- {Port, {data, "unknown option" ++ _}} ->
- false;
- {Port, {data, Data}} ->
- case lists:member("error", string:tokens(Data, ":")) of
- true ->
- false;
- false ->
- do_supports_ssl_tls_version(Port)
- end
- after 500 ->
- true
+ {Port, {data, Data}} ->
+ case Acc ++ Data of
+ "unknown option" ++ _ ->
+ false;
+ Error when length(Error) >= 11 ->
+ case lists:member("error", string:tokens(Data, ":")) of
+ true ->
+ false;
+ false ->
+ do_supports_ssl_tls_version(Port, Error)
+ end;
+ _ ->
+ do_supports_ssl_tls_version(Port, Acc ++ Data)
+ end
+ after 1000 ->
+ true
end.
-ssl_options(Option, Config) ->
+ssl_options(Option, Config) when is_atom(Option) ->
ProtocolOpts = proplists:get_value(protocol_opts, Config, []),
Opts = proplists:get_value(Option, Config, []),
- Opts ++ ProtocolOpts.
+ Opts ++ ProtocolOpts;
+ssl_options(Options, Config) ->
+ ProtocolOpts = proplists:get_value(protocol_opts, Config, []),
+ Options ++ ProtocolOpts.
protocol_version(Config) ->
protocol_version(Config, atom).
@@ -1320,7 +1770,7 @@ protocol_version(Config) ->
protocol_version(Config, tuple) ->
case proplists:get_value(protocol, Config) of
dtls ->
- dtls_record:protocol_version(dtls_record:highest_protocol_version([]));
+ dtls_record:highest_protocol_version(dtls_record:supported_protocol_versions());
_ ->
tls_record:highest_protocol_version(tls_record:supported_protocol_versions())
end;
@@ -1345,3 +1795,146 @@ ct_log_supported_protocol_versions(Config) ->
_ ->
ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()])
end.
+
+clean_env() ->
+ application:unset_env(ssl, protocol_version),
+ application:unset_env(ssl, dtls_protocol_version),
+ application:unset_env(ssl, session_lifetime),
+ application:unset_env(ssl, session_cb),
+ application:unset_env(ssl, session_cb_init_args),
+ application:unset_env(ssl, session_cache_client_max),
+ application:unset_env(ssl, session_cache_server_max),
+ application:unset_env(ssl, ssl_pem_cache_clean),
+ application:unset_env(ssl, bypass_pem_cache),
+ application:unset_env(ssl, alert_timeout).
+
+clean_start() ->
+ ssl:stop(),
+ application:load(ssl),
+ clean_env(),
+ ssl:start().
+
+is_psk_anon_suite({psk, _,_}) ->
+ true;
+is_psk_anon_suite({dhe_psk,_,_}) ->
+ true;
+is_psk_anon_suite({psk, _,_,_}) ->
+ true;
+is_psk_anon_suite({dhe_psk, _,_,_}) ->
+ true;
+is_psk_anon_suite(_) ->
+ false.
+
+cipher_atom(aes_256_cbc) ->
+ aes_cbc256;
+cipher_atom(aes_128_cbc) ->
+ aes_cbc128;
+cipher_atom('3des_ede_cbc') ->
+ des_ede3;
+cipher_atom(Atom) ->
+ Atom.
+tls_version('dtlsv1' = Atom) ->
+ dtls_v1:corresponding_tls_version(dtls_record:protocol_version(Atom));
+tls_version('dtlsv1.2' = Atom) ->
+ dtls_v1:corresponding_tls_version(dtls_record:protocol_version(Atom));
+tls_version(Atom) ->
+ tls_record:protocol_version(Atom).
+
+hardcode_rsa_key(1) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
+ publicExponent = 17,
+ privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
+ prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
+ prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
+ exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
+ exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
+ coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(2) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777,
+ publicExponent = 17,
+ privateExponent = 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773,
+ prime1 = 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419,
+ prime2 = 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083,
+ exponent1 = 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677,
+ exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
+ coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
+ otherPrimeInfos = asn1_NOVALUE};
+hardcode_rsa_key(3) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
+ publicExponent = 17,
+ privateExponent = 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265,
+ prime1 = 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823,
+ prime2 =146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523,
+ exponent1 = 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349,
+ exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
+ coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
+ otherPrimeInfos = asn1_NOVALUE};
+hardcode_rsa_key(4) ->
+ #'RSAPrivateKey'{
+ version ='two-prime',
+ modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389,
+ publicExponent = 17,
+ privateExponent = 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641,
+ prime1 = 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867,
+ prime2 = 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967,
+ exponent1 = 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541,
+ exponent2 = 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347,
+ coefficient = 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012,
+ otherPrimeInfos = asn1_NOVALUE};
+
+hardcode_rsa_key(5) ->
+ #'RSAPrivateKey'{
+ version= 'two-prime',
+ modulus = 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633,
+ publicExponent = 17,
+ privateExponent = 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001,
+ prime1 =163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709,
+ prime2 = 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637,
+ exponent1 = 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441,
+ exponent2 = 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973,
+ coefficient = 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392,
+ otherPrimeInfos = asn1_NOVALUE};
+hardcode_rsa_key(6) ->
+ #'RSAPrivateKey'{
+ version = 'two-prime',
+ modulus = 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039,
+ publicExponent = 17,
+ privateExponent = 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713,
+ prime1 = 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063,
+ prime2 = 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953,
+ exponent1 = 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125,
+ exponent2 = 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689,
+ coefficient = 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227,
+ otherPrimeInfos = asn1_NOVALUE}.
+
+hardcode_dsa_key(1) ->
+ {'DSAPrivateKey',0,
+ 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491,
+ 1454908511695148818053325447108751926908854531909,
+ 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579,
+ 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358,
+ 1457508827177594730669011716588605181448418352823};
+hardcode_dsa_key(2) ->
+ #'DSAPrivateKey'{
+ version = 0,
+ p = 145447354557382582722944332987784622105075065624518040072393858097520305927329240484963764783346271194321683798321743658303478090647837211867389721684646254999291098347011037298359107547264573476540026676832159205689428125157386525591130716464335426605521884822982379206842523670736739023467072341958074788151,
+ q = 742801637799670234315651916144768554943688916729,
+ g = 79727684678125120155622004643594683941478642656111969487719464672433839064387954070113655822700268007902716505761008423792735229036965034283173483862273639257533568978482104785033927768441235063983341565088899599358397638308472931049309161811156189887217888328371767967629005149630676763492409067382020352505,
+ y = 35853727034965131665219275925554159789667905059030049940938124723126925435403746979702929280654735557166864135215989313820464108440192507913554896358611966877432546584986661291483639036057475682547385322659469460385785257933737832719745145778223672383438466035853830832837226950912832515496378486927322864228,
+ x = 801315110178350279541885862867982846569980443911};
+hardcode_dsa_key(3) ->
+ #'DSAPrivateKey'{
+ version = 0,
+ p = 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491,
+ q = 1454908511695148818053325447108751926908854531909,
+ g = 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579,
+ y = 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358,
+ x = 1457508827177594730669011716588605181448418352823}.
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index b3109b5de9..9b0ae94ef2 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -37,25 +37,49 @@
%%--------------------------------------------------------------------
all() ->
- [
- {group, basic},
- {group, 'tlsv1.2'},
- {group, 'tlsv1.1'},
- {group, 'tlsv1'},
- {group, 'sslv3'}
- ].
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{group, basic},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'},
+ {group, 'dtlsv1.2'},
+ {group, 'dtlsv1'}];
+ false ->
+ [{group, basic},
+ {group, 'tlsv1.2'},
+ {group, 'tlsv1.1'},
+ {group, 'tlsv1'},
+ {group, 'sslv3'}]
+ end.
groups() ->
- [{basic, [], basic_tests()},
- {'tlsv1.2', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'tlsv1.1', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'tlsv1', [], all_versions_tests()++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
- {'sslv3', [], all_versions_tests()}].
+ case ssl_test_lib:openssl_sane_dtls() of
+ true ->
+ [{basic, [], basic_tests()},
+ {'tlsv1.2', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
+ {'tlsv1.1', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
+ {'tlsv1', [], all_versions_tests()++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
+ {'sslv3', [], all_versions_tests()},
+ {'dtlsv1.2', [], dtls_all_versions_tests()},
+ {'dtlsv1', [], dtls_all_versions_tests()}
+ ];
+ false ->
+ [{basic, [], basic_tests()},
+ {'tlsv1.2', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
+ {'tlsv1.1', [], all_versions_tests() ++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
+ {'tlsv1', [], all_versions_tests()++ alpn_tests() ++ npn_tests() ++ sni_server_tests()},
+ {'sslv3', [], all_versions_tests()}
+ ]
+ end.
basic_tests() ->
[basic_erlang_client_openssl_server,
basic_erlang_server_openssl_client,
- expired_session].
+ expired_session,
+ ssl2_erlang_server_openssl_client_comp
+ ].
all_versions_tests() ->
[
@@ -63,6 +87,9 @@ all_versions_tests() ->
erlang_server_openssl_client,
erlang_client_openssl_server_dsa_cert,
erlang_server_openssl_client_dsa_cert,
+ erlang_client_openssl_server_anon,
+ erlang_server_openssl_client_anon,
+ erlang_server_openssl_client_anon_with_cert,
erlang_server_openssl_client_reuse_session,
erlang_client_openssl_server_renegotiate,
erlang_client_openssl_server_nowrap_seqnum,
@@ -74,7 +101,36 @@ all_versions_tests() ->
ciphers_dsa_signed_certs,
erlang_client_bad_openssl_server,
expired_session,
- ssl2_erlang_server_openssl_client].
+ ssl2_erlang_server_openssl_client
+ ].
+
+dtls_all_versions_tests() ->
+ case ssl_test_lib:openssl_sane_client_cert() of
+ true ->
+ [erlang_server_openssl_client_client_cert,
+ erlang_client_openssl_server_no_server_ca_cert,
+ erlang_client_openssl_server_client_cert
+ | dtls_all_versions_tests_2()];
+ false ->
+ dtls_all_versions_tests_2()
+ end.
+
+dtls_all_versions_tests_2() ->
+ [erlang_client_openssl_server,
+ erlang_server_openssl_client,
+ erlang_client_openssl_server_dsa_cert,
+ erlang_server_openssl_client_dsa_cert,
+ erlang_client_openssl_server_anon,
+ erlang_server_openssl_client_anon,
+ erlang_server_openssl_client_anon_with_cert,
+ erlang_server_openssl_client_reuse_session,
+ erlang_client_openssl_server_renegotiate,
+ erlang_client_openssl_server_nowrap_seqnum,
+ erlang_server_openssl_client_nowrap_seqnum,
+ ciphers_rsa_signed_certs,
+ ciphers_dsa_signed_certs
+ %%expired_session
+ ].
alpn_tests() ->
[erlang_client_alpn_openssl_server_alpn,
@@ -116,12 +172,16 @@ init_per_suite(Config0) ->
catch crypto:stop(),
try crypto:start() of
ok ->
- ssl:start(),
- {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
- proplists:get_value(priv_dir, Config0)),
- Config1 = ssl_test_lib:make_dsa_cert(Config0),
- Config = ssl_test_lib:cert_options(Config1),
- ssl_test_lib:cipher_restriction(Config)
+ ssl_test_lib:clean_start(),
+ Config =
+ case ssl_test_lib:openssl_dsa_support() of
+ true ->
+ Config1 = ssl_test_lib:make_rsa_cert(Config0),
+ ssl_test_lib:make_dsa_cert(Config1);
+ false ->
+ ssl_test_lib:make_rsa_cert(Config0)
+ end,
+ ssl_test_lib:cipher_restriction(Config)
catch _:_ ->
{skip, "Crypto did not start"}
end
@@ -131,7 +191,8 @@ end_per_suite(_Config) ->
ssl:stop(),
application:stop(crypto).
-init_per_group(basic, Config) ->
+init_per_group(basic, Config0) ->
+ Config = ssl_test_lib:clean_tls_version(Config0),
case ssl_test_lib:supports_ssl_tls_version(sslv2) of
true ->
[{v2_hello_compatible, true} | Config];
@@ -141,19 +202,29 @@ init_per_group(basic, Config) ->
init_per_group(GroupName, Config) ->
case ssl_test_lib:is_tls_version(GroupName) of
true ->
- case ssl_test_lib:check_sane_openssl_version(GroupName) of
- true ->
- ssl_test_lib:init_tls_version(GroupName, Config);
- false ->
- {skip, openssl_does_not_support_version}
- end;
- _ ->
+ case ssl_test_lib:supports_ssl_tls_version(GroupName) of
+ true ->
+ case ssl_test_lib:check_sane_openssl_version(GroupName) of
+ true ->
+ ssl_test_lib:init_tls_version(GroupName, Config);
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ false ->
+ {skip, openssl_does_not_support_version}
+ end;
+ _ ->
ssl:start(),
Config
end.
-end_per_group(_GroupName, Config) ->
- Config.
+end_per_group(GroupName, Config) ->
+ case ssl_test_lib:is_tls_version(GroupName) of
+ true ->
+ ssl_test_lib:clean_tls_version(Config);
+ false ->
+ Config
+ end.
init_per_testcase(expired_session, Config) ->
ct:timetrap(?EXPIRE * 1000 * 5),
@@ -163,15 +234,27 @@ init_per_testcase(expired_session, Config) ->
ssl:start(),
Config;
-init_per_testcase(TestCase, Config) when TestCase == ciphers_rsa_signed_certs;
- TestCase == ciphers_dsa_signed_certs ->
- ct:timetrap({seconds, 45}),
- special_init(TestCase, Config);
-
+init_per_testcase(TestCase, Config) when
+ TestCase == ciphers_dsa_signed_certs;
+ TestCase == erlang_client_openssl_server_dsa_cert;
+ TestCase == erlang_server_openssl_client_dsa_cert;
+ TestCase == erlang_client_openssl_server_dsa_cert;
+ TestCase == erlang_server_openssl_client_dsa_cert ->
+ case ssl_test_lib:openssl_dsa_support() of
+ true ->
+ special_init(TestCase, Config);
+ false ->
+ {skip, "DSA not supported by OpenSSL"}
+ end;
init_per_testcase(TestCase, Config) ->
- ct:timetrap({seconds, 20}),
+ ct:timetrap({seconds, 35}),
special_init(TestCase, Config).
+special_init(TestCase, Config) when
+ TestCase == ciphers_rsa_signed_certs;
+ TestCase == ciphers_dsa_signed_certs->
+ ct:timetrap({seconds, 90}),
+ Config;
special_init(TestCase, Config)
when TestCase == erlang_client_openssl_server_renegotiate;
TestCase == erlang_client_openssl_server_nowrap_seqnum;
@@ -180,7 +263,8 @@ special_init(TestCase, Config)
{ok, Version} = application:get_env(ssl, protocol_version),
check_sane_openssl_renegotaite(Config, Version);
-special_init(ssl2_erlang_server_openssl_client, Config) ->
+special_init(Case, Config) when Case == ssl2_erlang_server_openssl_client;
+ Case == ssl2_erlang_server_openssl_client_comp ->
case ssl_test_lib:supports_ssl_tls_version(sslv2) of
true ->
Config;
@@ -238,13 +322,24 @@ special_init(TestCase, Config)
check_openssl_npn_support(Config)
end;
-special_init(TestCase, Config)
+special_init(TestCase, Config0)
when TestCase == erlang_server_openssl_client_sni_match;
TestCase == erlang_server_openssl_client_sni_no_match;
TestCase == erlang_server_openssl_client_sni_no_header;
TestCase == erlang_server_openssl_client_sni_match_fun;
TestCase == erlang_server_openssl_client_sni_no_match_fun;
TestCase == erlang_server_openssl_client_sni_no_header_fun ->
+ RsaOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config0),
+ Config = [{sni_server_opts, [{sni_hosts,
+ [{"a.server", [
+ {certfile, proplists:get_value(certfile, RsaOpts)},
+ {keyfile, proplists:get_value(keyfile, RsaOpts)}
+ ]},
+ {"b.server", [
+ {certfile, proplists:get_value(certfile, RsaOpts)},
+ {keyfile, proplists:get_value(keyfile, RsaOpts)}
+ ]}
+ ]}]} | Config0],
check_openssl_sni_support(Config);
special_init(_, Config) ->
@@ -263,8 +358,8 @@ basic_erlang_client_openssl_server() ->
[{doc,"Test erlang client with openssl server"}].
basic_erlang_client_openssl_server(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -280,7 +375,8 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+
+ ssl_test_lib:wait_for_openssl_server(Port, tls),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -302,10 +398,10 @@ basic_erlang_server_openssl_client() ->
[{doc,"Test erlang server with openssl client"}].
basic_erlang_server_openssl_client(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
V2Compat = proplists:get_value(v2_hello_compatible, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
ct:pal("v2_hello_compatible: ~p", [V2Compat]),
@@ -318,7 +414,8 @@ basic_erlang_server_openssl_client(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(Server),
Exe = "openssl",
- Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port) | workaround_openssl_s_clinent()],
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++
+ ":" ++ integer_to_list(Port) | workaround_openssl_s_clinent()],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
@@ -335,8 +432,8 @@ erlang_client_openssl_server() ->
[{doc,"Test erlang client with openssl server"}].
erlang_client_openssl_server(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -353,7 +450,7 @@ erlang_client_openssl_server(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -375,9 +472,9 @@ erlang_server_openssl_client() ->
[{doc,"Test erlang server with openssl client"}].
erlang_server_openssl_client(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
@@ -389,7 +486,7 @@ erlang_server_openssl_client(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client", "-connect", "localhost: " ++ integer_to_list(Port),
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++":" ++ integer_to_list(Port),
ssl_test_lib:version_flag(Version)],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -408,7 +505,7 @@ erlang_client_openssl_server_dsa_cert() ->
erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
ClientOpts = ssl_test_lib:ssl_options(client_dsa_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_dsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -427,7 +524,7 @@ erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -453,7 +550,7 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
ClientOpts = ssl_test_lib:ssl_options(client_dsa_opts, Config),
ServerOpts = ssl_test_lib:ssl_options(server_dsa_verify_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
CaCertFile = proplists:get_value(cacertfile, ClientOpts),
@@ -467,7 +564,7 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(Server),
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client", "-connect", "localhost: " ++ integer_to_list(Port),
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
ssl_test_lib:version_flag(Version),
"-cert", CertFile,
"-CAfile", CaCertFile,
@@ -483,16 +580,130 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) ->
ssl_test_lib:close_port(OpenSslPort),
process_flag(trap_exit, false).
-%%--------------------------------------------------------------------
+%%--------------------------------------------------------------------
+erlang_client_openssl_server_anon() ->
+ [{doc,"Test erlang client with openssl server, anonymous"}].
+erlang_client_openssl_server_anon(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ %% OpenSSL expects a certificate and key, even if the cipher spec
+ %% is restructed to aNULL, so we use 'server_rsa_opts' here
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_anon_opts, Config),
+ VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Port = ssl_test_lib:inet_port(node()),
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ KeyFile = proplists:get_value(keyfile, ServerOpts),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile,
+ "-cipher", "aNULL", "-msg"],
+
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE,
+ erlang_ssl_receive, [Data]}},
+ {options, [{ciphers, Ciphers} | ClientOpts]}]),
+
+ true = port_command(OpensslPort, Data),
+
+ ssl_test_lib:check_result(Client, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close_port(OpensslPort),
+ ssl_test_lib:close(Client),
+ process_flag(trap_exit, false),
+ ok.
+%%--------------------------------------------------------------------
+erlang_server_openssl_client_anon() ->
+ [{doc,"Test erlang server with openssl client, anonymous"}].
+erlang_server_openssl_client_anon(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_anon_opts, Config),
+ VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
+
+ %%--------------------------------------------------------------------
+ erlang_server_openssl_client_anon_with_cert() ->
+ [{doc,"Test erlang server with openssl client, anonymous (with cert)"}].
+ erlang_server_openssl_client_anon_with_cert(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {?MODULE, erlang_ssl_receive, [Data]}},
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false).
+
+%%--------------------------------------------------------------------
erlang_server_openssl_client_reuse_session() ->
[{doc, "Test erlang server with openssl client that reconnects with the"
"same session id, to test reusing of sessions."}].
erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
@@ -505,7 +716,8 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port),
+ Args = ["s_client", "-connect", hostname_format(Hostname)
+ ++ ":" ++ integer_to_list(Port),
ssl_test_lib:version_flag(Version),
"-reconnect"],
@@ -527,8 +739,8 @@ erlang_client_openssl_server_renegotiate() ->
[{doc,"Test erlang client when openssl server issuses a renegotiate"}].
erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -547,7 +759,7 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -577,8 +789,8 @@ erlang_client_openssl_server_nowrap_seqnum() ->
" to lower treashold substantially."}].
erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -596,7 +808,7 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -620,9 +832,9 @@ erlang_server_openssl_client_nowrap_seqnum() ->
" to lower treashold substantially."}].
erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
@@ -636,7 +848,7 @@ erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) ->
Port = ssl_test_lib:inet_port(Server),
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client","-connect", "localhost: " ++ integer_to_list(Port),
+ Args = ["s_client","-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
ssl_test_lib:version_flag(Version),
"-msg"],
@@ -659,8 +871,8 @@ erlang_client_openssl_server_no_server_ca_cert() ->
"implicitly tested eleswhere."}].
erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -677,7 +889,7 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -700,8 +912,8 @@ erlang_client_openssl_server_client_cert() ->
[{doc,"Test erlang client with openssl server when client sends cert"}].
erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -720,7 +932,7 @@ erlang_client_openssl_server_client_cert(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -743,10 +955,10 @@ erlang_server_openssl_client_client_cert() ->
[{doc,"Test erlang server with openssl client when client sends cert"}].
erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
@@ -766,7 +978,7 @@ erlang_server_openssl_client_client_cert(Config) when is_list(Config) ->
Exe = "openssl",
Args = ["s_client", "-cert", CertFile,
"-CAfile", CaCertFile,
- "-key", KeyFile,"-connect", "localhost:" ++ integer_to_list(Port),
+ "-key", KeyFile,"-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
ssl_test_lib:version_flag(Version)],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -784,8 +996,8 @@ erlang_server_erlang_client_client_cert() ->
[{doc,"Test erlang server with erlang client when client sends cert"}].
erlang_server_erlang_client_client_cert(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = proplists:get_value(server_verification_opts, Config),
- ClientOpts = proplists:get_value(client_verification_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_verify_opts, Config),
+ ClientOpts = proplists:get_value(client_rsa_verify_opts, Config),
Version = ssl_test_lib:protocol_version(Config),
{ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
@@ -830,7 +1042,8 @@ ciphers_dsa_signed_certs() ->
[{doc,"Test cipher suites that uses dsa certs"}].
ciphers_dsa_signed_certs(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:dsa_suites(),
+ NVersion = ssl_test_lib:protocol_version(Config, tuple),
+ Ciphers = ssl_test_lib:dsa_suites(NVersion),
run_suites(Ciphers, Version, Config, dsa).
%%--------------------------------------------------------------------
@@ -838,8 +1051,8 @@ erlang_client_bad_openssl_server() ->
[{doc,"Test what happens if openssl server sends garbage to erlang ssl client"}].
erlang_client_bad_openssl_server(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_verification_opts, Config),
- ClientOpts = ssl_test_lib:ssl_options(client_verification_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -852,7 +1065,7 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) ->
"-cert", CertFile, "-key", KeyFile],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -893,8 +1106,8 @@ expired_session() ->
"better code coverage of the ssl_manager module"}].
expired_session(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ClientOpts = ssl_test_lib:ssl_options(client_opts, Config),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ClientOpts = ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
Port = ssl_test_lib:inet_port(node()),
@@ -907,7 +1120,7 @@ expired_session(Config) when is_list(Config) ->
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, tls),
Client0 =
ssl_test_lib:start_client([{node, ClientNode},
@@ -947,39 +1160,54 @@ ssl2_erlang_server_openssl_client() ->
ssl2_erlang_server_openssl_client(Config) when is_list(Config) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {options, ServerOpts}]),
+ Port = ssl_test_lib:inet_port(Server),
+
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ "-ssl2", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
+ consume_port_exit(OpenSslPort),
+ ssl_test_lib:check_result(Server, {error, {tls_alert, "bad record mac"}}),
+ process_flag(trap_exit, false).
+%%--------------------------------------------------------------------
+ssl2_erlang_server_openssl_client_comp() ->
+ [{doc,"Test that ssl v2 clients are rejected"}].
+
+ssl2_erlang_server_openssl_client_comp(Config) when is_list(Config) ->
+ process_flag(trap_exit, true),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ V2Compat = proplists:get_value(v2_hello_compatible, Config),
+
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Data = "From openssl to erlang",
Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0},
{from, self()},
- {options, ServerOpts}]),
+ {options, [{v2_hello_compatible, V2Compat} | ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Exe = "openssl",
- Args = ["s_client", "-connect", "localhost:" ++ integer_to_list(Port),
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
"-ssl2", "-msg"],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
true = port_command(OpenSslPort, Data),
ct:log("Ports ~p~n", [[erlang:port_info(P) || P <- erlang:ports()]]),
- receive
- {'EXIT', OpenSslPort, _} = Exit ->
- ct:log("Received: ~p ~n", [Exit]),
- ok
- end,
- receive
- {'EXIT', _, _} = UnkownExit ->
- Msg = lists:flatten(io_lib:format("Received: ~p ~n", [UnkownExit])),
- ct:log(Msg),
- ct:comment(Msg),
- ok
- after 0 ->
- ok
- end,
+ consume_port_exit(OpenSslPort),
ssl_test_lib:check_result(Server, {error, {tls_alert, "protocol version"}}),
process_flag(trap_exit, false).
@@ -1200,22 +1428,22 @@ erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) ->
ok.
%--------------------------------------------------------------------------
erlang_server_openssl_client_sni_no_header(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test(Config, undefined, undefined, "server").
+ erlang_server_openssl_client_sni_test(Config, undefined, undefined, "server Peer cert").
erlang_server_openssl_client_sni_no_header_fun(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test_sni_fun(Config, undefined, undefined, "server").
+ erlang_server_openssl_client_sni_test_sni_fun(Config, undefined, undefined, "server Peer cert").
-erlang_server_openssl_client_sni_match(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test(Config, "a.server", "a.server", "a.server").
+erlang_server_openssl_client_sni_match(Config) when is_list(Config) ->
+ erlang_server_openssl_client_sni_test(Config, "a.server", "a.server", "server Peer cert").
erlang_server_openssl_client_sni_match_fun(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test_sni_fun(Config, "a.server", "a.server", "a.server").
+ erlang_server_openssl_client_sni_test_sni_fun(Config, "a.server", "a.server", "server Peer cert").
erlang_server_openssl_client_sni_no_match(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test(Config, "c.server", undefined, "server").
+ erlang_server_openssl_client_sni_test(Config, "c.server", undefined, "server Peer cert").
erlang_server_openssl_client_sni_no_match_fun(Config) when is_list(Config) ->
- erlang_server_openssl_client_sni_test_sni_fun(Config, "c.server", undefined, "server").
+ erlang_server_openssl_client_sni_test_sni_fun(Config, "c.server", undefined, "server Peer cert").
%%--------------------------------------------------------------------
@@ -1225,11 +1453,11 @@ run_suites(Ciphers, Version, Config, Type) ->
{ClientOpts, ServerOpts} =
case Type of
rsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_opts, Config)};
+ {ssl_test_lib:ssl_options(client_rsa_opts, Config),
+ ssl_test_lib:ssl_options(server_rsa_opts, Config)};
dsa ->
- {ssl_test_lib:ssl_options(client_opts, Config),
- ssl_test_lib:ssl_options(server_dsa_opts, Config)}
+ {ssl_test_lib:ssl_options(client_dsa_opts, Config),
+ ssl_test_lib:ssl_options(server_dsa_verify_opts, Config)}
end,
Result = lists:map(fun(Cipher) ->
@@ -1264,7 +1492,7 @@ client_check_result(Port, DataExpected, DataReceived) ->
_ ->
client_check_result(Port, DataExpected, NewData)
end
- after 3000 ->
+ after 20000 ->
ct:fail({"Time out on openSSL Client", {expected, DataExpected},
{got, DataReceived}})
end.
@@ -1282,7 +1510,7 @@ send_and_hostname(SSLSocket) ->
erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname, ExpectedCN) ->
ct:log("Start running handshake, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
- ServerOptions = proplists:get_value(sni_server_opts, Config) ++ proplists:get_value(server_opts, Config),
+ ServerOptions = proplists:get_value(sni_server_opts, Config) ++ proplists:get_value(server_rsa_opts, Config),
{_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()}, {mfa, {?MODULE, send_and_hostname, []}},
@@ -1296,11 +1524,7 @@ erlang_server_openssl_client_sni_test(Config, SNIHostname, ExpectedSNIHostname,
openssl_client_args(ssl_test_lib:supports_ssl_tls_version(sslv2), Hostname, Port, SNIHostname)
end,
ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
-
- %% Client check needs to be done befor server check,
- %% or server check might consume client messages
- ExpectedClientOutput = ["OK", "/CN=" ++ ExpectedCN ++ "/"],
- client_check_result(ClientPort, ExpectedClientOutput),
+
ssl_test_lib:check_result(Server, ExpectedSNIHostname),
ssl_test_lib:close_port(ClientPort),
ssl_test_lib:close(Server),
@@ -1311,7 +1535,7 @@ erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHo
ct:log("Start running handshake for sni_fun, Config: ~p, SNIHostname: ~p, ExpectedSNIHostname: ~p, ExpectedCN: ~p", [Config, SNIHostname, ExpectedSNIHostname, ExpectedCN]),
[{sni_hosts, ServerSNIConf}] = proplists:get_value(sni_server_opts, Config),
SNIFun = fun(Domain) -> proplists:get_value(Domain, ServerSNIConf, undefined) end,
- ServerOptions = proplists:get_value(server_opts, Config) ++ [{sni_fun, SNIFun}],
+ ServerOptions = proplists:get_value(server_rsa_opts, Config) ++ [{sni_fun, SNIFun}],
{_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
{from, self()}, {mfa, {?MODULE, send_and_hostname, []}},
@@ -1327,10 +1551,6 @@ erlang_server_openssl_client_sni_test_sni_fun(Config, SNIHostname, ExpectedSNIHo
ClientPort = ssl_test_lib:portable_open_port(Exe, ClientArgs),
- %% Client check needs to be done befor server check,
- %% or server check might consume client messages
- ExpectedClientOutput = ["OK", "/CN=" ++ ExpectedCN ++ "/"],
- client_check_result(ClientPort, ExpectedClientOutput),
ssl_test_lib:check_result(Server, ExpectedSNIHostname),
ssl_test_lib:close_port(ClientPort),
ssl_test_lib:close(Server).
@@ -1351,7 +1571,7 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
ConnectionInfo = {ok, {Version, CipherSuite}},
@@ -1394,8 +1614,8 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, OpensslServerOpts, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = ErlangClientOpts ++ ClientOpts0,
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1421,7 +1641,7 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -1440,8 +1660,8 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens
start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = proplists:get_value(server_opts, Config),
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_opts, Config),
+ ClientOpts0 = proplists:get_value(client_rsa_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"spdy/2">>]} | ClientOpts0],
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1457,7 +1677,7 @@ start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callba
Args = ["s_server", "-msg", "-alpn", "http/1.1,spdy/2", "-accept", integer_to_list(Port), ssl_test_lib:version_flag(Version),
"-cert", CertFile, "-key", KeyFile],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -1476,7 +1696,7 @@ start_erlang_client_and_openssl_server_for_alpn_negotiation(Config, Data, Callba
start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = proplists:get_value(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]} | ServerOpts0],
{_, ServerNode, _} = ssl_test_lib:run_where(Config),
@@ -1505,8 +1725,8 @@ start_erlang_server_and_openssl_client_for_alpn_negotiation(Config, Data, Callba
start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = proplists:get_value(server_opts, Config),
- ClientOpts0 = proplists:get_value(client_opts, Config),
+ ServerOpts = proplists:get_value(server_rsa_opts, Config),
+ ClientOpts0 = proplists:get_value(client_rsa_opts, Config),
ClientOpts = [{alpn_advertised_protocols, [<<"spdy/2">>]},
{client_preferred_next_protocols, {client, [<<"spdy/3">>, <<"http/1.1">>]}} | ClientOpts0],
@@ -1526,7 +1746,7 @@ start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, Ca
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -1545,7 +1765,7 @@ start_erlang_client_and_openssl_server_for_alpn_npn_negotiation(Config, Data, Ca
start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts0 = proplists:get_value(server_opts, Config),
+ ServerOpts0 = proplists:get_value(server_rsa_opts, Config),
ServerOpts = [{alpn_preferred_protocols, [<<"spdy/2">>]},
{next_protocols_advertised, [<<"spdy/3">>, <<"http/1.1">>]} | ServerOpts0],
@@ -1572,8 +1792,8 @@ start_erlang_server_and_openssl_client_for_alpn_npn_negotiation(Config, Data, Ca
start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts = ssl_test_lib:ssl_options(server_opts, Config),
- ClientOpts0 = ssl_test_lib:ssl_options(client_opts, Config),
+ ServerOpts = ssl_test_lib:ssl_options(server_rsa_opts, Config),
+ ClientOpts0 = ssl_test_lib:ssl_options(client_rsa_opts, Config),
ClientOpts = [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}} | ClientOpts0],
{ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
@@ -1591,7 +1811,7 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac
"-cert", CertFile, "-key", KeyFile],
OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
- ssl_test_lib:wait_for_openssl_server(Port),
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
{host, Hostname},
@@ -1610,10 +1830,10 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac
start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = [{next_protocols_advertised, [<<"spdy/2">>]}, ServerOpts0],
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -1624,7 +1844,8 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client", "-nextprotoneg", "http/1.0,spdy/2", "-msg", "-connect", "localhost:"
+ Args = ["s_client", "-nextprotoneg", "http/1.0,spdy/2", "-msg", "-connect",
+ hostname_format(Hostname) ++ ":"
++ integer_to_list(Port), ssl_test_lib:version_flag(Version)],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -1639,10 +1860,10 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac
start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenSSLClientOpts, Data, Callback) ->
process_flag(trap_exit, true),
- ServerOpts0 = ssl_test_lib:ssl_options(server_opts, Config),
+ ServerOpts0 = ssl_test_lib:ssl_options(server_rsa_opts, Config),
ServerOpts = ErlangServerOpts ++ ServerOpts0,
- {_, ServerNode, _} = ssl_test_lib:run_where(Config),
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
@@ -1653,8 +1874,9 @@ start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenS
Version = ssl_test_lib:protocol_version(Config),
Exe = "openssl",
- Args = ["s_client"] ++ OpenSSLClientOpts ++ ["-msg", "-connect", "localhost:" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version)],
+ Args = ["s_client"] ++ OpenSSLClientOpts ++ ["-msg", "-connect",
+ hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version)],
OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
@@ -1800,3 +2022,17 @@ openssl_client_args(false, Hostname, Port, ServerName) ->
openssl_client_args(true, Hostname, Port, ServerName) ->
["s_client", "-no_ssl2", "-connect", Hostname ++ ":" ++
integer_to_list(Port), "-servername", ServerName].
+
+consume_port_exit(OpenSSLPort) ->
+ receive
+ {'EXIT', OpenSSLPort, _} ->
+ ok
+ end.
+
+hostname_format(Hostname) ->
+ case lists:member($., Hostname) of
+ true ->
+ Hostname;
+ false ->
+ "localhost"
+ end.
diff --git a/lib/ssl/test/ssl_upgrade_SUITE.erl b/lib/ssl/test/ssl_upgrade_SUITE.erl
index 113b3b4158..875399db76 100644
--- a/lib/ssl/test/ssl_upgrade_SUITE.erl
+++ b/lib/ssl/test/ssl_upgrade_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,8 @@
server,
client,
soft,
- result_proxy
+ result_proxy,
+ skip
}).
all() ->
@@ -73,8 +74,15 @@ major_upgrade(Config) when is_list(Config) ->
minor_upgrade(Config) when is_list(Config) ->
ct_release_test:upgrade(ssl, minor,{?MODULE, #state{config = Config}}, Config).
-upgrade_init(CTData, #state{config = Config} = State) ->
- {ok, {_, _, Up, _Down}} = ct_release_test:get_appup(CTData, ssl),
+upgrade_init(CtData, State) ->
+ {ok,{FromVsn,ToVsn}} = ct_release_test:get_app_vsns(CtData, ssl),
+ upgrade_init(FromVsn, ToVsn, CtData, State).
+
+upgrade_init(_, "8.0.2", _, State) ->
+ %% Requires stdlib upgrade so it will be a node upgrade!
+ State#state{skip = true};
+upgrade_init(_, _, CtData, #state{config = Config} = State) ->
+ {ok, {_, _, Up, _Down}} = ct_release_test:get_appup(CtData, ssl),
ct:pal("Up: ~p", [Up]),
Soft = is_soft(Up), %% It is symmetrical, if upgrade is soft so is downgrade
Pid = spawn(?MODULE, result_proxy_init, [[]]),
@@ -88,6 +96,8 @@ upgrade_init(CTData, #state{config = Config} = State) ->
State#state{soft = Soft, result_proxy = Pid}
end.
+upgrade_upgraded(_, #state{skip = true} = State) ->
+ State;
upgrade_upgraded(_, #state{soft = false, config = Config, result_proxy = Pid} = State) ->
ct:pal("Restart upgrade ~n", []),
{Server, Client} = restart_start_connection(Config, Pid),
@@ -96,7 +106,6 @@ upgrade_upgraded(_, #state{soft = false, config = Config, result_proxy = Pid} =
ssl_test_lib:close(Client),
ok = Result,
State;
-
upgrade_upgraded(_, #state{server = Server0, client = Client0,
config = Config, soft = true,
result_proxy = Pid} = State) ->
@@ -110,6 +119,8 @@ upgrade_upgraded(_, #state{server = Server0, client = Client0,
{Server, Client} = soft_start_connection(Config, Pid),
State#state{server = Server, client = Client}.
+upgrade_downgraded(_, #state{skip = true} = State) ->
+ State;
upgrade_downgraded(_, #state{soft = false, config = Config, result_proxy = Pid} = State) ->
ct:pal("Restart downgrade: ~n", []),
{Server, Client} = restart_start_connection(Config, Pid),
@@ -119,7 +130,6 @@ upgrade_downgraded(_, #state{soft = false, config = Config, result_proxy = Pid}
Pid ! stop,
ok = Result,
State;
-
upgrade_downgraded(_, #state{server = Server, client = Client, soft = true, result_proxy = Pid} = State) ->
ct:pal("Soft downgrade: ~n", []),
Server ! changed_version,
diff --git a/lib/ssl/test/x509_test.erl b/lib/ssl/test/x509_test.erl
new file mode 100644
index 0000000000..fea01efdaf
--- /dev/null
+++ b/lib/ssl/test/x509_test.erl
@@ -0,0 +1,108 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+ -module(x509_test).
+
+ -include_lib("public_key/include/public_key.hrl").
+
+-export([extensions/1, gen_pem_config_files/3]).
+
+gen_pem_config_files(#{server_config := ServerConf,
+ client_config := ClientConf}, ClientBase, ServerBase) ->
+
+ ServerCaCertFile = ServerBase ++ "_server_cacerts.pem",
+ ServerCertFile = ServerBase ++ "_server_cert.pem",
+ ServerKeyFile = ServerBase ++ "_server_key.pem",
+
+ ClientCaCertFile = ClientBase ++ "_client_cacerts.pem",
+ ClientCertFile = ClientBase ++ "_client_cert.pem",
+ ClientKeyFile = ClientBase ++ "_client_key.pem",
+
+ do_gen_pem_config_files(ServerConf,
+ ServerCertFile,
+ ServerKeyFile,
+ ServerCaCertFile),
+ do_gen_pem_config_files(ClientConf,
+ ClientCertFile,
+ ClientKeyFile,
+ ClientCaCertFile),
+ [{server_config, [{certfile, ServerCertFile},
+ {keyfile, ServerKeyFile}, {cacertfile, ServerCaCertFile}]},
+ {client_config, [{certfile, ClientCertFile},
+ {keyfile, ClientKeyFile}, {cacertfile, ClientCaCertFile}]}].
+extensions(Exts) ->
+ [extension(Ext) || Ext <- Exts].
+
+
+do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) ->
+ CAs = proplists:get_value(cacerts, Config),
+ Cert = proplists:get_value(cert, Config),
+ Key = proplists:get_value(key, Config),
+ der_to_pem(CertFile, [cert_entry(Cert)]),
+ der_to_pem(KeyFile, [key_entry(Key)]),
+ der_to_pem(CAFile, ca_entries(CAs)).
+
+cert_entry(Cert) ->
+ {'Certificate', Cert, not_encrypted}.
+
+key_entry({'RSAPrivateKey', DERKey}) ->
+ {'RSAPrivateKey', DERKey, not_encrypted};
+key_entry({'DSAPrivateKey', DERKey}) ->
+ {'DSAPrivateKey', DERKey, not_encrypted};
+key_entry({'ECPrivateKey', DERKey}) ->
+ {'ECPrivateKey', DERKey, not_encrypted}.
+
+ca_entries(CAs) ->
+ [{'Certificate', CACert, not_encrypted} || CACert <- CAs].
+
+extension({_, undefined}) ->
+ [];
+extension({basic_constraints, Data}) ->
+ case Data of
+ default ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true},
+ critical=true};
+ false ->
+ [];
+ Len when is_integer(Len) ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = #'BasicConstraints'{cA=true, pathLenConstraint = Len},
+ critical = true};
+ _ ->
+ #'Extension'{extnID = ?'id-ce-basicConstraints',
+ extnValue = Data}
+ end;
+extension({key_usage, Value}) ->
+ #'Extension'{extnID = ?'id-ce-keyUsage',
+ extnValue = Value,
+ critical = false};
+extension({subject_alt, Hostname}) ->
+ #'Extension'{extnID = ?'id-ce-subjectAltName',
+ extnValue = [{dNSName, Hostname}],
+ critical = false};
+extension({Id, Data, Critical}) ->
+ #'Extension'{extnID = Id, extnValue = Data, critical = Critical}.
+
+der_to_pem(File, Entries) ->
+ PemBin = public_key:pem_encode(Entries),
+ file:write_file(File, PemBin).