aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/crypto/doc/src/crypto.xml14
-rw-r--r--lib/crypto/doc/src/crypto_app.xml18
-rw-r--r--lib/crypto/src/crypto.app.src2
-rw-r--r--lib/crypto/src/crypto.erl38
4 files changed, 62 insertions, 10 deletions
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 5afab632cd..c32e3430ab 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -800,6 +800,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<v>Alg = crypto | crypto_cache</v>
</type>
<desc>
+ <marker id="rand_seed_alg-1" />
<p>
Creates state object for
<seealso marker="stdlib:rand">random number generation</seealso>,
@@ -814,6 +815,12 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
may throw exception <c>low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
+ <p>
+ The cache size can be changed from its default value using the
+ <seealso marker="crypto_app">
+ crypto app's
+ </seealso> configuration parameter <c>rand_cache_size</c>.
+ </p>
<p><em>Example</em></p>
<pre>
_ = crypto:rand_seed_alg(crypto_cache),
@@ -829,6 +836,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<v>Alg = crypto | crypto_cache</v>
</type>
<desc>
+ <marker id="rand_seed_alg_s-1" />
<p>
Creates state object for
<seealso marker="stdlib:rand">random number generation</seealso>,
@@ -852,6 +860,12 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
may throw exception <c>low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
+ <p>
+ The cache size can be changed from its default value using the
+ <seealso marker="crypto_app">
+ crypto app's
+ </seealso> configuration parameter <c>rand_cache_size</c>.
+ </p>
<note>
<p>
The state returned from this function can not be used
diff --git a/lib/crypto/doc/src/crypto_app.xml b/lib/crypto/doc/src/crypto_app.xml
index ba22557480..8296b1bc77 100644
--- a/lib/crypto/doc/src/crypto_app.xml
+++ b/lib/crypto/doc/src/crypto_app.xml
@@ -68,6 +68,24 @@
thus the crypto module will fail to load. This mechanism
prevents the accidental use of non-validated algorithms.</p>
</item>
+ <tag><c>rand_cache_size = integer()</c></tag>
+ <item>
+ <p>
+ Sets the cache size in bytes to use by
+ <seealso marker="crypto#rand_seed_alg-1">
+ <c>crypto:rand_seed_alg(crypto_cache)</c>
+ </seealso> and
+ <seealso marker="crypto#rand_seed_alg_s-1">
+ <c>crypto:rand_seed_alg_s(crypto_cache)</c>
+ </seealso>.
+ This parameter is read when a seed function is called,
+ and then kept in generators state object. It has a rather
+ small default value that causes reads of strong random bytes
+ about once per hundred calls for a random value.
+ The set value is rounded up to an integral number of words
+ of the size these seed functions use.
+ </p>
+ </item>
</taglist>
</section>
diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src
index 1d3f35e465..492aa10e51 100644
--- a/lib/crypto/src/crypto.app.src
+++ b/lib/crypto/src/crypto.app.src
@@ -24,7 +24,7 @@
crypto_ec_curves]},
{registered, []},
{applications, [kernel, stdlib]},
- {env, [{fips_mode, false}]},
+ {env, [{fips_mode, false}, {rand_cache_size, 896}]},
{runtime_dependencies, ["erts-9.0","stdlib-3.4","kernel-5.3"]}]}.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 69c98c651f..69ca884471 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -297,11 +297,17 @@ stream_decrypt(State, Data0) ->
%%
%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
%%
+-type rand_cache_seed() ::
+ nonempty_improper_list(non_neg_integer(), binary()).
-spec strong_rand_bytes(non_neg_integer()) -> binary().
-spec rand_seed() -> rand:state().
-spec rand_seed_s() -> rand:state().
--spec rand_seed_alg(Alg :: atom()) -> rand:state().
--spec rand_seed_alg_s(Alg :: atom()) -> rand:state().
+-spec rand_seed_alg(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
+-spec rand_seed_alg_s(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
-spec rand_uniform(crypto_integer(), crypto_integer()) ->
crypto_integer().
@@ -319,10 +325,12 @@ rand_seed() ->
rand_seed_s() ->
rand_seed_alg_s(?MODULE).
+-dialyzer({no_improper_lists, rand_seed_alg/1}).
rand_seed_alg(Alg) ->
rand:seed(rand_seed_alg_s(Alg)).
-
+
-define(CRYPTO_CACHE_BITS, 56).
+-dialyzer({no_improper_lists, rand_seed_alg_s/1}).
rand_seed_alg_s(?MODULE) ->
{#{ type => ?MODULE,
bits => 64,
@@ -331,10 +339,22 @@ rand_seed_alg_s(?MODULE) ->
uniform_n => fun ?MODULE:rand_plugin_uniform/2},
no_seed};
rand_seed_alg_s(crypto_cache) ->
+ EnvCacheSize =
+ application:get_env(
+ crypto, rand_cache_size,
+ ?CRYPTO_CACHE_BITS * 16), % Cache 16 * 8 words
+ Bytes = (?CRYPTO_CACHE_BITS + 7) div 8,
+ CacheSize =
+ case ((EnvCacheSize + (Bytes - 1)) div Bytes) * Bytes of
+ Sz when is_integer(Sz), Bytes =< Sz ->
+ Sz;
+ _ ->
+ Bytes
+ end,
{#{ type => crypto_cache,
bits => ?CRYPTO_CACHE_BITS,
next => fun ?MODULE:rand_cache_plugin_next/1},
- <<>>}.
+ [CacheSize|<<>>]}.
rand_plugin_next(Seed) ->
{bytes_to_integer(strong_rand_range(1 bsl 64)), Seed}.
@@ -345,11 +365,11 @@ rand_plugin_uniform(State) ->
rand_plugin_uniform(Max, State) ->
{bytes_to_integer(strong_rand_range(Max)) + 1, State}.
-rand_cache_plugin_next(<<>>) ->
- rand_cache_plugin_next(
- strong_rand_bytes(?CRYPTO_CACHE_BITS * 16)); % Cache 16 * 8 words
-rand_cache_plugin_next(<<I:?CRYPTO_CACHE_BITS,Cache/binary>>) ->
- {I, Cache}.
+-dialyzer({no_improper_lists, rand_cache_plugin_next/1}).
+rand_cache_plugin_next([CacheSize|<<>>]) ->
+ rand_cache_plugin_next([CacheSize|strong_rand_bytes(CacheSize)]);
+rand_cache_plugin_next([CacheSize|<<I:?CRYPTO_CACHE_BITS,Cache/binary>>]) ->
+ {I, [CacheSize|Cache]}.
strong_rand_range(Range) when is_integer(Range), Range > 0 ->
BinRange = int_to_bin(Range),