%%
%% %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(),
kex_keys :: {PublicKey :: binary(), PrivateKey :: binary()} | #'ECPrivateKey'{} | undefined | secret_printout(),
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(),
protocol_specific = #{} :: map(),
session :: #session{} | secret_printout(),
key_share,
%% 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(),
log_level
}).
-define(DEFAULT_DIFFIE_HELLMAN_PARAMS,
#'DHParameter'{prime = ?DEFAULT_DIFFIE_HELLMAN_PRIME,
base = ?DEFAULT_DIFFIE_HELLMAN_GENERATOR}).
-define(WAIT_TO_ALLOW_RENEGOTIATION, 12000).
%%----------------------------------------------------------------------
%% TLS 1.3
%%----------------------------------------------------------------------
%% TLS 1.3 uses the same state record with the following differences:
%%
%% state :: record()
%%
%% session_cache - not implemented
%% session_cache_cb - not implemented
%% crl_db - not implemented
%% client_hello_version - Bleichenbacher mitigation in TLS 1.2
%% client_certificate_requested - Built into TLS 1.3 state machine
%% key_algorithm - not used
%% diffie_hellman_params - used in TLS 1.2 ECDH key exchange
%% diffie_hellman_keys - used in TLS 1.2 ECDH key exchange
%% psk_identity - not used
%% srp_params - not used, no srp extension in TLS 1.3
%% srp_keys - not used, no srp extension in TLS 1.3
%% premaster_secret - not used
%% renegotiation - TLS 1.3 forbids renegotiation
%% hello - used in user_hello, handshake continue
%% allow_renegotiate - TLS 1.3 forbids renegotiation
%% expecting_next_protocol_negotiation - ALPN replaced NPN, depricated in TLS 1.3
%% expecting_finished - not implemented, used by abbreviated
%% next_protocol - ALPN replaced NPN, depricated in TLS 1.3
%%
%% connection_state :: map()
%%
%% compression_state - not used
%% mac_secret - not used
%% sequence_number - not used
%% secure_renegotiation - not used, no renegotiation_info in TLS 1.3
%% client_verify_data - not used, no renegotiation_info in TLS 1.3
%% server_verify_data - not used, no renegotiation_info in TLS 1.3
%% beast_mitigation - not used
%%
%% security_parameters :: map()
%%
%% cipher_type - TLS 1.3 uses only AEAD ciphers
%% iv_size - not used
%% key_size - not used
%% key_material_length - not used
%% expanded_key_material_length - used in SSL 3.0
%% mac_algorithm - not used
%% prf_algorithm - not used
%% hash_size - not used
%% compression_algorithm - not used
%% master_secret - used for multiple secret types in TLS 1.3
%% client_random - not used
%% server_random - not used
%% exportable - not used
%%
%% cipher_state :: record()
%% nonce - used for sequence_number
-endif. % -ifdef(ssl_connection).