diff options
| author | Erlang/OTP <[email protected]> | 2016-06-13 13:21:22 +0200 | 
|---|---|---|
| committer | Erlang/OTP <[email protected]> | 2016-06-13 13:21:22 +0200 | 
| commit | 60b02048d3b51e4e59d324f52d482dcb338b3c47 (patch) | |
| tree | b9d04bd7d034e15cd45b1a4c1bd9e8a8dc149e9d /lib | |
| parent | d76ad05a499556d3b82e10ab08c4aa0d819d598f (diff) | |
| parent | 7001063d331e5702ba21bfec3b3d84c06a31fefb (diff) | |
| download | otp-60b02048d3b51e4e59d324f52d482dcb338b3c47.tar.gz otp-60b02048d3b51e4e59d324f52d482dcb338b3c47.tar.bz2 otp-60b02048d3b51e4e59d324f52d482dcb338b3c47.zip | |
Merge branch 'kennethlakin/maint/tls-use-negotiated-prf/PR-1042/OTP-13546' into maint-18
* kennethlakin/maint/tls-use-negotiated-prf/PR-1042/OTP-13546:
  ssl: Use cipher suite's PRF in prf/5
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ssl/src/ssl_connection.erl | 5 | ||||
| -rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 12 | ||||
| -rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 122 | 
3 files changed, 129 insertions, 10 deletions
| diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index f774873269..0f0072ba34 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -821,7 +821,8 @@ handle_sync_event({prf, Secret, Label, Seed, WantedLength}, _, StateName,      SecParams = ConnectionState#connection_state.security_parameters,      #security_parameters{master_secret = MasterSecret,  			 client_random = ClientRandom, -			 server_random = ServerRandom} = SecParams, +			 server_random = ServerRandom, +			 prf_algorithm = PRFAlgorithm} = SecParams,      Reply = try  		SecretToUse = case Secret of  				  _ when is_binary(Secret) -> Secret; @@ -832,7 +833,7 @@ handle_sync_event({prf, Secret, Label, Seed, WantedLength}, _, StateName,  					     (client_random, Acc) -> [ClientRandom|Acc];  					     (server_random, Acc) -> [ServerRandom|Acc]  					  end, [], Seed)), -		ssl_handshake:prf(Version, SecretToUse, Label, SeedToUse, WantedLength) +		ssl_handshake:prf(Version, PRFAlgorithm, SecretToUse, Label, SeedToUse, WantedLength)  	    catch  		exit:_ -> {error, badarg};  		error:Reason -> {error, Reason} diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 644903cf4b..235d6efbb6 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -74,7 +74,7 @@  	]).  %% MISC --export([select_version/3, prf/5, select_hashsign/5,  +-export([select_version/3, prf/6, select_hashsign/5,  	 select_hashsign_algs/3,  	 premaster_secret/2, premaster_secret/3, premaster_secret/4]). @@ -564,17 +564,15 @@ server_key_exchange_hash(md5sha, Value) ->  server_key_exchange_hash(Hash, Value) ->      crypto:hash(Hash, Value).  %%-------------------------------------------------------------------- --spec prf(ssl_record:ssl_version(), binary(), binary(), [binary()], non_neg_integer()) -> +-spec prf(ssl_record:ssl_version(), non_neg_integer(), binary(), binary(), [binary()], non_neg_integer()) ->  		 {ok, binary()} | {error, undefined}.  %%  %% Description: use the TLS PRF to generate key material  %%-------------------------------------------------------------------- -prf({3,0}, _, _, _, _) -> +prf({3,0}, _, _, _, _, _) ->      {error, undefined}; -prf({3,1}, Secret, Label, Seed, WantedLength) -> -    {ok, tls_v1:prf(?MD5SHA, Secret, Label, Seed, WantedLength)}; -prf({3,_N}, Secret, Label, Seed, WantedLength) -> -    {ok, tls_v1:prf(?SHA256, Secret, Label, Seed, WantedLength)}. +prf({3,_N}, PRFAlgo, Secret, Label, Seed, WantedLength) -> +    {ok, tls_v1:prf(PRFAlgo, Secret, Label, Seed, WantedLength)}.  %%-------------------------------------------------------------------- diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 89cdd40b4c..16211a54c1 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -145,7 +145,8 @@ api_tests() ->       versions_option,       server_name_indication_option,       accept_pool, -     new_options_in_accept +     new_options_in_accept, +     prf      ].  session_tests() -> @@ -324,6 +325,31 @@ init_per_testcase(rizzo, Config) ->      ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]),      ct:timetrap({seconds, 40}),      Config; +init_per_testcase(prf, Config) -> +    ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()]), +    ct:timetrap({seconds, 40}), +    case ?config(tc_group_path, Config) of +        [] -> Prop = []; +        [Prop] -> Prop +    end, +    case ?config(name, Prop) of +        undefined -> TlsVersions = [sslv3, tlsv1, 'tlsv1.1', 'tlsv1.2']; +        TlsVersion when is_atom(TlsVersion) -> +            TlsVersions = [TlsVersion] +    end, +    PRFS=[md5, sha, sha256, sha384, sha512], +    %All are the result of running tls_v1:prf(PrfAlgo, <<>>, <<>>, <<>>, 16) +    %with the specified PRF algorithm +    ExpectedPrfResults= +    [{md5, <<96,139,180,171,236,210,13,10,28,32,2,23,88,224,235,199>>}, +     {sha, <<95,3,183,114,33,169,197,187,231,243,19,242,220,228,70,151>>}, +     {sha256, <<166,249,145,171,43,95,158,232,6,60,17,90,183,180,0,155>>}, +     {sha384, <<153,182,217,96,186,130,105,85,65,103,123,247,146,91,47,106>>}, +     {sha512, <<145,8,98,38,243,96,42,94,163,33,53,49,241,4,127,28>>}, +     %TLS 1.0 and 1.1 PRF: +     {md5sha, <<63,136,3,217,205,123,200,177,251,211,17,229,132,4,173,80>>}], +    TestPlan = prf_create_plan(TlsVersions, PRFS, ExpectedPrfResults), +    [{prf_test_plan, TestPlan} | Config];  init_per_testcase(TestCase, Config) when TestCase == ssl_accept_timeout;  					 TestCase == client_closes_socket; @@ -429,6 +455,25 @@ new_options_in_accept(Config) when is_list(Config) ->      ssl_test_lib:close(Server),      ssl_test_lib:close(Client).  %%-------------------------------------------------------------------- +prf() -> +    [{doc,"Test that ssl:prf/5 uses the negotiated PRF."}]. +prf(Config) when is_list(Config) -> +    TestPlan = ?config(prf_test_plan, Config), +    case TestPlan of +        [] -> ct:fail({error, empty_prf_test_plan}); +        _ -> lists:foreach(fun(Suite) -> +                                   lists:foreach( +                                     fun(Test) -> +                                             V = ?config(tls_ver, Test), +                                             C = ?config(ciphers, Test), +                                             E = ?config(expected, Test), +                                             P = ?config(prf, Test), +                                             prf_run_test(Config, V, C, E, P) +                                     end, Suite) +                           end, TestPlan) +    end. + +%%--------------------------------------------------------------------  connection_info() ->      [{doc,"Test the API function ssl:connection_information/1"}]. @@ -3662,6 +3707,81 @@ basic_test(Config) ->      ssl_test_lib:close(Server),      ssl_test_lib:close(Client). +prf_create_plan(TlsVersions, PRFs, Results) -> +    lists:foldl(fun(Ver, Acc) -> +                        A = prf_ciphers_and_expected(Ver, PRFs, Results), +                        [A|Acc] +                end, [], TlsVersions). +prf_ciphers_and_expected(TlsVer, PRFs, Results) -> +    case TlsVer of +        TlsVer when TlsVer == sslv3 orelse TlsVer == tlsv1 +                    orelse TlsVer == 'tlsv1.1' -> +            Ciphers = ssl:cipher_suites(), +            {_, Expected} = lists:keyfind(md5sha, 1, Results), +            [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected}, {prf, md5sha}]]; +        'tlsv1.2' -> +            lists:foldl( +              fun(PRF, Acc) -> +                      Ciphers = prf_get_ciphers(TlsVer, PRF), +                      case Ciphers of +                          [] -> +                              ct:log("No ciphers for PRF algorithm ~p. Skipping.", [PRF]), +                              Acc; +                          Ciphers -> +                              {_, Expected} = lists:keyfind(PRF, 1, Results), +                              [[{tls_ver, TlsVer}, {ciphers, Ciphers}, {expected, Expected}, +                                {prf, PRF}] | Acc] +                      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_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}], +    ServerOpts = BaseOpts ++ ?config(server_opts, Config), +    ClientOpts = BaseOpts ++ ?config(client_opts, Config), +    Server = ssl_test_lib:start_server( +               [{node, ServerNode}, {port, 0}, {from, self()}, +                {mfa, {?MODULE, prf_verify_value, [TlsVer, Expected, Prf]}}, +                {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, prf_verify_value, [TlsVer, Expected, Prf]}}, +                {options, ClientOpts}]), +    ssl_test_lib:check_result(Server, ok, Client, ok), +    ssl_test_lib:close(Server), +    ssl_test_lib:close(Client). +prf_verify_value(Socket, TlsVer, Expected, Algo) -> +    Ret = ssl:prf(Socket, <<>>, <<>>, [<<>>], 16), +    case TlsVer of +        sslv3 -> +            case Ret of +                {error, undefined} -> ok; +                _ -> +                    {error, {expected, {error, undefined}, +                             got, Ret, tls_ver, TlsVer, prf_algorithm, Algo}} +            end; +        _ -> +            case Ret of +                {ok, Expected} -> ok; +                {ok, Val} -> {error, {expected, Expected, got, Val, tls_ver, TlsVer, +                                      prf_algorithm, Algo}} +            end +    end. +  send_recv_result_timeout_client(Socket) ->      {error, timeout} = ssl:recv(Socket, 11, 500),      ssl:send(Socket, "Hello world"), | 
