Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 48 additions & 44 deletions lib/ssl/doc/ssl_app.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,53 @@ The environment parameters can be set on the command line, for example:
might be configurable, by the SSL application. This option can be overridden
by the version option to `ssl:connect/2,3` and `ssl:listen/2`.

- **`max_crl_cache = pos_integer() <optional>`** - Sets the
maximum number of entries allowed in the default crl store. Defaults to 150. Size limit
Comment thread
IngelaAndin marked this conversation as resolved.
Comment thread
IngelaAndin marked this conversation as resolved.
is enforced by emptying cache when limit is reached.

- **`ssl_pem_cache_clean = pos_integer() <optional>`** - Number of milliseconds
between PEM cache validations. Defaults to 2 minutes.

Note: The cache can be reloaded by calling `ssl:clear_pem_cache/0`.

- **`bypass_pem_cache = boolean() <optional>`** - Introduced in ssl-8.0.2.
Disables the PEM-cache. Can be used as a workaround for the PEM-cache
bottleneck before ssl-8.1.1. Defaults to false.

- **`internal_active_n = integer() <optional>`** - For TLS connections this
value is used to handle the internal socket. As the implementation was changed
from an active once to an active N behavior (N = 100), for performance
reasons, this option exist for possible tweaking or restoring of the old
behavior (internal_active_n = 1) in unforeseen scenarios. The option will not
affect erlang distribution over TLS that will always run in active N mode.
Added in ssl-9.1 (OTP-21.2).

- **`server_session_tickets_amount = integer() <optional>`** - Number of session
tickets sent by the server. It must be greater than 0. Defaults to 3.

- **`server_session_ticket_lifetime = integer() <optional>`** - Lifetime of
session tickets sent by the server. Servers must not use any value greater
than 604800 seconds (7 days). Expired tickets are automatically removed.
Defaults to 7200 seconds (2 hours).

- **`server_session_ticket_store_size = integer() <optional>`** - Sets the
maximum size of the server session ticket store (stateful tickets). Defaults
to 1000. Size limit is enforced by dropping old tickets.

- **`server_session_ticket_max_early_data = integer() <optional>`** - Sets the
maximum size of the early data that the server accepts and also configures its
NewSessionTicket messages to include this same size limit in their
early_data_indication extension. Defaults to 16384. Size limit is enforced by
both client and server.

- **`client_session_ticket_lifetime = integer() <optional>`** - Lifetime of
session tickets in the client ticket store. Expired tickets are automatically
removed. Defaults to 7200 seconds (2 hours).

- **`client_session_ticket_store_size = integer() <optional>`** - Sets the
maximum size of the client session ticket store. Defaults to 1000. Size limit
is enforced by dropping old tickets.

