1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22
23-module(ssl_npn_hello_SUITE).
24
25%% Note: This directive should only be used in test suites.
26-compile(export_all).
27
28-include_lib("ssl/src/tls_record.hrl").
29-include_lib("ssl/src/tls_handshake.hrl").
30-include_lib("ssl/src/ssl_cipher.hrl").
31-include_lib("ssl/src/ssl_internal.hrl").
32-include_lib("common_test/include/ct.hrl").
33
34%%--------------------------------------------------------------------
35%% Common Test interface functions -----------------------------------
36%%--------------------------------------------------------------------
37all() ->
38    [encode_and_decode_npn_client_hello_test,
39     encode_and_decode_npn_server_hello_test,
40     encode_and_decode_client_hello_test,
41     encode_and_decode_server_hello_test,
42     create_server_hello_with_advertised_protocols_test,
43     create_server_hello_with_no_advertised_protocols_test].
44
45init_per_suite(Config) ->
46    catch crypto:stop(),
47    try crypto:start() of
48	ok ->
49	    Config
50    catch _:_ ->
51	    {skip, "Crypto did not start"}
52    end.
53
54end_per_suite(_Config) ->
55    %% This function is required since init_per_suite/1 exists.
56    ok.
57
58init_per_testcase(_TestCase, Config) ->
59    ssl_test_lib:ct_log_supported_protocol_versions(Config),
60    ct:timetrap({seconds, 5}),
61    Config.
62
63end_per_testcase(_TestCase, Config) ->
64    Config.
65
66%%--------------------------------------------------------------------
67%% Test Cases --------------------------------------------------------
68%%--------------------------------------------------------------------
69
70encode_and_decode_client_hello_test(Config) ->
71    HandShakeData = create_client_handshake(undefined),
72    Version = ssl_test_lib:protocol_version(Config),
73    {[{DecodedHandshakeMessage, _Raw}], _} =
74	tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
75                                        default_options_map()),
76    Extensions = DecodedHandshakeMessage#client_hello.extensions,
77    #{next_protocol_negotiation := undefined} = Extensions.
78%%--------------------------------------------------------------------
79encode_and_decode_npn_client_hello_test(Config) ->
80    HandShakeData = create_client_handshake(#next_protocol_negotiation{extension_data = <<>>}),
81    Version = ssl_test_lib:protocol_version(Config),
82    {[{DecodedHandshakeMessage, _Raw}], _} =
83	tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
84                                        default_options_map()),
85    Extensions = DecodedHandshakeMessage#client_hello.extensions,
86    #{next_protocol_negotiation := #next_protocol_negotiation{extension_data = <<>>}} = Extensions.
87%%--------------------------------------------------------------------
88encode_and_decode_server_hello_test(Config) ->
89    HandShakeData = create_server_handshake(undefined),
90    Version = ssl_test_lib:protocol_version(Config),
91    {[{DecodedHandshakeMessage, _Raw}], _} =
92	tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
93                                        default_options_map()),
94    Extensions = DecodedHandshakeMessage#server_hello.extensions,
95    #{next_protocol_negotiation := undefined} = Extensions.
96
97%%--------------------------------------------------------------------
98encode_and_decode_npn_server_hello_test(Config) ->
99    HandShakeData = create_server_handshake(#next_protocol_negotiation{extension_data = <<6, "spdy/2">>}),
100    Version = ssl_test_lib:protocol_version(Config),
101    {[{DecodedHandshakeMessage, _Raw}], _} =
102	tls_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>,
103                                        default_options_map()),
104    Extensions = DecodedHandshakeMessage#server_hello.extensions,
105    ct:log("~p ~n", [Extensions]),
106    #{next_protocol_negotiation := #next_protocol_negotiation{extension_data = <<6, "spdy/2">>}} = Extensions.
107
108%%--------------------------------------------------------------------
109create_server_hello_with_no_advertised_protocols_test(_Config) ->
110    Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(), #{}),
111    Extensions = Hello#server_hello.extensions,
112    #{} = Extensions.
113%%--------------------------------------------------------------------
114create_server_hello_with_advertised_protocols_test(_Config) ->
115    Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(),
116				       #{next_protocol_negotiation => [<<"spdy/1">>, <<"http/1.0">>, <<"http/1.1">>]}),
117    Extensions = Hello#server_hello.extensions,
118    #{next_protocol_negotiation := [<<"spdy/1">>, <<"http/1.0">>, <<"http/1.1">>]} = Extensions.
119%%--------------------------------------------------------------------
120%% Internal functions ------------------------------------------------
121%%--------------------------------------------------------------------
122create_client_handshake(Npn) ->
123    Vsn = {1, 2},
124    tls_handshake:encode_handshake(#client_hello{
125				      client_version = Vsn,
126				      random = <<1:256>>,
127				      session_id = <<>>,
128				      cipher_suites = [?TLS_DHE_DSS_WITH_DES_CBC_SHA],
129				      compression_methods = "",
130				      extensions = #{next_protocol_negotiation => Npn,
131						      renegotiation_info => #renegotiation_info{}}
132				     }, Vsn).
133
134create_server_handshake(Npn) ->
135    Vsn = {1, 2},
136    tls_handshake:encode_handshake(#server_hello{
137				      server_version = Vsn,
138				      random = <<1:256>>,
139				      session_id = <<>>,
140				      cipher_suite = ?TLS_DHE_DSS_WITH_DES_CBC_SHA,
141				      compression_method = 1,
142				      extensions = #{next_protocol_negotiation => Npn,
143                                                     renegotiation_info => #renegotiation_info{}}
144				     }, Vsn).
145
146create_connection_states() ->
147    #{pending_read => #{security_parameters => #security_parameters{
148						  server_random = <<1:256>>,
149						  compression_algorithm = 1,
150						  cipher_suite = ?TLS_DHE_DSS_WITH_DES_CBC_SHA
151						 }
152		       },
153      current_read => #{secure_renegotiation => false
154                       }
155     }.
156
157default_options_map() ->
158    Fun = fun (_Key, {Default, _}) -> Default end,
159    maps:map(Fun, ?RULES).
160