1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2013-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%
%%
%%
%%----------------------------------------------------------------------
%% Purpose: SSL/TLS specific state
%%----------------------------------------------------------------------
-ifndef(ssl_connection).
-define(ssl_connection, true).
-include("ssl_internal.hrl").
-include("ssl_record.hrl").
-include("ssl_handshake.hrl").
-include("ssl_srp.hrl").
-include("ssl_cipher.hrl").
-include_lib("public_key/include/public_key.hrl").
-record(static_env, {
role :: client | server,
transport_cb :: atom(), % callback module
protocol_cb :: tls_connection | dtls_connection,
data_tag :: atom(), % ex tcp.
close_tag :: atom(), % ex tcp_closed
error_tag :: atom(), % ex tcp_error
host :: string() | inet:ip_address(),
port :: integer(),
socket :: port() | tuple(), %% TODO: dtls socket
cert_db :: reference() | 'undefined',
session_cache :: db_handle(),
session_cache_cb :: atom(),
crl_db :: term(),
file_ref_db :: db_handle(),
cert_db_ref :: certdb_ref() | 'undefined',
tracker :: pid() | 'undefined' %% Tracker process for listen socket
}).
-record(handshake_env, {
client_hello_version :: ssl_record:ssl_version() | 'undefined',
unprocessed_handshake_events = 0 :: integer(),
tls_handshake_history :: ssl_handshake:ssl_handshake_history() | secret_printout()
| 'undefined',
expecting_finished = false ::boolean(),
renegotiation :: undefined | {boolean(), From::term() | internal | peer},
allow_renegotiate = true ::boolean(),
%% Ext handling
hello, %%:: #client_hello{} | #server_hello{}
sni_hostname = undefined,
expecting_next_protocol_negotiation = false ::boolean(),
next_protocol = undefined :: undefined | binary(),
negotiated_protocol,
hashsign_algorithm = {undefined, undefined},
cert_hashsign_algorithm = {undefined, undefined},
%% key exchange
kex_algorithm :: ssl:key_algo(),
diffie_hellman_params:: #'DHParameter'{} | undefined | secret_printout(),
srp_params :: #srp_user{} | secret_printout() | 'undefined',
public_key_info :: ssl_handshake:public_key_info() | 'undefined',
premaster_secret :: binary() | secret_printout() | 'undefined',
server_psk_identity :: binary() | 'undefined' % server psk identity hint
}).
-record(connection_env, {
user_application :: {Monitor::reference(), User::pid()},
downgrade,
terminated = false ::boolean() | closed,
negotiated_version :: ssl_record:ssl_version() | 'undefined',
erl_dist_handle = undefined :: erlang:dist_handle() | undefined,
private_key :: public_key:private_key() | secret_printout() | 'undefined'
}).
-record(state, {
static_env :: #static_env{},
connection_env :: #connection_env{} | secret_printout(),
ssl_options :: #ssl_options{},
socket_options :: #socket_options{},
%% Hanshake %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
handshake_env :: #handshake_env{} | secret_printout(),
%% Buffer of TLS/DTLS records, used during the TLS
%% handshake to when possible pack more than one TLS
%% record into the underlaying packet
%% format. Introduced by DTLS - RFC 4347. The
%% mecahnism is also usefull in TLS although we do not
%% need to worry about packet loss in TLS. In DTLS we
%% need to track DTLS handshake seqnr
flight_buffer = [] :: list() | map(),
client_certificate_requested = false :: boolean(),
diffie_hellman_keys :: {PublicKey :: binary(), PrivateKey :: binary()} | #'ECPrivateKey'{} | undefined | secret_printout(),
srp_keys ::{PublicKey :: binary(), PrivateKey :: binary()} | secret_printout() | 'undefined',
protocol_specific = #{} :: map(),
session :: #session{} | secret_printout(),
%% Data shuffling %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
connection_states :: ssl_record:connection_states() | secret_printout(),
protocol_buffers :: term() | secret_printout() , %% #protocol_buffers{} from tls_record.hrl or dtls_recor.hr
user_data_buffer :: undefined | binary() | secret_printout(),
bytes_to_read :: undefined | integer(), %% bytes to read in passive mode
%% recv and start handling
start_or_recv_from :: term(),
timer :: undefined | reference() % start_or_recive_timer
}).
-define(DEFAULT_DIFFIE_HELLMAN_PARAMS,
#'DHParameter'{prime = ?DEFAULT_DIFFIE_HELLMAN_PRIME,
base = ?DEFAULT_DIFFIE_HELLMAN_GENERATOR}).
-define(WAIT_TO_ALLOW_RENEGOTIATION, 12000).
-endif. % -ifdef(ssl_connection).
|