diff options
-rw-r--r-- | lib/crypto/doc/src/crypto.xml | 14 | ||||
-rw-r--r-- | lib/crypto/doc/src/crypto_app.xml | 18 | ||||
-rw-r--r-- | lib/crypto/src/crypto.app.src | 2 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 38 |
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), |