- **`session_lifetime = integer() <optional>`** - Maximum lifetime of the
session data in seconds. Defaults to 24 hours which is the maximum recommended
lifetime by [RFC 5246](http://www.ietf.org/rfc/5246rfc.txt). However sessions
Expand Down Expand Up @@ -108,54 +155,11 @@ The environment parameters can be set on the command line, for example:
entries will be invalidated regardless of their remaining lifetime. Defaults
to 1000. Recommended ssl-8.2.1 or later for this option to work as intended.

- **`ssl_pem_cache_clean = integer() <optional>`** - Number of milliseconds
between PEM cache validations. Defaults to 2 minutes.

Note: The cache can be reloaded by calling `ssl:clear_pem_cache/0`.

- **`bypass_pem_cache = boolean() <optional>`** - Introduced in ssl-8.0.2.
Disables the PEM-cache. Can be used as a workaround for the PEM-cache
bottleneck before ssl-8.1.1. Defaults to false.

- **`alert_timeout = integer() <optional>`** - Number of milliseconds between
- **`alert_timeout = pos_integer() <optional>`** - Number of milliseconds between
sending of a fatal alert and closing the connection. Waiting a little while
improves the peers chances to properly receiving the alert so it may shutdown
gracefully. Defaults to 5000 milliseconds.

- **`internal_active_n = integer() <optional>`** - For TLS connections this
value is used to handle the internal socket. As the implementation was changed
from an active once to an active N behavior (N = 100), for performance
reasons, this option exist for possible tweaking or restoring of the old
behavior (internal_active_n = 1) in unforeseen scenarios. The option will not
affect erlang distribution over TLS that will always run in active N mode.
Added in ssl-9.1 (OTP-21.2).

- **`server_session_tickets_amount = integer() <optional>`** - Number of session
tickets sent by the server. It must be greater than 0. Defaults to 3.

- **`server_session_ticket_lifetime = integer() <optional>`** - Lifetime of
session tickets sent by the server. Servers must not use any value greater
than 604800 seconds (7 days). Expired tickets are automatically removed.
Defaults to 7200 seconds (2 hours).

- **`server_session_ticket_store_size = integer() <optional>`** - Sets the
maximum size of the server session ticket store (stateful tickets). Defaults
to 1000. Size limit is enforced by dropping old tickets.

- **`server_session_ticket_max_early_data = integer() <optional>`** - Sets the
maximum size of the early data that the server accepts and also configures its
NewSessionTicket messages to include this same size limit in their
early_data_indication extension. Defaults to 16384. Size limit is enforced by
both client and server.

- **`client_session_ticket_lifetime = integer() <optional>`** - Lifetime of
session tickets in the client ticket store. Expired tickets are automatically
removed. Defaults to 7200 seconds (2 hours).

- **`client_session_ticket_store_size = integer() <optional>`** - Sets the
maximum size of the client session ticket store. Defaults to 1000. Size limit
is enforced by dropping old tickets.

## Error Logger and Event Handlers

The SSL application uses [OTP logger](`m:logger`). TLS/DTLS alerts are logged on
Expand Down
10 changes: 1 addition & 9 deletions lib/ssl/src/dtls_packet_demux.erl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ getstat(PacketSocket, Opts) ->
%%%===================================================================

init([Owner, Port0, TransportInfo, EmOpts, DTLSOptions, Socket]) ->
InternalActiveN = get_internal_active_n(),
InternalActiveN = ssl_config:get_internal_active_n(),
erlang:monitor(process, Owner),
{ok, SessionIdHandle} = session_id_tracker(Socket, DTLSOptions),
proc_lib:set_label({dtls_server_packet_demultiplexer, Port0}),
Expand Down Expand Up @@ -431,11 +431,3 @@ emulated_opts_list(Opts, [active | Rest], Acc) ->
session_id_tracker(Listener,_) ->
dtls_server_session_cache_sup:start_child(Listener).

get_internal_active_n() ->
case application:get_env(ssl, internal_active_n) of
{ok, N} when is_integer(N) ->
N;
_ ->
?INTERNAL_ACTIVE_N
end.

1 change: 0 additions & 1 deletion lib/ssl/src/dtls_server_session_cache_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
%% Supervisor callback
-export([init/1]).

-define(DEFAULT_MAX_SESSION_CACHE, 1000).
%%%=========================================================================
%%% API
%%%=========================================================================
Expand Down
14 changes: 14 additions & 0 deletions lib/ssl/src/ssl_config.erl
Comment thread
IngelaAndin marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
-define(DEFAULT_MAX_SESSION_CACHE, 1000).
-define(TWO_HOURS, 7200).
-define(SEVEN_DAYS, 604800).
-define(DEFAULT_MAX_CRL_CACHE, 150).
-define(INTERNAL_ACTIVE_N, 100).

%% Connection parameter configuration
-export([init/2,
Expand All @@ -44,6 +46,7 @@
%% Application configuration
-export([pre_1_3_session_opts/1,
get_max_early_data_size/0,
get_max_crl_cache/0,
get_ticket_lifetime/0,
get_ticket_store_size/0,
get_internal_active_n/0,
Expand Down Expand Up @@ -143,6 +146,14 @@ get_internal_active_n(true) ->
get_internal_active_n(false) ->
application_int(internal_active_n, ?INTERNAL_ACTIVE_N).

get_max_crl_cache() ->
case application:get_env(ssl, max_crl_cache) of
{ok, Size} when is_integer(Size) ->
Comment on lines +150 to +151

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
case application:get_env(ssl, max_crl_cache) of
{ok, Size} when is_integer(Size) ->
application_int(max_crl_cache, ?DEFAULT_MAX_CRL_CACHE)

Comment thread
IngelaAndin marked this conversation as resolved.
Size;
_ ->
?DEFAULT_MAX_CRL_CACHE
end.

%%====================================================================
%% Certificate and Key configuration
%%====================================================================
Expand Down Expand Up @@ -362,6 +373,9 @@ mldsa_priv_key_dec(Type, DERKey, PrivKey) ->
expandedkey = ExpandedKey}
end.

%%====================================================================
%% Internal functions
%%====================================================================
init_manager_name(false) ->
put(ssl_manager, ssl_manager:name(normal)),
put(ssl_pem_cache, ssl_pem_cache:name(normal));
Expand Down
10 changes: 6 additions & 4 deletions lib/ssl/src/ssl_crl_cache.erl
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,12 @@ cache_lookup(URL, {{Cache, _}, _}) ->

handle_http(URI, Rest, {_, [{http, Timeout}]} = CRLDbInfo) ->
CRLs = http_lookup(URI, Rest, CRLDbInfo, Timeout),
%% Uncomment to improve performance, but need to
%% implement cache limit and or cleaning to prevent
%% DoS attack possibilities
%%insert(URI, {der, CRLs}),
case CRLs of
not_available ->
ok;
_ ->
insert(URI, {der, CRLs})
end,
CRLs;
handle_http(_, Rest, CRLDbInfo) ->
get_crls(Rest, CRLDbInfo).
Expand Down
1 change: 0 additions & 1 deletion lib/ssl/src/ssl_internal.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@

-define(CDR_MAGIC, "GIOP").
-define(CDR_HDR_SIZE, 12).
-define(INTERNAL_ACTIVE_N, 100).
-define(DEPTH, 20).

-define(DEFAULT_TIMEOUT, 5000).
Expand Down
18 changes: 9 additions & 9 deletions lib/ssl/src/ssl_manager.erl
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,12 @@
session_cache_client_max :: integer(),
session_client_invalidator :: undefined | pid(),
options :: list(),
client_session_order :: gb_trees:tree()
client_session_order :: gb_trees:tree(),
max_crl_db_entries :: pos_integer()
}).

-define(GEN_UNIQUE_ID_MAX_TRIES, 10).
-define(SESSION_VALIDATION_INTERVAL, 60000).
-define(CLEAN_SESSION_DB, 60000).
-define(CLEAN_CERT_DB, 500).
-define(DEFAULT_MAX_SESSION_CACHE, 1000).
-define(LOAD_MITIGATION, 10).

%%====================================================================
Expand Down Expand Up @@ -268,7 +266,8 @@ init([ManagerName, PemCacheName, Opts]) ->
session_cache_client_max = ClientSessMax,
session_client_invalidator = undefined,
options = Opts,
client_session_order = gb_trees:empty()
client_session_order = gb_trees:empty(),
max_crl_db_entries = ssl_config:get_max_crl_cache()
}}.

