diff options
Diffstat (limited to 'lib/ssl')
-rw-r--r-- | lib/ssl/doc/src/book.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/fascicules.xml | 2 | ||||
-rw-r--r-- | lib/ssl/doc/src/notes.xml | 2 | ||||
-rw-r--r-- | lib/ssl/doc/src/pkix_certs.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/refman.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/release_notes.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl.xml | 6 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl_app.xml | 2 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl_distribution.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl_protocol.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/ssl_session_cache_api.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/usersguide.xml | 4 | ||||
-rw-r--r-- | lib/ssl/doc/src/using_ssl.xml | 4 | ||||
-rw-r--r-- | lib/ssl/src/dtls_handshake.erl | 2 | ||||
-rw-r--r-- | lib/ssl/src/ssl.erl | 86 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.hrl | 2 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 16 | ||||
-rw-r--r-- | lib/ssl/src/ssl_internal.hrl | 16 | ||||
-rw-r--r-- | lib/ssl/src/tls_v1.erl | 28 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 83 | ||||
-rw-r--r-- | lib/ssl/test/ssl_dist_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/ssl/test/ssl_test_lib.erl | 20 | ||||
-rw-r--r-- | lib/ssl/test/ssl_to_openssl_SUITE.erl | 67 |
23 files changed, 273 insertions, 97 deletions
diff --git a/lib/ssl/doc/src/book.xml b/lib/ssl/doc/src/book.xml index ecfb915b44..317997b22b 100644 --- a/lib/ssl/doc/src/book.xml +++ b/lib/ssl/doc/src/book.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE book SYSTEM "book.dtd"> <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <copyright> - <year>1999</year><year>2011</year> + <year>1999</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/fascicules.xml b/lib/ssl/doc/src/fascicules.xml index 7ee764fda3..7a60e8dd1f 100644 --- a/lib/ssl/doc/src/fascicules.xml +++ b/lib/ssl/doc/src/fascicules.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE fascicules SYSTEM "fascicules.dtd"> <fascicules> diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 141f076eed..0b28b1ebd4 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> diff --git a/lib/ssl/doc/src/pkix_certs.xml b/lib/ssl/doc/src/pkix_certs.xml index 1de807cadc..cfbc6b08d7 100644 --- a/lib/ssl/doc/src/pkix_certs.xml +++ b/lib/ssl/doc/src/pkix_certs.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2003</year><year>2009</year> + <year>2003</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/refman.xml b/lib/ssl/doc/src/refman.xml index 011819e82b..ae11198edb 100644 --- a/lib/ssl/doc/src/refman.xml +++ b/lib/ssl/doc/src/refman.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE application SYSTEM "application.dtd"> <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1999</year><year>2011</year> + <year>1999</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/release_notes.xml b/lib/ssl/doc/src/release_notes.xml index e7c766bb91..123e8e1451 100644 --- a/lib/ssl/doc/src/release_notes.xml +++ b/lib/ssl/doc/src/release_notes.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1999</year><year>2009</year> + <year>1999</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 1d74faf1b3..910dca3889 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> @@ -460,6 +460,10 @@ fun(srp, Username :: string(), UserState :: term()) -> </item> <tag>{log_alert, boolean()}</tag> <item>If false, error reports will not be displayed.</item> + <tag>{honor_cipher_order, boolean()}</tag> + <item>If true, use the server's preference for cipher selection. If false + (the default), use the client's preference. + </item> </taglist> </section> diff --git a/lib/ssl/doc/src/ssl_app.xml b/lib/ssl/doc/src/ssl_app.xml index 0ee5b23e47..43cb3934f7 100644 --- a/lib/ssl/doc/src/ssl_app.xml +++ b/lib/ssl/doc/src/ssl_app.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE appref SYSTEM "appref.dtd"> <appref> diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml index 4ae4ead3ee..4b4d042f70 100644 --- a/lib/ssl/doc/src/ssl_distribution.xml +++ b/lib/ssl/doc/src/ssl_distribution.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2000</year><year>2011</year> + <year>2000</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/ssl_protocol.xml b/lib/ssl/doc/src/ssl_protocol.xml index f540dc999b..cdfafe224b 100644 --- a/lib/ssl/doc/src/ssl_protocol.xml +++ b/lib/ssl/doc/src/ssl_protocol.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2003</year><year>2012</year> + <year>2003</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/ssl_session_cache_api.xml b/lib/ssl/doc/src/ssl_session_cache_api.xml index e0b07961fb..82de1784ca 100644 --- a/lib/ssl/doc/src/ssl_session_cache_api.xml +++ b/lib/ssl/doc/src/ssl_session_cache_api.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1999</year><year>2010</year> + <year>1999</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/usersguide.xml b/lib/ssl/doc/src/usersguide.xml index 6528c00a0b..b1c7190085 100644 --- a/lib/ssl/doc/src/usersguide.xml +++ b/lib/ssl/doc/src/usersguide.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE part SYSTEM "part.dtd"> <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2000</year><year>2010</year> + <year>2000</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/doc/src/using_ssl.xml b/lib/ssl/doc/src/using_ssl.xml index ab837a156a..cce388d02a 100644 --- a/lib/ssl/doc/src/using_ssl.xml +++ b/lib/ssl/doc/src/using_ssl.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2003</year><year>2011</year> + <year>2003</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl index ec7f21bd35..5db2434753 100644 --- a/lib/ssl/src/dtls_handshake.erl +++ b/lib/ssl/src/dtls_handshake.erl @@ -342,7 +342,7 @@ dtls_fragment_init(Length, 0, Length, Body) -> {Length, [{0, Length}], Body}; dtls_fragment_init(Length, FragmentOffset, FragmentLength, Body) -> Bin = dtls_fragment_bin_add(FragmentOffset, FragmentLength, Body, <<0:(Length*8)>>), - {Length, [{FragmentOffset, FragmentLength}], Bin}. + {Length, [{FragmentOffset, FragmentOffset + FragmentLength}], Bin}. dtls_fragment_bin_add(FragmentOffset, FragmentLength, Add, Buffer) -> <<First:FragmentOffset/bytes, _:FragmentLength/bytes, Rest/binary>> = Buffer, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index a7fd9f5f81..c3bdeb1a54 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -626,7 +626,7 @@ handle_options(Opts0, _Role) -> user_lookup_fun = handle_option(user_lookup_fun, Opts, undefined), psk_identity = handle_option(psk_identity, Opts, undefined), srp_identity = handle_option(srp_identity, Opts, undefined), - ciphers = handle_option(ciphers, Opts, []), + ciphers = handle_cipher_option(proplists:get_value(ciphers, Opts, []), hd(Versions)), %% Server side option reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun), reuse_sessions = handle_option(reuse_sessions, Opts, true), @@ -640,7 +640,8 @@ handle_options(Opts0, _Role) -> make_next_protocol_selector( handle_option(client_preferred_next_protocols, Opts, undefined)), log_alert = handle_option(log_alert, Opts, true), - server_name_indication = handle_option(server_name_indication, Opts, undefined) + server_name_indication = handle_option(server_name_indication, Opts, undefined), + honor_cipher_order = handle_option(honor_cipher_order, Opts, false) }, CbInfo = proplists:get_value(cb_info, Opts, {gen_tcp, tcp, tcp_closed, tcp_error}), @@ -652,7 +653,8 @@ handle_options(Opts0, _Role) -> reuse_session, reuse_sessions, ssl_imp, cb_info, renegotiate_at, secure_renegotiate, hibernate_after, erl_dist, next_protocols_advertised, - client_preferred_next_protocols, log_alert, server_name_indication], + client_preferred_next_protocols, log_alert, + server_name_indication, honor_cipher_order], SockOpts = lists:foldl(fun(Key, PropList) -> proplists:delete(Key, PropList) @@ -695,11 +697,9 @@ validate_option(verify_fun, Fun) when is_function(Fun) -> end, Fun}; validate_option(verify_fun, {Fun, _} = Value) when is_function(Fun) -> Value; -validate_option(fail_if_no_peer_cert, Value) - when Value == true; Value == false -> +validate_option(fail_if_no_peer_cert, Value) when is_boolean(Value) -> Value; -validate_option(verify_client_once, Value) - when Value == true; Value == false -> +validate_option(verify_client_once, Value) when is_boolean(Value) -> Value; validate_option(depth, Value) when is_integer(Value), Value >= 0, Value =< 255-> @@ -712,7 +712,7 @@ validate_option(certfile, undefined = Value) -> validate_option(certfile, Value) when is_binary(Value) -> Value; validate_option(certfile, Value) when is_list(Value) -> - list_to_binary(Value); + binary_filename(Value); validate_option(key, undefined) -> undefined; @@ -729,7 +729,7 @@ validate_option(keyfile, undefined) -> validate_option(keyfile, Value) when is_binary(Value) -> Value; validate_option(keyfile, Value) when is_list(Value), Value =/= "" -> - list_to_binary(Value); + binary_filename(Value); validate_option(password, Value) when is_list(Value) -> Value; @@ -743,7 +743,7 @@ validate_option(cacertfile, undefined) -> validate_option(cacertfile, Value) when is_binary(Value) -> Value; validate_option(cacertfile, Value) when is_list(Value), Value =/= ""-> - list_to_binary(Value); + binary_filename(Value); validate_option(dh, Value) when Value == undefined; is_binary(Value) -> Value; @@ -752,12 +752,12 @@ validate_option(dhfile, undefined = Value) -> validate_option(dhfile, Value) when is_binary(Value) -> Value; validate_option(dhfile, Value) when is_list(Value), Value =/= "" -> - list_to_binary(Value); + binary_filename(Value); validate_option(psk_identity, undefined) -> undefined; validate_option(psk_identity, Identity) when is_list(Identity), Identity =/= "", length(Identity) =< 65535 -> - list_to_binary(Identity); + binary_filename(Identity); validate_option(user_lookup_fun, undefined) -> undefined; validate_option(user_lookup_fun, {Fun, _} = Value) when is_function(Fun, 3) -> @@ -766,25 +766,15 @@ validate_option(srp_identity, undefined) -> undefined; validate_option(srp_identity, {Username, Password}) when is_list(Username), is_list(Password), Username =/= "", length(Username) =< 255 -> - {list_to_binary(Username), list_to_binary(Password)}; + {unicode:characters_to_binary(Username), + unicode:characters_to_binary(Password)}; -validate_option(ciphers, Value) when is_list(Value) -> - Version = tls_record:highest_protocol_version([]), - try cipher_suites(Version, Value) - catch - exit:_ -> - throw({error, {options, {ciphers, Value}}}); - error:_-> - throw({error, {options, {ciphers, Value}}}) - end; validate_option(reuse_session, Value) when is_function(Value) -> Value; -validate_option(reuse_sessions, Value) when Value == true; - Value == false -> +validate_option(reuse_sessions, Value) when is_boolean(Value) -> Value; -validate_option(secure_renegotiate, Value) when Value == true; - Value == false -> +validate_option(secure_renegotiate, Value) when is_boolean(Value) -> Value; validate_option(renegotiate_at, Value) when is_integer(Value) -> erlang:min(Value, ?DEFAULT_RENEGOTIATE_AT); @@ -793,8 +783,7 @@ validate_option(hibernate_after, undefined) -> undefined; validate_option(hibernate_after, Value) when is_integer(Value), Value >= 0 -> Value; -validate_option(erl_dist,Value) when Value == true; - Value == false -> +validate_option(erl_dist,Value) when is_boolean(Value) -> Value; validate_option(client_preferred_next_protocols = Opt, {Precedence, PreferredProtocols} = Value) when is_list(PreferredProtocols) -> @@ -820,8 +809,7 @@ validate_option(client_preferred_next_protocols = Opt, {Precedence, PreferredPro validate_option(client_preferred_next_protocols, undefined) -> undefined; -validate_option(log_alert, Value) when Value == true; - Value == false -> +validate_option(log_alert, Value) when is_boolean(Value) -> Value; validate_option(next_protocols_advertised = Opt, Value) when is_list(Value) -> case tls_record:highest_protocol_version([]) of @@ -840,6 +828,8 @@ validate_option(server_name_indication, disable) -> disable; validate_option(server_name_indication, undefined) -> undefined; +validate_option(honor_cipher_order, Value) when is_boolean(Value) -> + Value; validate_option(Opt, Value) -> throw({error, {options, {Opt, Value}}}). @@ -938,16 +928,26 @@ emulated_options([Opt|Opts], Inet, Emulated) -> emulated_options([], Inet,Emulated) -> {Inet, Emulated}. -cipher_suites(Version, []) -> +handle_cipher_option(Value, Version) when is_list(Value) -> + try binary_cipher_suites(Version, Value) of + Suites -> + Suites + catch + exit:_ -> + throw({error, {options, {ciphers, Value}}}); + error:_-> + throw({error, {options, {ciphers, Value}}}) + end. +binary_cipher_suites(Version, []) -> %% Defaults to all supported suits ssl_cipher:suites(Version); -cipher_suites(Version, [{_,_,_,_}| _] = Ciphers0) -> %% Backwards compatibility +binary_cipher_suites(Version, [{_,_,_,_}| _] = Ciphers0) -> %% Backwards compatibility Ciphers = [{KeyExchange, Cipher, Hash} || {KeyExchange, Cipher, Hash, _} <- Ciphers0], - cipher_suites(Version, Ciphers); -cipher_suites(Version, [{_,_,_}| _] = Ciphers0) -> + binary_cipher_suites(Version, Ciphers); +binary_cipher_suites(Version, [{_,_,_}| _] = Ciphers0) -> Ciphers = [ssl_cipher:suite(C) || C <- Ciphers0], - cipher_suites(Version, Ciphers); + binary_cipher_suites(Version, Ciphers); -cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) -> +binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) -> Supported0 = ssl_cipher:suites(Version) ++ ssl_cipher:anonymous_suites() ++ ssl_cipher:psk_suites(Version) @@ -955,18 +955,18 @@ cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) -> Supported = ssl_cipher:filter_suites(Supported0), case [Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported)] of [] -> - Supported; + Supported; %% Defaults to all supported suits Ciphers -> Ciphers end; -cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) -> +binary_cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) -> %% Format: ["RC4-SHA","RC4-MD5"] Ciphers = [ssl_cipher:openssl_suite(C) || C <- Ciphers0], - cipher_suites(Version, Ciphers); -cipher_suites(Version, Ciphers0) -> + binary_cipher_suites(Version, Ciphers); +binary_cipher_suites(Version, Ciphers0) -> %% Format: "RC4-SHA:RC4-MD5" Ciphers = [ssl_cipher:openssl_suite(C) || C <- string:tokens(Ciphers0, ":")], - cipher_suites(Version, Ciphers). + binary_cipher_suites(Version, Ciphers). unexpected_format(Error) -> lists:flatten(io_lib:format("Unexpected error: ~p", [Error])). @@ -1038,3 +1038,7 @@ connection_sup(tls_connection) -> tls_connection_sup; connection_sup(dtls_connection) -> dtls_connection_sup. + +binary_filename(FileName) -> + Enc = file:native_name_encoding(), + unicode:characters_to_binary(FileName, unicode, Enc). diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index 27489ca325..adb2e1debe 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -41,7 +41,7 @@ data_tag :: atom(), % ex tcp. close_tag :: atom(), % ex tcp_closed error_tag :: atom(), % ex tcp_error - host :: string() | inet:ipaddress(), + host :: string() | inet:ip_address(), port :: integer(), socket :: port(), ssl_options :: #ssl_options{}, diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 2b9bae6e80..7b4cf8eb06 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -164,7 +164,7 @@ next_protocol(SelectedProtocol) -> %%-------------------------------------------------------------------- -spec client_certificate_verify(undefined | der_cert(), binary(), - tls_version(), term(), private_key(), + tls_version(), term(), public_key:private_key(), tls_handshake_history()) -> #certificate_verify{} | ignore | #alert{}. %% @@ -207,12 +207,12 @@ certificate_request(CipherSuite, CertDbHandle, CertDbRef, Version) -> {premaster_secret, binary(), public_key_info()} | {dh, binary()} | {dh, {binary(), binary()}, #'DHParameter'{}, {HashAlgo::atom(), SignAlgo::atom()}, - binary(), binary(), private_key()} | + binary(), binary(), public_key:private_key()} | {ecdh, #'ECPrivateKey'{}} | {psk, binary()} | {dhe_psk, binary(), binary()} | {srp, {binary(), binary()}, #srp_user{}, {HashAlgo::atom(), SignAlgo::atom()}, - binary(), binary(), private_key()}) -> + binary(), binary(), public_key:private_key()}) -> #client_key_exchange{} | #server_key_exchange{}. %% @@ -1029,14 +1029,15 @@ cipher_suites(Suites, true) -> select_session(SuggestedSessionId, CipherSuites, Compressions, Port, #session{ecc = ECCCurve} = Session, Version, - #ssl_options{ciphers = UserSuites} = SslOpts, Cache, CacheCb, Cert) -> + #ssl_options{ciphers = UserSuites, honor_cipher_order = HCO} = SslOpts, + Cache, CacheCb, Cert) -> {SessionId, Resumed} = ssl_session:server_id(Port, SuggestedSessionId, SslOpts, Cert, Cache, CacheCb), case Resumed of undefined -> Suites = available_suites(Cert, UserSuites, Version, ECCCurve), - CipherSuite = select_cipher_suite(CipherSuites, Suites), + CipherSuite = select_cipher_suite(CipherSuites, Suites, HCO), Compression = select_compression(Compressions), {new, Session#session{session_id = SessionId, cipher_suite = CipherSuite, @@ -1796,6 +1797,11 @@ handle_srp_extension(#srp{username = Username}, Session) -> %%-------------Misc -------------------------------- +select_cipher_suite(CipherSuites, Suites, false) -> + select_cipher_suite(CipherSuites, Suites); +select_cipher_suite(CipherSuites, Suites, true) -> + select_cipher_suite(Suites, CipherSuites). + select_cipher_suite([], _) -> no_suite; select_cipher_suite([Suite | ClientSuites], SupportedSuites) -> diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index 0186f9fca2..64b89e9f95 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -35,7 +35,6 @@ -type certdb_ref() :: reference(). -type db_handle() :: term(). -type der_cert() :: binary(). --type private_key() :: #'RSAPrivateKey'{} | #'DSAPrivateKey'{} | #'ECPrivateKey'{}. -type issuer() :: tuple(). -type serialnumber() :: integer(). -type cert_key() :: {reference(), integer(), issuer()}. @@ -83,13 +82,13 @@ validate_extensions_fun, depth :: integer(), certfile :: binary(), - cert :: der_encoded(), + cert :: public_key:der_encoded(), keyfile :: binary(), - key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', der_encoded()}, + key :: {'RSAPrivateKey' | 'DSAPrivateKey' | 'ECPrivateKey' | 'PrivateKeyInfo', public_key:der_encoded()}, password :: string(), - cacerts :: [der_encoded()], + cacerts :: [public_key:der_encoded()], cacertfile :: binary(), - dh :: der_encoded(), + dh :: public_key:der_encoded(), dhfile :: binary(), user_lookup_fun, % server option, fun to lookup the user psk_identity :: binary(), @@ -114,7 +113,10 @@ next_protocols_advertised = undefined, %% [binary()], next_protocol_selector = undefined, %% fun([binary()]) -> binary()) log_alert :: boolean(), - server_name_indication = undefined + server_name_indication = undefined, + %% Should the server prefer its own cipher order over the one provided by + %% the client? + honor_cipher_order = false }). -record(config, {ssl, %% SSL parameters diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl index 2395e98642..7c7fdd64c3 100644 --- a/lib/ssl/src/tls_v1.erl +++ b/lib/ssl/src/tls_v1.erl @@ -368,11 +368,19 @@ finished_label(server) -> %% list ECC curves in prefered order ecc_curves(_Minor) -> - [?sect571r1,?sect571k1,?secp521r1,?sect409k1,?sect409r1, - ?secp384r1,?sect283k1,?sect283r1,?secp256k1,?secp256r1, - ?sect239k1,?sect233k1,?sect233r1,?secp224k1,?secp224r1, - ?sect193r1,?sect193r2,?secp192k1,?secp192r1,?sect163k1, - ?sect163r1,?sect163r2,?secp160k1,?secp160r1,?secp160r2]. + TLSCurves = [sect571r1,sect571k1,secp521r1,brainpoolP512r1, + sect409k1,sect409r1,brainpoolP384r1,secp384r1, + sect283k1,sect283r1,brainpoolP256r1,secp256k1,secp256r1, + sect239k1,sect233k1,sect233r1,secp224k1,secp224r1, + sect193r1,sect193r2,secp192k1,secp192r1,sect163k1, + sect163r1,sect163r2,secp160k1,secp160r1,secp160r2], + CryptoCurves = crypto:ec_curves(), + lists:foldr(fun(Curve, Curves) -> + case proplists:get_bool(Curve, CryptoCurves) of + true -> [pubkey_cert_records:namedCurves(Curve)|Curves]; + false -> Curves + end + end, [], TLSCurves). %% ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) oid_to_enum(?sect163k1) -> 1; @@ -399,7 +407,10 @@ oid_to_enum(?secp224r1) -> 21; oid_to_enum(?secp256k1) -> 22; oid_to_enum(?secp256r1) -> 23; oid_to_enum(?secp384r1) -> 24; -oid_to_enum(?secp521r1) -> 25. +oid_to_enum(?secp521r1) -> 25; +oid_to_enum(?brainpoolP256r1) -> 26; +oid_to_enum(?brainpoolP384r1) -> 27; +oid_to_enum(?brainpoolP512r1) -> 28. enum_to_oid(1) -> ?sect163k1; enum_to_oid(2) -> ?sect163r1; @@ -425,7 +436,10 @@ enum_to_oid(21) -> ?secp224r1; enum_to_oid(22) -> ?secp256k1; enum_to_oid(23) -> ?secp256r1; enum_to_oid(24) -> ?secp384r1; -enum_to_oid(25) -> ?secp521r1. +enum_to_oid(25) -> ?secp521r1; +enum_to_oid(26) -> ?brainpoolP256r1; +enum_to_oid(27) -> ?brainpoolP384r1; +enum_to_oid(28) -> ?brainpoolP512r1. sufficent_ec_support() -> CryptoSupport = crypto:supports(), diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 1006b23a30..2e216b32fa 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -86,6 +86,7 @@ basic_tests() -> [app, alerts, send_close, + version_option, connect_twice, connect_dist, clear_pem_cache @@ -110,7 +111,10 @@ options_tests() -> empty_protocol_versions, ipv6, reuseaddr, - tcp_reuseaddr]. + tcp_reuseaddr, + honor_server_cipher_order, + honor_client_cipher_order +]. api_tests() -> [connection_info, @@ -1069,6 +1073,13 @@ send_close(Config) when is_list(Config) -> {error, _} = ssl:send(SslS, "Hello world"). %%-------------------------------------------------------------------- +version_option() -> + [{doc, "Use version option and do no specify ciphers list. Bug specified incorrect ciphers"}]. +version_option(Config) when is_list(Config) -> + Versions = proplists:get_value(supported, ssl:versions()), + [version_option_test(Config, Version) || Version <- Versions]. + +%%-------------------------------------------------------------------- close_transport_accept() -> [{doc,"Tests closing ssl socket when waiting on ssl:transport_accept/1"}]. @@ -2443,6 +2454,51 @@ tcp_reuseaddr(Config) when is_list(Config) -> %%-------------------------------------------------------------------- +honor_server_cipher_order() -> + [{doc,"Test API honor server cipher order."}]. +honor_server_cipher_order(Config) when is_list(Config) -> + ClientCiphers = [{rsa, aes_128_cbc, sha}, {rsa, aes_256_cbc, sha}], + ServerCiphers = [{rsa, aes_256_cbc, sha}, {rsa, aes_128_cbc, sha}], +honor_cipher_order(Config, true, ServerCiphers, ClientCiphers, {rsa, aes_256_cbc, sha}). + +honor_client_cipher_order() -> + [{doc,"Test API honor server cipher order."}]. +honor_client_cipher_order(Config) when is_list(Config) -> + ClientCiphers = [{rsa, aes_128_cbc, sha}, {rsa, aes_256_cbc, sha}], + ServerCiphers = [{rsa, aes_256_cbc, sha}, {rsa, aes_128_cbc, sha}], +honor_cipher_order(Config, false, ServerCiphers, ClientCiphers, {rsa, aes_128_cbc, sha}). + +honor_cipher_order(Config, Honor, ServerCiphers, ClientCiphers, Expected) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(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, {?MODULE, connection_info_result, []}}, + {options, [{ciphers, ServerCiphers}, {honor_cipher_order, Honor} + | 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, []}}, + {options, [{ciphers, ClientCiphers}, {honor_cipher_order, Honor} + | ClientOpts]}]), + + Version = + tls_record:protocol_version(tls_record:highest_protocol_version([])), + + ServerMsg = ClientMsg = {ok, {Version, Expected}}, + + ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- + hibernate() -> [{doc,"Check that an SSL connection that is started with option " "{hibernate_after, 1000} indeed hibernates after 1000ms of " @@ -3440,3 +3496,28 @@ shutdown_both_result(Socket, client) -> peername_result(S) -> ssl:peername(S). + +version_option_test(Config, Version) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(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, []}}, + {options, [{active, false}, {versions, [Version]}| 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, []}}, + {options, [{active, false}, {versions, [Version]}| ClientOpts]}]), + + ct:log("Testcase ~p, Client ~p Server ~p ~n", + [self(), Client, Server]), + + 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_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index d3b523ca8c..1a1b2af8d4 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -324,7 +324,7 @@ start_ssl_node_raw(Name, Args) -> [binary, {packet, 4}, {active, false}]), {ok, ListenPort} = inet:port(LSock), CmdLine = mk_node_cmdline(ListenPort, Name, Args), - ?t:format("Attempting to start ssl node ~s: ~s~n", [Name, CmdLine]), + ?t:format("Attempting to start ssl node ~ts: ~ts~n", [Name, CmdLine]), case open_port({spawn, CmdLine}, []) of Port when is_port(Port) -> unlink(Port), diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 74fadc0cc7..7ed9adfcd9 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-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -146,7 +146,7 @@ remove_close_msg(ReconnectTimes) -> end. start_client(Args) -> - Result = spawn_link(?MODULE, run_client, [lists:delete(return_socket, Args)]), + Result = spawn_link(?MODULE, run_client_init, [lists:delete(return_socket, Args)]), receive { connected, Socket } -> case lists:member(return_socket, Args) of @@ -155,6 +155,10 @@ start_client(Args) -> end end. +run_client_init(Opts) -> + put(retries, 0), + run_client(Opts). + run_client(Opts) -> Node = proplists:get_value(node, Opts), Host = proplists:get_value(host, Opts), @@ -189,9 +193,19 @@ run_client(Opts) -> {gen_tcp, closed} -> ok end; + {error, econnrefused = Reason} -> + case get(retries) of + N when N < 5 -> + put(retries, N+1), + ct:sleep(?SLEEP), + run_client(Opts); + _ -> + ct:log("Client faild several times: connection failed: ~p ~n", [Reason]), + Pid ! {self(), {error, Reason}} + end; {error, Reason} -> ct:log("Client: connection failed: ~p ~n", [Reason]), - Pid ! {self(), {error, Reason}} + Pid ! {self(), {error, Reason}} end. close(Pid) -> diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 21f0172dba..a7361755e5 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-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -154,22 +154,31 @@ special_init(TestCase, Config) TestCase == erlang_client_openssl_server_nowrap_seqnum; TestCase == erlang_server_openssl_client_nowrap_seqnum -> - check_sane_openssl_renegotaite(Config); + {ok, Version} = application:get_env(ssl, protocol_version), + check_sane_openssl_renegotaite(Config, Version); special_init(ssl2_erlang_server_openssl_client, Config) -> check_sane_openssl_sslv2(Config); special_init(TestCase, Config) when TestCase == erlang_client_openssl_server_npn; - TestCase == erlang_server_openssl_client_npn; - TestCase == erlang_server_openssl_client_npn_renegotiate; - TestCase == erlang_client_openssl_server_npn_renegotiate; + TestCase == erlang_server_openssl_client_npn; TestCase == erlang_server_openssl_client_npn_only_server; TestCase == erlang_server_openssl_client_npn_only_client; TestCase == erlang_client_openssl_server_npn_only_client; TestCase == erlang_client_openssl_server_npn_only_server -> check_openssl_npn_support(Config); +special_init(TestCase, Config) + when TestCase == erlang_server_openssl_client_npn_renegotiate; + TestCase == erlang_client_openssl_server_npn_renegotiate -> + {ok, Version} = application:get_env(ssl, protocol_version), + case check_sane_openssl_renegotaite(Config, Version) of + {skip, _} = Skip -> + Skip; + _ -> + check_openssl_npn_support(Config) + end; special_init(_, Config) -> Config. @@ -239,7 +248,7 @@ basic_erlang_server_openssl_client(Config) when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ - " -host localhost", + " -host localhost" ++ workaround_openssl_s_clinent(), ct:log("openssl cmd: ~p~n", [Cmd]), @@ -903,8 +912,16 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) -> {'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, ssl_test_lib:check_result(Server, {error, {tls_alert, "protocol version"}}), process_flag(trap_exit, false). @@ -1315,8 +1332,25 @@ check_openssl_npn_support(Config) -> Config end. +check_sane_openssl_renegotaite(Config, Version) when Version == 'tlsv1.1'; + Version == 'tlsv1.2' -> + case os:cmd("openssl version") of + "OpenSSL 1.0.1c" ++ _ -> + {skip, "Known renegotiation bug in OpenSSL"}; + "OpenSSL 1.0.1b" ++ _ -> + {skip, "Known renegotiation bug in OpenSSL"}; + "OpenSSL 1.0.1a" ++ _ -> + {skip, "Known renegotiation bug in OpenSSL"}; + "OpenSSL 1.0.1" ++ _ -> + {skip, "Known renegotiation bug in OpenSSL"}; + _ -> + check_sane_openssl_renegotaite(Config) + end; +check_sane_openssl_renegotaite(Config, _) -> + check_sane_openssl_renegotaite(Config). + check_sane_openssl_renegotaite(Config) -> - case os:cmd("openssl version") of + case os:cmd("openssl version") of "OpenSSL 0.9.8" ++ _ -> {skip, "Known renegotiation bug in OpenSSL"}; "OpenSSL 0.9.7" ++ _ -> @@ -1349,3 +1383,20 @@ supports_sslv2(Port) -> true end. +workaround_openssl_s_clinent() -> + %% http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=683159 + %% https://bugs.archlinux.org/task/33919 + %% Bug seems to manifests it self if TLS version is not + %% explicitly specified + case os:cmd("openssl version") of + "OpenSSL 1.0.1c" ++ _ -> + " -no_tls1_2 "; + "OpenSSL 1.0.1d" ++ _ -> + " -no_tls1_2 "; + "OpenSSL 1.0.1e" ++ _ -> + " -no_tls1_2 "; + "OpenSSL 1.0.1f" ++ _ -> + " -no_tls1_2 "; + _ -> + "" + end. |