diff options
Diffstat (limited to 'lib/crypto/src/crypto.erl')
-rw-r--r-- | lib/crypto/src/crypto.erl | 132 |
1 files changed, 89 insertions, 43 deletions
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 1df05462c9..6b4f3a256d 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -30,11 +30,12 @@ -export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]). -export([cmac/3, cmac/4]). -export([exor/2, strong_rand_bytes/1, mod_pow/3]). --export([rand_seed/0]). --export([rand_seed_s/0]). +-export([rand_seed/0, rand_seed_alg/1]). +-export([rand_seed_s/0, rand_seed_alg_s/1]). -export([rand_plugin_next/1]). -export([rand_plugin_uniform/1]). -export([rand_plugin_uniform/2]). +-export([rand_cache_plugin_next/1]). -export([rand_uniform/2]). -export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]). -export([next_iv/2, next_iv/3]). @@ -301,9 +302,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: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,12 +328,36 @@ rand_seed() -> rand:seed(rand_seed_s()). rand_seed_s() -> + rand_seed_alg_s(?MODULE). + +rand_seed_alg(Alg) -> + rand:seed(rand_seed_alg_s(Alg)). + +-define(CRYPTO_CACHE_BITS, 56). +rand_seed_alg_s(?MODULE) -> {#{ type => ?MODULE, bits => 64, next => fun ?MODULE:rand_plugin_next/1, uniform => fun ?MODULE:rand_plugin_uniform/1, uniform_n => fun ?MODULE:rand_plugin_uniform/2}, - no_seed}. + no_seed}; +rand_seed_alg_s(crypto_cache) -> + CacheBits = ?CRYPTO_CACHE_BITS, + EnvCacheSize = + application:get_env( + crypto, rand_cache_size, CacheBits * 16), % Cache 16 * 8 words + Bytes = (CacheBits + 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 => CacheBits, + next => fun ?MODULE:rand_cache_plugin_next/1}, + {CacheBits, CacheSize, <<>>}}. rand_plugin_next(Seed) -> {bytes_to_integer(strong_rand_range(1 bsl 64)), Seed}. @@ -335,6 +368,12 @@ rand_plugin_uniform(State) -> rand_plugin_uniform(Max, State) -> {bytes_to_integer(strong_rand_range(Max)) + 1, State}. +rand_cache_plugin_next({CacheBits, CacheSize, <<>>}) -> + rand_cache_plugin_next( + {CacheBits, CacheSize, strong_rand_bytes(CacheSize)}); +rand_cache_plugin_next({CacheBits, CacheSize, Cache}) -> + <<I:CacheBits, NewCache/binary>> = Cache, + {I, {CacheBits, CacheSize, NewCache}}. strong_rand_range(Range) when is_integer(Range), Range > 0 -> BinRange = int_to_bin(Range), @@ -382,7 +421,7 @@ rand_uniform_nif(_From,_To) -> ?nif_stub. -spec rand_seed(binary()) -> ok. -rand_seed(Seed) -> +rand_seed(Seed) when is_binary(Seed) -> rand_seed_nif(Seed). rand_seed_nif(_Seed) -> ?nif_stub. @@ -420,46 +459,55 @@ sign(Algorithm, Type, Data, Key, Options) -> Signature -> Signature end. --spec public_encrypt(rsa, binary(), [binary()], rsa_padding()) -> - binary(). --spec public_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) -> - binary(). --spec private_encrypt(rsa, binary(), [integer() | binary()], rsa_padding()) -> - binary(). --spec private_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) -> - binary(). - -public_encrypt(rsa, BinMesg, Key, Padding) -> - case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of - error -> - erlang:error(encrypt_failed, [rsa, BinMesg,Key, Padding]); - Sign -> Sign - end. -%% Binary, Key = [E,N,D] -private_decrypt(rsa, BinMesg, Key, Padding) -> - case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of - error -> - erlang:error(decrypt_failed, [rsa, BinMesg,Key, Padding]); - Sign -> Sign - end. +-type pk_algs() :: rsa | ecdsa | dss . +-type pk_opt() :: list() | rsa_padding() . +-spec public_encrypt(pk_algs(), binary(), [binary()], pk_opt()) -> binary(). +-spec public_decrypt(pk_algs(), binary(), [integer() | binary()], pk_opt()) -> binary(). +-spec private_encrypt(pk_algs(), binary(), [integer() | binary()], pk_opt()) -> binary(). +-spec private_decrypt(pk_algs(), binary(), [integer() | binary()], pk_opt()) -> binary(). -%% Binary, Key = [E,N,D] -private_encrypt(rsa, BinMesg, Key, Padding) -> - case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of - error -> - erlang:error(encrypt_failed, [rsa, BinMesg,Key, Padding]); - Sign -> Sign - end. +public_encrypt(Algorithm, In, Key, Options) when is_list(Options) -> + case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, true) of + error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]); + notsup -> erlang:error(notsup); + Out -> Out + end; +%% Backwards compatible +public_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> + public_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). + +private_decrypt(Algorithm, In, Key, Options) when is_list(Options) -> + case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, false) of + error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]); + notsup -> erlang:error(notsup); + Out -> Out + end; +%% Backwards compatible +private_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> + private_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). + +private_encrypt(Algorithm, In, Key, Options) when is_list(Options) -> + case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, true) of + error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]); + notsup -> erlang:error(notsup); + Out -> Out + end; +%% Backwards compatible +private_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> + private_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). + +public_decrypt(Algorithm, In, Key, Options) when is_list(Options) -> + case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, false) of + error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]); + notsup -> erlang:error(notsup); + Out -> Out + end; +%% Backwards compatible +public_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> + public_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). -%% Binary, Key = [E,N] -public_decrypt(rsa, BinMesg, Key, Padding) -> - case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of - error -> - erlang:error(decrypt_failed, [rsa, BinMesg,Key, Padding]); - Sign -> Sign - end. %% %% XOR - xor to iolists and return a binary @@ -970,9 +1018,7 @@ format_pkey(_, Key) -> %% -type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'. -rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. - -rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. +pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub. %% large integer in a binary with 32bit length %% MP representaion (SSH2) |