%%--------------------------------------------------------------------
Expand Down Expand Up @@ -307,8 +306,9 @@ handle_call({{connection_init, Trustedcerts, Role, {CRLCb, UserCRLDb}}, Pid}, _F
end;

handle_call({{insert_crls, Path, CRLs}, _}, _From,
Comment thread
IngelaAndin marked this conversation as resolved.
#state{certificate_db = Db} = State) ->
ssl_pkix_db:add_crls(Db, Path, CRLs),
#state{certificate_db = Db,
max_crl_db_entries = Max} = State) ->
ssl_pkix_db:add_crls(Db, Path, CRLs, Max),
{reply, ok, State};

handle_call({{delete_crls, CRLsOrPath}, _}, _From,
Expand Down Expand Up @@ -345,8 +345,8 @@ handle_cast({invalidate_session, Host, Port,
session_cache_client_cb = CacheCb} = State) ->
invalidate_session(Cache, CacheCb, {{Host, Port}, ID}, Session, State);
handle_cast({insert_crls, Path, CRLs},
Comment thread
IngelaAndin marked this conversation as resolved.
#state{certificate_db = Db} = State) ->
ssl_pkix_db:add_crls(Db, Path, CRLs),
#state{certificate_db = Db, max_crl_db_entries = Max} = State) ->
ssl_pkix_db:add_crls(Db, Path, CRLs, Max),
{noreply, State};

handle_cast({delete_crls, CRLsOrPath},
Expand Down
34 changes: 28 additions & 6 deletions lib/ssl/src/ssl_pkix_db.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,27 @@
-include_lib("kernel/include/file.hrl").
-include_lib("kernel/include/logger.hrl").

-export([create/1, create_pem_cache/1,
add_crls/3, remove_crls/2, remove/1, add_trusted_certs/3,
-export([create/1,
create_pem_cache/1,
add_crls/4,
remove_crls/2,
remove/1,
add_trusted_certs/3,
refresh_trusted_certs/2,
refresh_trusted_certs/3,
extract_trusted_certs/1,
remove_trusted_certs/2, insert/3, remove/2, clear/1, db_size/1,
ref_count/3, lookup_trusted_cert/4, foldl/3, select_certentries_by_ref/2,
select_certs_by_ref/2, decode_pem_file/1, lookup/2]).
extract_trusted_certs/1,
remove_trusted_certs/2,
insert/3,
remove/2,
clear/1,
db_size/1,
ref_count/3,
lookup_trusted_cert/4,
foldl/3,
select_certentries_by_ref/2,
select_certs_by_ref/2,
decode_pem_file/1,
lookup/2]).
Comment thread
IngelaAndin marked this conversation as resolved.

%%====================================================================
%% Internal application API
Expand Down Expand Up @@ -365,6 +378,15 @@ new_trusted_cert_entry(File, [CertsDb, RefsDb, _ | _]) ->
Error
end.

add_crls([_,_,_, {Cache, _} | _]= DB, Path, CRLs, MaxSize) ->
case ets:info(Cache, size) + length(CRLs) > MaxSize of
true ->
Comment thread
IngelaAndin marked this conversation as resolved.
ets:delete_all_objects(Cache),
add_crls(DB, Path, CRLs);
false ->
add_crls(DB, Path, CRLs)
end.

Comment thread
IngelaAndin marked this conversation as resolved.
add_crls([_,_,_, {_, Mapping} | _], ?NO_DIST_POINT, CRLs) ->
[add_crls(CRL, Mapping) || CRL <- CRLs];
add_crls([_,_,_, {Cache, Mapping} | _], Path, CRLs) ->
Expand Down
19 changes: 3 additions & 16 deletions lib/ssl/src/tls_gen_connection_1_3.erl
Original file line number Diff line number Diff line change
Expand Up @@ -434,22 +434,9 @@ init_max_early_data_size(server) ->
internal_active_n(#{ktls := true}, Socket) ->
inet:setopts(Socket, [{packet, ssl_tls}]),
1;
internal_active_n(#{erl_dist := true}, _) ->
%% Start with a random number between 1 and ?INTERNAL_ACTIVE_N
%% In most cases distribution connections are established all at
%% the same time, and flow control engages with ?INTERNAL_ACTIVE_N for
%% all connections. Which creates a wave of "passive" messages, leading
%% to significant bump of memory & scheduler utilisation. Starting with
%% a random number between 1 and ?INTERNAL_ACTIVE_N helps to spread the
%% spike.
erlang:system_time() rem ?INTERNAL_ACTIVE_N + 1;
internal_active_n(_,_) ->
case application:get_env(ssl, internal_active_n) of
{ok, N} when is_integer(N) ->
N;
_ ->
?INTERNAL_ACTIVE_N
end.
internal_active_n(Options, _) ->
Boolean = maps:get(erl_dist, Options, false),
ssl_config:get_internal_active_n(Boolean).

exporter_secrets(ExporterMasterSecret, Labels, PRFAlgorithm) ->
DeriveSecret =
Expand Down
Loading