aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto/src/crypto.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto/src/crypto.erl')
-rw-r--r--lib/crypto/src/crypto.erl1204
1 files changed, 490 insertions, 714 deletions
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 60e0affda0..641e526537 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -22,12 +22,19 @@
-module(crypto).
--export([start/0, stop/0, info_lib/0, supports/0, version/0, bytes_to_integer/1]).
+-export([start/0, stop/0, info_lib/0, info_fips/0, supports/0, enable_fips_mode/1,
+ version/0, bytes_to_integer/1]).
-export([hash/2, hash_init/1, hash_update/2, hash_final/1]).
--export([sign/4, verify/5]).
+-export([sign/4, sign/5, verify/5, verify/6]).
-export([generate_key/2, generate_key/3, compute_key/4]).
-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_plugin_next/1]).
+-export([rand_plugin_uniform/1]).
+-export([rand_plugin_uniform/2]).
-export([rand_uniform/2]).
-export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]).
-export([next_iv/2, next_iv/3]).
@@ -35,149 +42,36 @@
-export([public_encrypt/4, private_decrypt/4]).
-export([private_encrypt/4, public_decrypt/4]).
-export([dh_generate_parameters/2, dh_check/1]). %% Testing see
+-export([privkey_to_pubkey/2]).
-export([ec_curve/1, ec_curves/0]).
-export([rand_seed/1]).
+%% Engine
+-export([
+ engine_get_all_methods/0,
+ engine_load/3,
+ engine_load/4,
+ engine_unload/1,
+ engine_list/0
+ ]).
-%% DEPRECATED
--export([rand_bytes/1]).
--deprecated({rand_bytes, 1, next_major_release}).
-
-%% Replaced by hash_*
--export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
--export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
--export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
--deprecated({md4, 1, next_major_release}).
--deprecated({md5, 1, next_major_release}).
--deprecated({sha, 1, next_major_release}).
--deprecated({md4_init, 0, next_major_release}).
--deprecated({md5_init, 0, next_major_release}).
--deprecated({sha_init, 0, next_major_release}).
--deprecated({md4_update, 2, next_major_release}).
--deprecated({md5_update, 2, next_major_release}).
--deprecated({sha_update, 2, next_major_release}).
--deprecated({md4_final, 1, next_major_release}).
--deprecated({md5_final, 1, next_major_release}).
--deprecated({sha_final, 1, next_major_release}).
-
-%% Replaced by hmac_*
--export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]).
--deprecated({md5_mac, 2, next_major_release}).
--deprecated({md5_mac_96, 2, next_major_release}).
--deprecated({sha_mac, 2, next_major_release}).
--deprecated({sha_mac, 3, next_major_release}).
--deprecated({sha_mac_96, 2, next_major_release}).
-
-%% Replaced by sign/verify
--export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]).
--export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]).
--deprecated({dss_verify, 3, next_major_release}).
--deprecated({dss_verify, 4, next_major_release}).
--deprecated({rsa_verify, 3, next_major_release}).
--deprecated({rsa_verify, 4, next_major_release}).
--deprecated({dss_sign, 2, next_major_release}).
--deprecated({dss_sign, 3, next_major_release}).
--deprecated({rsa_sign, 2, next_major_release}).
--deprecated({rsa_sign, 3, next_major_release}).
-
-%% Replaced by generate_key
--export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]).
--deprecated({dh_generate_key, 1, next_major_release}).
--deprecated({dh_generate_key, 2, next_major_release}).
--deprecated({dh_compute_key, 3, next_major_release}).
-
-%% Replaced by mod_exp_prim and no longer needed
--export([mod_exp/3, mpint/1, erlint/1, strong_rand_mpint/3]).
--deprecated({mod_exp, 3, next_major_release}).
--deprecated({mpint, 1, next_major_release}).
--deprecated({erlint, 1, next_major_release}).
--deprecated({strong_rand_mpint, 3, next_major_release}).
-
-%% Replaced by block_*
--export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
--export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]).
--export([des_ecb_encrypt/2, des_ecb_decrypt/2]).
--export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]).
--export([des_cfb_encrypt/3, des_cfb_decrypt/3, des_cfb_ivec/2]).
--export([des3_cfb_encrypt/5, des3_cfb_decrypt/5]).
--deprecated({des_cbc_encrypt, 3, next_major_release}).
--deprecated({des_cbc_decrypt, 3, next_major_release}).
--deprecated({des_cbc_ivec, 1, next_major_release}).
--deprecated({des3_cbc_encrypt, 5, next_major_release}).
--deprecated({des3_cbc_decrypt, 5, next_major_release}).
--deprecated({des_ecb_encrypt, 2, next_major_release}).
--deprecated({des_ecb_decrypt, 2, next_major_release}).
--deprecated({des_ede3_cbc_encrypt, 5, next_major_release}).
--deprecated({des_ede3_cbc_decrypt, 5, next_major_release}).
--deprecated({des_cfb_encrypt, 3, next_major_release}).
--deprecated({des_cfb_decrypt, 3, next_major_release}).
--deprecated({des_cfb_ivec, 2, next_major_release}).
--deprecated({des3_cfb_encrypt, 5, next_major_release}).
--deprecated({des3_cfb_decrypt, 5, next_major_release}).
--export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]).
--export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]).
--export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]).
--export([blowfish_ofb64_encrypt/3]).
--deprecated({blowfish_ecb_encrypt, 2, next_major_release}).
--deprecated({blowfish_ecb_decrypt, 2, next_major_release}).
--deprecated({blowfish_cbc_encrypt, 3, next_major_release}).
--deprecated({blowfish_cbc_decrypt, 3, next_major_release}).
--deprecated({blowfish_cfb64_encrypt, 3, next_major_release}).
--deprecated({blowfish_cfb64_decrypt, 3, next_major_release}).
--deprecated({blowfish_ofb64_encrypt, 3, next_major_release}).
--export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]).
--export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]).
--export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]).
--export([aes_cbc_ivec/1]).
--deprecated({aes_cfb_128_encrypt, 3, next_major_release}).
--deprecated({aes_cfb_128_decrypt, 3, next_major_release}).
--deprecated({aes_cbc_128_encrypt, 3, next_major_release}).
--deprecated({aes_cbc_128_decrypt, 3, next_major_release}).
--deprecated({aes_cbc_256_encrypt, 3, next_major_release}).
--deprecated({aes_cbc_256_decrypt, 3, next_major_release}).
--deprecated({aes_cbc_ivec, 1, next_major_release}).
--export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3]).
--export([rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
--deprecated({rc2_cbc_encrypt, 3, next_major_release}).
--deprecated({rc2_cbc_decrypt, 3, next_major_release}).
-%% allready replaced by above!
--deprecated({rc2_40_cbc_encrypt, 3, next_major_release}).
--deprecated({rc2_40_cbc_decrypt, 3, next_major_release}).
-
-%% Replaced by stream_*
--export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]).
--export([rc4_set_key/1, rc4_encrypt_with_state/2]).
--deprecated({aes_ctr_stream_init, 2, next_major_release}).
--deprecated({aes_ctr_stream_encrypt, 2, next_major_release}).
--deprecated({aes_ctr_stream_decrypt, 2, next_major_release}).
--deprecated({rc4_set_key, 1, next_major_release}).
--deprecated({rc4_encrypt_with_state, 2, next_major_release}).
-
-%% Not needed special case of stream_*
--export([aes_ctr_encrypt/3, aes_ctr_decrypt/3, rc4_encrypt/2]).
--deprecated({aes_ctr_encrypt, 3, next_major_release}).
--deprecated({aes_ctr_decrypt, 3, next_major_release}).
--deprecated({rc4_encrypt, 2, next_major_release}).
-
-%% Replace by public/private_encrypt/decrypt
--export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
--export([rsa_private_encrypt/3, rsa_public_decrypt/3]).
--deprecated({rsa_public_encrypt, 3, next_major_release}).
--deprecated({rsa_private_decrypt, 3, next_major_release}).
--deprecated({rsa_public_decrypt, 3, next_major_release}).
--deprecated({rsa_private_encrypt, 3, next_major_release}).
-
-%% Replaced by crypto:module_info()
--export([info/0]).
--deprecated({info, 0, next_major_release}).
+-export_type([engine_ref/0,
+ key_id/0,
+ password/0
+ ]).
+
+
+%% Private. For tests.
+-export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2, get_test_engine/0]).
+
+-deprecated({rand_uniform, 2, next_major_release}).
%% This should correspond to the similar macro in crypto.c
-define(MAX_BYTES_TO_NIF, 20000). %% Current value is: erlang:system_info(context_reductions) * 10
--type mpint() :: binary().
--type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type dss_digest_type() :: 'none' | 'sha'.
+%% Used by strong_rand_float/0
+-define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53)
+
%%-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'.
--type data_or_digest() :: binary() | {digest, binary()}.
-type crypto_integer() :: binary() | integer().
%%-type ec_named_curve() :: atom().
%%-type ec_point() :: crypto_integer().
@@ -188,8 +82,9 @@
%%-type ec_curve() :: ec_named_curve() | ec_curve_spec().
%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}.
+-compile(no_native).
-on_load(on_load/0).
--define(CRYPTO_NIF_VSN,301).
+-define(CRYPTO_NIF_VSN,302).
-define(nif_stub,nif_stub_error(?LINE)).
nif_stub_error(Line) ->
@@ -210,15 +105,24 @@ stop() ->
application:stop(crypto).
supports()->
- {Hashs, PubKeys, Ciphers} = algorithms(),
+ {Hashs, PubKeys, Ciphers, Macs} = algorithms(),
[{hashs, Hashs},
{ciphers, Ciphers},
- {public_keys, PubKeys}
+ {public_keys, PubKeys},
+ {macs, Macs}
].
info_lib() -> ?nif_stub.
+-spec info_fips() -> not_supported | not_enabled | enabled.
+
+info_fips() -> ?nif_stub.
+
+-spec enable_fips_mode(boolean()) -> boolean().
+
+enable_fips_mode(_) -> ?nif_stub.
+
-spec hash(_, iodata()) -> binary().
hash(Hash, Data0) ->
@@ -271,6 +175,14 @@ hmac_final(Context) ->
hmac_final_n(Context, HashLen) ->
notsup_to_error(hmac_final_nif(Context, HashLen)).
+-spec cmac(_, iodata(), iodata()) -> binary().
+-spec cmac(_, iodata(), iodata(), integer()) -> binary().
+
+cmac(Type, Key, Data) ->
+ notsup_to_error(cmac_nif(Type, Key, Data)).
+cmac(Type, Key, Data, MacSize) ->
+ erlang:binary_part(cmac(Type, Key, Data), 0, MacSize).
+
%% Ecrypt/decrypt %%%
-spec block_encrypt(des_cbc | des_cfb |
@@ -306,7 +218,7 @@ block_encrypt(des3_cfb, Key0, Ivec, Data) ->
Key = check_des3_key(Key0),
block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, true);
block_encrypt(aes_ige256, Key, Ivec, Data) ->
- aes_ige_crypt_nif(Key, Ivec, Data, true);
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, true));
block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) ->
aes_gcm_encrypt(Key, Ivec, AAD, Data);
block_encrypt(aes_gcm, Key, Ivec, {AAD, Data, TagLength}) ->
@@ -401,15 +313,14 @@ stream_decrypt(State, Data0) ->
stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
%%
-%% RAND - pseudo random numbers using RN_ functions in crypto lib
+%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
%%
--spec rand_bytes(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_uniform(crypto_integer(), crypto_integer()) ->
crypto_integer().
-rand_bytes(_Bytes) -> ?nif_stub.
-
strong_rand_bytes(Bytes) ->
case strong_rand_bytes_nif(Bytes) of
false -> erlang:error(low_entropy);
@@ -418,6 +329,43 @@ strong_rand_bytes(Bytes) ->
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+rand_seed() ->
+ rand:seed(rand_seed_s()).
+
+rand_seed_s() ->
+ {#{ 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}.
+
+rand_plugin_next(Seed) ->
+ {bytes_to_integer(strong_rand_range(1 bsl 64)), Seed}.
+
+rand_plugin_uniform(State) ->
+ {strong_rand_float(), State}.
+
+rand_plugin_uniform(Max, State) ->
+ {bytes_to_integer(strong_rand_range(Max)) + 1, State}.
+
+
+strong_rand_range(Range) when is_integer(Range), Range > 0 ->
+ BinRange = int_to_bin(Range),
+ strong_rand_range(BinRange);
+strong_rand_range(BinRange) when is_binary(BinRange) ->
+ case strong_rand_range_nif(BinRange) of
+ false ->
+ erlang:error(low_entropy);
+ <<BinResult/binary>> ->
+ BinResult
+ end.
+strong_rand_range_nif(_BinRange) -> ?nif_stub.
+
+strong_rand_float() ->
+ WholeRange = strong_rand_range(1 bsl 53),
+ ?HALF_DBL_EPSILON * bytes_to_integer(WholeRange).
+
rand_uniform(From,To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
<<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
@@ -446,6 +394,7 @@ rand_uniform_pos(_,_) ->
rand_uniform_nif(_From,_To) -> ?nif_stub.
+
-spec rand_seed(binary()) -> ok.
rand_seed(Seed) ->
rand_seed_nif(Seed).
@@ -458,79 +407,94 @@ mod_pow(Base, Exponent, Prime) ->
<<0>> -> error;
R -> R
end.
-verify(dss, none, Data, Signature, Key) when is_binary(Data) ->
- verify(dss, sha, {digest, Data}, Signature, Key);
-verify(Alg, Type, Data, Signature, Key) when is_binary(Data) ->
- verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key);
-verify(dss, Type, {digest, Digest}, Signature, Key) ->
- dss_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key));
-verify(rsa, Type, {digest, Digest}, Signature, Key) ->
- notsup_to_error(
- rsa_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key)));
-verify(ecdsa, Type, {digest, Digest}, Signature, [Key, Curve]) ->
- notsup_to_error(
- ecdsa_verify_nif(Type, Digest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key))).
-sign(dss, none, Data, Key) when is_binary(Data) ->
- sign(dss, sha, {digest, Data}, Key);
-sign(Alg, Type, Data, Key) when is_binary(Data) ->
- sign(Alg, Type, {digest, hash(Type, Data)}, Key);
-sign(rsa, Type, {digest, Digest}, Key) ->
- case rsa_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,Digest,Key]);
- Sign -> Sign
- end;
-sign(dss, Type, {digest, Digest}, Key) ->
- case dss_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Digest, Key]);
- Sign -> Sign
- end;
-sign(ecdsa, Type, {digest, Digest}, [Key, Curve]) ->
- case ecdsa_sign_nif(Type, Digest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,Digest,Key]);
- Sign -> Sign
- 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, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
+verify(Algorithm, Type, Data, Signature, Key) ->
+ verify(Algorithm, Type, Data, Signature, Key, []).
-%% 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, [BinMesg,Key, Padding]);
- Sign -> Sign
+%% Backwards compatible
+verify(Algorithm = dss, none, Digest, Signature, Key, Options) ->
+ verify(Algorithm, sha, {digest, Digest}, Signature, Key, Options);
+verify(Algorithm, Type, Data, Signature, Key, Options) ->
+ case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
+ notsup -> erlang:error(notsup);
+ Boolean -> Boolean
end.
-%% 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, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
+sign(Algorithm, Type, Data, Key) ->
+ sign(Algorithm, Type, Data, Key, []).
-%% 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, [BinMesg,Key, Padding]);
- Sign -> Sign
+%% Backwards compatible
+sign(Algorithm = dss, none, Digest, Key, Options) ->
+ sign(Algorithm, sha, {digest, Digest}, Key, Options);
+sign(Algorithm, Type, Data, Key, Options) ->
+ case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of
+ error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]);
+ notsup -> erlang:error(notsup);
+ Signature -> Signature
end.
+
+
+-type key_id() :: string() | binary() .
+-type password() :: string() | binary() .
+
+-type engine_key_ref() :: #{engine := engine_ref(),
+ key_id := key_id(),
+ password => password(),
+ term() => term()
+ }.
+
+-type pk_algs() :: rsa | ecdsa | dss .
+-type pk_key() :: engine_key_ref() | [integer() | binary()] .
+-type pk_opt() :: list() | rsa_padding() .
+
+-spec public_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
+-spec public_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
+-spec private_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
+-spec private_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
+
+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}]).
+
+
%%
%% XOR - xor to iolists and return a binary
%% NB doesn't check that they are the same size, just concatenates
@@ -573,6 +537,15 @@ generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg)
end,
user_srp_gen_key(Private, Generator, Prime);
+generate_key(rsa, {ModulusSize, PublicExponent}, undefined) ->
+ case rsa_generate_key_nif(ModulusSize, ensure_int_as_bin(PublicExponent)) of
+ error ->
+ erlang:error(computation_failed,
+ [rsa,{ModulusSize,PublicExponent}]);
+ Private ->
+ {lists:sublist(Private, 2), Private}
+ end;
+
generate_key(ecdh, Curve, PrivKey) ->
ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey)).
@@ -581,7 +554,7 @@ compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
ensure_int_as_bin(MyPrivateKey),
map_ensure_int_as_bin(DHParameters)) of
error -> erlang:error(computation_failed,
- [OthersPublicKey,MyPrivateKey,DHParameters]);
+ [dh,OthersPublicKey,MyPrivateKey,DHParameters]);
Ret -> Ret
end;
@@ -620,10 +593,145 @@ compute_key(ecdh, Others, My, Curve) ->
nif_curve_params(Curve),
ensure_int_as_bin(My)).
+%%======================================================================
+%% Engine functions
+%%======================================================================
+%%----------------------------------------------------------------------
+%% Function: engine_get_all_methods/0
+%%----------------------------------------------------------------------
+-type engine_method_type() :: engine_method_rsa | engine_method_dsa | engine_method_dh |
+ engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
+ engine_method_ciphers | engine_method_digests | engine_method_store |
+ engine_method_pkey_meths | engine_method_pkey_asn1_meths |
+ engine_method_ec.
+
+-type engine_ref() :: term().
+
+-spec engine_get_all_methods() ->
+ [engine_method_type()].
+engine_get_all_methods() ->
+ notsup_to_error(engine_get_all_methods_nif()).
+
+%%----------------------------------------------------------------------
+%% Function: engine_load/3
+%%----------------------------------------------------------------------
+-spec engine_load(EngineId::unicode:chardata(),
+ PreCmds::[{unicode:chardata(), unicode:chardata()}],
+ PostCmds::[{unicode:chardata(), unicode:chardata()}]) ->
+ {ok, Engine::engine_ref()} | {error, Reason::term()}.
+engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), is_list(PostCmds) ->
+ engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: engine_load/4
+%%----------------------------------------------------------------------
+-spec engine_load(EngineId::unicode:chardata(),
+ PreCmds::[{unicode:chardata(), unicode:chardata()}],
+ PostCmds::[{unicode:chardata(), unicode:chardata()}],
+ EngineMethods::[engine_method_type()]) ->
+ {ok, Engine::term()} | {error, Reason::term()}.
+engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
+ is_list(PostCmds) ->
+ try
+ ok = notsup_to_error(engine_load_dynamic_nif()),
+ case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of
+ {ok, Engine} ->
+ ok = engine_load_1(Engine, PreCmds, PostCmds, EngineMethods),
+ {ok, Engine};
+ {error, Error1} ->
+ {error, Error1}
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds))),
+ ok = engine_nif_wrapper(engine_add_nif(Engine)),
+ ok = engine_nif_wrapper(engine_init_nif(Engine)),
+ engine_load_2(Engine, PostCmds, EngineMethods),
+ ok
+ catch
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
+ end.
+
+engine_load_2(Engine, PostCmds, EngineMethods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PostCmds))),
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- EngineMethods],
+ ok
+ catch
+ throw:Error ->
+ %% The engine registration failed, release the functional reference
+ ok = engine_finish_nif(Engine),
+ throw(Error)
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_unload/1
+%%----------------------------------------------------------------------
+-spec engine_unload(Engine::term()) ->
+ ok | {error, Reason::term()}.
+engine_unload(Engine) ->
+ engine_unload(Engine, engine_get_all_methods()).
+
+-spec engine_unload(Engine::term(), EngineMethods::[engine_method_type()]) ->
+ ok | {error, Reason::term()}.
+engine_unload(Engine, EngineMethods) ->
+ try
+ [ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- EngineMethods],
+ ok = engine_nif_wrapper(engine_remove_nif(Engine)),
+ %% Release the functional reference from engine_init_nif
+ ok = engine_nif_wrapper(engine_finish_nif(Engine)),
+ %% Release the structural reference from engine_by_id_nif
+ ok = engine_nif_wrapper(engine_free_nif(Engine))
+ catch
+ throw:Error ->
+ Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_list/0
+%%----------------------------------------------------------------------
+-spec engine_list() ->
+ [EngineId::binary()].
+engine_list() ->
+ case notsup_to_error(engine_get_first_nif()) of
+ {ok, <<>>} ->
+ [];
+ {ok, Engine} ->
+ case notsup_to_error(engine_get_id_nif(Engine)) of
+ {ok, <<>>} ->
+ engine_list(Engine, []);
+ {ok, EngineId} ->
+ engine_list(Engine, [EngineId])
+ end
+ end.
+
+engine_list(Engine0, IdList) ->
+ case notsup_to_error(engine_get_next_nif(Engine0)) of
+ {ok, <<>>} ->
+ lists:reverse(IdList);
+ {ok, Engine1} ->
+ case notsup_to_error(engine_get_id_nif(Engine1)) of
+ {ok, <<>>} ->
+ engine_list(Engine1, IdList);
+ {ok, EngineId} ->
+ engine_list(Engine1, [EngineId |IdList])
+ end
+ end.
+
+
%%--------------------------------------------------------------------
%%% On load
%%--------------------------------------------------------------------
-
on_load() ->
LibBaseName = "crypto",
PrivDir = code:priv_dir(crypto),
@@ -649,7 +757,8 @@ on_load() ->
end,
Lib = filename:join([PrivDir, "lib", LibName]),
LibBin = path2bin(Lib),
- Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,LibBin}) of
+ FipsMode = application:get_env(crypto, fips_mode, false) == true,
+ Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,LibBin,FipsMode}) of
ok -> ok;
{error, {load_failed, _}}=Error1 ->
ArchLibDir =
@@ -662,7 +771,7 @@ on_load() ->
_ ->
ArchLib = filename:join([ArchLibDir, LibName]),
ArchBin = path2bin(ArchLib),
- erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchBin})
+ erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchBin,FipsMode})
end;
Error1 -> Error1
end,
@@ -682,12 +791,12 @@ path2bin(Path) when is_list(Path) ->
end.
%%--------------------------------------------------------------------
-%%% Internal functions (some internal API functions are part of the deprecated API)
+%%% Internal functions
%%--------------------------------------------------------------------
max_bytes() ->
?MAX_BYTES_TO_NIF.
-notsup_to_error(notsup) ->
+notsup_to_error(notsup) ->
erlang:error(notsup);
notsup_to_error(Other) ->
Other.
@@ -712,59 +821,6 @@ hash_init_nif(_Hash) -> ?nif_stub.
hash_update_nif(_State, _Data) -> ?nif_stub.
hash_final_nif(_State) -> ?nif_stub.
-
-%%
-%% MD5
-%%
-
--spec md5(iodata()) -> binary().
--spec md5_init() -> binary().
--spec md5_update(binary(), iodata()) -> binary().
--spec md5_final(binary()) -> binary().
-
-md5(Data) ->
- hash(md5, Data).
-md5_init() ->
- hash_init(md5).
-md5_update(Context, Data) ->
- hash_update(Context, Data).
-md5_final(Context) ->
- hash_final(Context).
-
-%%
-%% MD4
-%%
--spec md4(iodata()) -> binary().
--spec md4_init() -> binary().
--spec md4_update(binary(), iodata()) -> binary().
--spec md4_final(binary()) -> binary().
-
-md4(Data) ->
- hash(md4, Data).
-md4_init() ->
- hash_init(md4).
-md4_update(Context, Data) ->
- hash_update(Context, Data).
-md4_final(Context) ->
- hash_final(Context).
-
-%%
-%% SHA
-%%
--spec sha(iodata()) -> binary().
--spec sha_init() -> binary().
--spec sha_update(binary(), iodata()) -> binary().
--spec sha_final(binary()) -> binary().
-
-sha(Data) ->
- hash(sha, Data).
-sha_init() ->
- hash_init(sha).
-sha_update(Context, Data) ->
- hash_update(Context, Data).
-sha_final(Context) ->
- hash_final(Context).
-
%% HMAC --------------------------------------------------------------------
hmac(Type, Key, Data, MacSize, Size, MaxBytes) when Size =< MaxBytes ->
@@ -795,35 +851,15 @@ hmac_update_nif(_Context, _Data) -> ?nif_stub.
hmac_final_nif(_Context) -> ?nif_stub.
hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
-%%
-%% MD5_MAC
-%%
--spec md5_mac(iodata(), iodata()) -> binary().
--spec md5_mac_96(iodata(), iodata()) -> binary().
-
-md5_mac(Key, Data) -> hmac(md5, Key, Data).
-
-md5_mac_96(Key, Data) -> hmac(md5, Key, Data, 12).
+%% CMAC
-%%
-%% SHA_MAC
-%%
--spec sha_mac(iodata(), iodata()) -> binary().
--spec sha_mac_96(iodata(), iodata()) -> binary().
-
-sha_mac(Key, Data) -> hmac(sha, Key, Data).
-
-sha_mac(Key, Data, Size) -> hmac(sha, Key, Data, Size).
-
-sha_mac_96(Key, Data) -> hmac(sha, Key, Data, 12).
+cmac_nif(_Type, _Key, _Data) -> ?nif_stub.
%% CIPHERS --------------------------------------------------------------------
block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
block_crypt_nif(_Type, _Key, _Text, _IsEncrypt) -> ?nif_stub.
-aes_cfb_128_crypt_nif(_Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
-
check_des3_key(Key) ->
case lists:map(fun erlang:iolist_to_binary/1, Key) of
ValidKey = [B1, B2, B3] when byte_size(B1) =:= 8,
@@ -835,96 +871,6 @@ check_des3_key(Key) ->
end.
%%
-%% DES - in electronic codebook mode (ECB)
-%%
--spec des_ecb_encrypt(iodata(), iodata()) -> binary().
--spec des_ecb_decrypt(iodata(), iodata()) -> binary().
-
-des_ecb_encrypt(Key, Data) ->
- block_encrypt(des_ecb, Key, Data).
-des_ecb_decrypt(Key, Data) ->
- block_decrypt(des_ecb, Key, Data).
-
-%%
-%% DES3 - in cipher block chaining mode (CBC)
-%%
--spec des3_cbc_encrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
- binary().
--spec des3_cbc_decrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
- binary().
-
-des3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- block_encrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
-des_ede3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- block_encrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
-
-des3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- block_decrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
-des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- block_decrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
-
-%%
-%% DES3 - in 8-bits cipher feedback mode (CFB)
-%%
--spec des3_cfb_encrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
- binary().
--spec des3_cfb_decrypt(iodata(), iodata(), iodata(), binary(), iodata()) ->
- binary().
-
-des3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
- block_encrypt(des3_cfb, [Key1, Key2, Key3], IVec, Data).
-
-des3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
- block_decrypt(des3_cfb, [Key1, Key2, Key3], IVec, Data).
-
-%%
-%% Blowfish
-%%
--spec blowfish_ecb_encrypt(iodata(), iodata()) -> binary().
--spec blowfish_ecb_decrypt(iodata(), iodata()) -> binary().
--spec blowfish_cbc_encrypt(iodata(), binary(), iodata()) -> binary().
--spec blowfish_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
--spec blowfish_cfb64_encrypt(iodata(), binary(), iodata()) -> binary().
--spec blowfish_cfb64_decrypt(iodata(), binary(), iodata()) -> binary().
--spec blowfish_ofb64_encrypt(iodata(), binary(), iodata()) -> binary().
-
-blowfish_ecb_encrypt(Key, Data) ->
- block_encrypt(blowfish_ecb, Key, Data).
-
-blowfish_ecb_decrypt(Key, Data) ->
- block_decrypt(blowfish_ecb, Key, Data).
-
-blowfish_cbc_encrypt(Key, IVec, Data) ->
- block_encrypt(blowfish_cbc, Key, IVec, Data).
-
-blowfish_cbc_decrypt(Key, IVec, Data) ->
- block_decrypt(blowfish_cbc, Key, IVec, Data).
-
-blowfish_cfb64_encrypt(Key, IVec, Data) ->
- block_encrypt(blowfish_cfb64, Key, IVec, Data).
-
-blowfish_cfb64_decrypt(Key, IVec, Data) ->
- block_decrypt(blowfish_cfb64, Key, IVec, Data).
-
-blowfish_ofb64_encrypt(Key, IVec, Data) ->
- block_encrypt(blowfish_ofb64, Key, IVec, Data).
-
-
-%%
-%% AES in cipher feedback mode (CFB) - 128 bit shift
-%%
--spec aes_cfb_128_encrypt(iodata(), binary(), iodata()) -> binary().
--spec aes_cfb_128_decrypt(iodata(), binary(), iodata()) -> binary().
-
-aes_cfb_128_encrypt(Key, IVec, Data) ->
- %% block_encrypt(aes_cfb128, Key, IVec, Data).
- aes_cfb_128_crypt_nif(Key, IVec, Data, true).
-
-
-aes_cfb_128_decrypt(Key, IVec, Data) ->
- block_decrypt(aes_cfb128, Key, IVec, Data).
-
-%%
%% AES - in Galois/Counter Mode (GCM)
%%
%% The default tag length is EVP_GCM_TLS_TAG_LEN(16),
@@ -940,88 +886,6 @@ chacha20_poly1305_encrypt(_Key, _Ivec, _AAD, _In) -> ?nif_stub.
chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
%%
-%% DES - in cipher block chaining mode (CBC)
-%%
--spec des_cbc_encrypt(iodata(), binary(), iodata()) -> binary().
--spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
-
-des_cbc_encrypt(Key, IVec, Data) ->
- block_encrypt(des_cbc, Key, IVec, Data).
-
-des_cbc_decrypt(Key, IVec, Data) ->
- block_decrypt(des_cbc, Key, IVec, Data).
-
-%%
-%% dec_cbc_ivec(Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% des_cbc_[encrypt|decrypt].
-%%
--spec des_cbc_ivec(iodata()) -> binary().
-
-des_cbc_ivec(Data) ->
- next_iv(des_cbc, Data).
-
-%%
-%% DES - in 8-bits cipher feedback mode (CFB)
-%%
--spec des_cfb_encrypt(iodata(), binary(), iodata()) -> binary().
--spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
-
-des_cfb_encrypt(Key, IVec, Data) ->
- block_encrypt(des_cfb, Key, IVec, Data).
-
-des_cfb_decrypt(Key, IVec, Data) ->
- block_decrypt(des_cfb, Key, IVec, Data).
-
-%%
-%% dec_cfb_ivec(IVec, Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% des_cfb_[encrypt|decrypt].
-%%
-
--spec des_cfb_ivec(iodata(), iodata()) -> binary().
-
-des_cfb_ivec(IVec, Data) ->
- next_iv(des_cfb, Data, IVec).
-
-
-%%
-%% AES - with 128 or 256 bit key in cipher block chaining mode (CBC)
-%%
--spec aes_cbc_128_encrypt(iodata(), binary(), iodata()) ->
- binary().
--spec aes_cbc_128_decrypt(iodata(), binary(), iodata()) ->
- binary().
--spec aes_cbc_256_encrypt(iodata(), binary(), iodata()) ->
- binary().
--spec aes_cbc_256_decrypt(iodata(), binary(), iodata()) ->
- binary().
-
-aes_cbc_128_encrypt(Key, IVec, Data) ->
- block_encrypt(aes_cbc128, Key, IVec, Data).
-
-aes_cbc_128_decrypt(Key, IVec, Data) ->
- block_decrypt(aes_cbc128, Key, IVec, Data).
-
-aes_cbc_256_encrypt(Key, IVec, Data) ->
- block_encrypt(aes_cbc256, Key, IVec, Data).
-
-aes_cbc_256_decrypt(Key, IVec, Data) ->
- block_decrypt(aes_cbc256, Key, IVec, Data).
-
-%%
-%% aes_cbc_ivec(Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% aes_cbc_*_[encrypt|decrypt].
-%% IVec size: 16 bytes
-%%
-aes_cbc_ivec(Data) ->
- next_iv(aes_cbc, Data).
-
-%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
%%
@@ -1054,20 +918,9 @@ do_stream_decrypt({rc4, State0}, Data) ->
{State, Text} = rc4_encrypt_with_state(State0, Data),
{{rc4, State}, Text}.
-%%
-%% AES - in counter mode (CTR)
-%%
--spec aes_ctr_encrypt(iodata(), binary(), iodata()) ->
- binary().
--spec aes_ctr_decrypt(iodata(), binary(), iodata()) ->
- binary().
-
-aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
-aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
-
%%
-%% AES - in counter mode (CTR) with state maintained for multi-call streaming
+%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
-type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary().
@@ -1076,42 +929,25 @@ aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
{ ctr_state(), binary() }.
-spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
{ ctr_state(), binary() }.
-
+
aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub.
aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub.
aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
-
+
%%
%% RC4 - symmetric stream cipher
%%
--spec rc4_encrypt(iodata(), iodata()) -> binary().
-
-rc4_encrypt(_Key, _Data) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
-
-%% RC2 block cipher
-
-rc2_cbc_encrypt(Key, IVec, Data) ->
- block_encrypt(rc2_cbc, Key, IVec, Data).
-
-rc2_cbc_decrypt(Key, IVec, Data) ->
- block_decrypt(rc2_cbc, Key, IVec, Data).
-
-%%
-%% RC2 - 40 bits block cipher - Backwards compatibility not documented.
-%%
-rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- block_encrypt(rc2_cbc, Key, IVec, Data).
-
-rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- block_decrypt(rc2_cbc, Key, IVec, Data).
-
-
%% Secure remote password -------------------------------------------------------------------
user_srp_gen_key(Private, Generator, Prime) ->
+ %% Ensure the SRP algorithm is disabled in FIPS mode
+ case info_fips() of
+ enabled -> erlang:error(notsup);
+ _ -> ok
+ end,
case mod_pow(Generator, Private, Prime) of
error ->
error;
@@ -1151,7 +987,7 @@ srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Versi
srp_scrambler('3', _, HostPublic, _Prime) ->
%% The parameter u is a 32-bit unsigned integer which takes its value
%% from the first 32 bits of the SHA1 hash of B, MSB first.
- <<U:32/bits, _/binary>> = sha(HostPublic),
+ <<U:32/bits, _/binary>> = hash(sha, HostPublic),
U.
srp_pad_length(Width, Length) ->
@@ -1171,32 +1007,33 @@ srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_s
%% Digital signatures --------------------------------------------------------------------
-rsa_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
-dss_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
-ecdsa_sign_nif(_Type, _Digest, _Curve, _Key) -> ?nif_stub.
-dss_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
-rsa_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
-ecdsa_verify_nif(_Type, _Digest, _Signature, _Curve, _Key) -> ?nif_stub.
+pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
+pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
%% Public Keys --------------------------------------------------------------------
+%% RSA Rivest-Shamir-Adleman functions
+%%
+
+rsa_generate_key_nif(_Bits, _Exp) -> ?nif_stub.
+
%% DH Diffie-Hellman functions
-%%
+%%
%% Generate (and check) Parameters is not documented because they are implemented
%% for testing (and offline parameter generation) only.
-%% From the openssl doc:
+%% From the openssl doc:
%% DH_generate_parameters() may run for several hours before finding a suitable prime.
-%% Thus dh_generate_parameters may in this implementation block
+%% Thus dh_generate_parameters may in this implementation block
%% the emulator for several hours.
%%
-%% usage: dh_generate_parameters(1024, 2 or 5) ->
+%% usage: dh_generate_parameters(1024, 2 or 5) ->
%% [Prime=mpint(), SharedGenerator=mpint()]
dh_generate_parameters(PrimeLen, Generator) ->
case dh_generate_parameters_nif(PrimeLen, Generator) of
error -> erlang:error(generation_failed, [PrimeLen,Generator]);
Ret -> Ret
- end.
+ end.
dh_generate_parameters_nif(_PrimeLen, _Generator) -> ?nif_stub.
@@ -1206,26 +1043,10 @@ dh_check([_Prime,_Gen]) -> ?nif_stub.
%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
%% PrivKey = mpint()
--spec dh_generate_key([binary()]) -> {binary(),binary()}.
--spec dh_generate_key(binary()|undefined, [binary()]) ->
- {binary(),binary()}.
-
-dh_generate_key(DHParameters) ->
- dh_generate_key_nif(undefined, map_mpint_to_bin(DHParameters), 4, 0).
-dh_generate_key(PrivateKey, DHParameters) ->
- dh_generate_key_nif(mpint_to_bin(PrivateKey), map_mpint_to_bin(DHParameters), 4, 0).
-
dh_generate_key_nif(_PrivateKey, _DHParameters, _Mpint, _Length) -> ?nif_stub.
%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
%% MyPrivKey, OthersPublicKey = mpint()
--spec dh_compute_key(binary(), binary(), [binary()]) -> binary().
-
-dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) ->
- compute_key(dh, mpint_to_bin(OthersPublicKey), mpint_to_bin(MyPrivateKey),
- map_mpint_to_bin(DHParameters)).
-
-
dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub.
ec_key_generate(_Curve, _Key) -> ?nif_stub.
@@ -1238,6 +1059,24 @@ ec_curves() ->
ec_curve(X) ->
crypto_ec_curves:curve(X).
+
+privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
+ try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap))
+ of
+ [_|_]=L -> map_ensure_bin_as_int(L);
+ X -> X
+ catch
+ error:badarg when Alg==ecdsa ->
+ {error, notsup};
+ error:badarg ->
+ {error, not_found};
+ error:notsup ->
+ {error, notsup}
+ end.
+
+privkey_to_pubkey_nif(_Alg, _EngineMap) -> ?nif_stub.
+
+
%%
%% EC
%%
@@ -1305,131 +1144,36 @@ ensure_int_as_bin(Int) when is_integer(Int) ->
ensure_int_as_bin(Bin) ->
Bin.
-map_to_norm_bin([H|_]=List) when is_integer(H) ->
- lists:map(fun(E) -> int_to_bin(E) end, List);
-map_to_norm_bin(List) ->
- lists:map(fun(E) -> mpint_to_bin(E) end, List).
+map_ensure_bin_as_int(List) when is_list(List) ->
+ lists:map(fun ensure_bin_as_int/1, List).
+
+ensure_bin_as_int(Bin) when is_binary(Bin) ->
+ bin_to_int(Bin);
+ensure_bin_as_int(E) ->
+ E.
+
+format_pkey(_Alg, #{engine:=_, key_id:=T}=M) when is_binary(T) -> format_pwd(M);
+format_pkey(_Alg, #{engine:=_, key_id:=T}=M) when is_list(T) -> format_pwd(M#{key_id:=list_to_binary(T)});
+format_pkey(_Alg, #{engine:=_ }=M) -> error({bad_key_id, M});
+format_pkey(_Alg, #{}=M) -> error({bad_engine_map, M});
+%%%
+format_pkey(rsa, Key) ->
+ map_ensure_int_as_bin(Key);
+format_pkey(ecdsa, [Key, Curve]) ->
+ {nif_curve_params(Curve), ensure_int_as_bin(Key)};
+format_pkey(dss, Key) ->
+ map_ensure_int_as_bin(Key);
+format_pkey(_, Key) ->
+ Key.
+
+format_pwd(#{password := Pwd}=M) when is_list(Pwd) -> M#{password := list_to_binary(Pwd)};
+format_pwd(M) -> M.
%%--------------------------------------------------------------------
-%%% Deprecated
-%%--------------------------------------------------------------------
%%
-%% rsa_public_encrypt
-%% rsa_private_decrypt
-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
--spec rsa_public_encrypt(binary(), [binary()], rsa_padding()) ->
- binary().
--spec rsa_public_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
--spec rsa_private_encrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
--spec rsa_private_decrypt(binary(), [integer() | mpint()], rsa_padding()) ->
- binary().
-
-%% Binary, Key = [E,N]
-rsa_public_encrypt(BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-
-%% Binary, Key = [E,N,D]
-rsa_private_decrypt(BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub.
-
-
-%% Binary, Key = [E,N,D]
-rsa_private_encrypt(BinMesg, Key, Padding) ->
- case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of
- error ->
- erlang:error(encrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-%% Binary, Key = [E,N]
-rsa_public_decrypt(BinMesg, Key, Padding) ->
- case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of
- error ->
- erlang:error(decrypt_failed, [BinMesg,Key, Padding]);
- Sign -> Sign
- end.
-
-map_mpint_to_bin(List) ->
- lists:map(fun(E) -> mpint_to_bin(E) end, List ).
-
-%%
-%% DSS, RSA - sign
-%%
-%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
--spec dss_sign(data_or_digest(), [binary()]) -> binary().
--spec dss_sign(dss_digest_type(), data_or_digest(), [binary()]) -> binary().
--spec rsa_sign(data_or_digest(), [binary()]) -> binary().
--spec rsa_sign(rsa_digest_type(), data_or_digest(), [binary()]) -> binary().
-
-dss_sign(DataOrDigest,Key) ->
- dss_sign(sha,DataOrDigest,Key).
-dss_sign(Type, Data, Key) when is_binary(Data), Type=/=none ->
- sign(dss, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
-dss_sign(Type, Digest, Key) ->
- sign(dss, Type, Digest, map_mpint_to_bin(Key)).
-
-
-%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
-rsa_sign(DataOrDigest,Key) ->
- rsa_sign(sha, DataOrDigest, Key).
-
-rsa_sign(Type, Data, Key) when is_binary(Data) ->
- sign(rsa, Type, mpint_to_bin(Data), map_mpint_to_bin(Key));
-rsa_sign(Type, Digest, Key) ->
- sign(rsa, Type, Digest, map_mpint_to_bin(Key)).
-
-%%
-%% DSS, RSA - verify
-%%
--spec dss_verify(data_or_digest(), binary(), [binary()]) -> boolean().
--spec dss_verify(dss_digest_type(), data_or_digest(), binary(), [binary()]) -> boolean().
--spec rsa_verify(data_or_digest(), binary(), [binary()]) -> boolean().
--spec rsa_verify(rsa_digest_type(), data_or_digest(), binary(), [binary()]) ->
- boolean().
-
-%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
-dss_verify(Data,Signature,Key) ->
- dss_verify(sha, Data, Signature, Key).
-
-dss_verify(Type,Data,Signature,Key) when is_binary(Data), Type=/=none ->
- verify(dss,Type,mpint_to_bin(Data),mpint_to_bin(Signature),map_mpint_to_bin(Key));
-dss_verify(Type,Digest,Signature,Key) ->
- verify(dss,Type,Digest,mpint_to_bin(Signature),map_mpint_to_bin(Key)).
-
-% Key = [E,N] E=PublicExponent N=PublicModulus
-rsa_verify(Data,Signature,Key) ->
- rsa_verify(sha, Data,Signature,Key).
-rsa_verify(Type, Data, Signature, Key) when is_binary(Data) ->
- verify(rsa, Type, mpint_to_bin(Data), mpint_to_bin(Signature), map_mpint_to_bin(Key));
-rsa_verify(Type, Digest, Signature, Key) ->
- verify(rsa, Type, Digest, mpint_to_bin(Signature), map_mpint_to_bin(Key)).
-
--spec strong_rand_mpint(Bits::non_neg_integer(),
- Top::-1..1,
- Bottom::0..1) -> binary().
-
-strong_rand_mpint(Bits, Top, Bottom) ->
- case strong_rand_mpint_nif(Bits,Top,Bottom) of
- false -> erlang:error(low_entropy);
- Bin -> Bin
- end.
-strong_rand_mpint_nif(_Bits, _Top, _Bottom) -> ?nif_stub.
-
+pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
%% large integer in a binary with 32bit length
%% MP representaion (SSH2)
@@ -1443,7 +1187,7 @@ mpint_neg(X) ->
Bin = int_to_bin_neg(X, []),
Sz = byte_size(Bin),
<<?UINT32(Sz), Bin/binary>>.
-
+
mpint_pos(X) ->
Bin = int_to_bin_pos(X, []),
<<MSB,_/binary>> = Bin,
@@ -1460,75 +1204,107 @@ erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
<<Integer:Bits/integer>> = MPIntValue,
Integer.
-mpint_to_bin(<<Len:32, Bin:Len/binary>>) ->
- Bin.
-
%%
%% mod_exp - utility for rsa generation and SRP
%%
-mod_exp(Base, Exponent, Modulo)
- when is_integer(Base), is_integer(Exponent), is_integer(Modulo) ->
- bin_to_int(mod_exp_nif(int_to_bin(Base), int_to_bin(Exponent), int_to_bin(Modulo), 0));
+mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
-mod_exp(Base, Exponent, Modulo) ->
- mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4).
+%%%----------------------------------------------------------------
+%% 9470495 == V(0,9,8,zh).
+%% 268435615 == V(1,0,0,i).
+%% 268439663 == V(1,0,1,f).
-mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
+packed_openssl_version(MAJ, MIN, FIX, P0) ->
+ %% crypto.c
+ P1 = atom_to_list(P0),
+ P = lists:sum([C-$a||C<-P1]),
+ ((((((((MAJ bsl 8) bor MIN) bsl 8 ) bor FIX) bsl 8) bor (P+1)) bsl 4) bor 16#f).
--define(FUNC_LIST, [hash, hash_init, hash_update, hash_final,
- hmac, hmac_init, hmac_update, hmac_final, hmac_final_n,
- %% deprecated
- md4, md4_init, md4_update, md4_final,
- md5, md5_init, md5_update, md5_final,
- sha, sha_init, sha_update, sha_final,
- md5_mac, md5_mac_96,
- sha_mac, sha_mac_96,
- %%
- block_encrypt, block_decrypt,
- %% deprecated
- des_cbc_encrypt, des_cbc_decrypt,
- des_cfb_encrypt, des_cfb_decrypt,
- des_ecb_encrypt, des_ecb_decrypt,
- des3_cbc_encrypt, des3_cbc_decrypt,
- des3_cfb_encrypt, des3_cfb_decrypt,
- aes_cfb_128_encrypt, aes_cfb_128_decrypt,
- rc2_cbc_encrypt, rc2_cbc_decrypt,
- rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
- aes_cbc_128_encrypt, aes_cbc_128_decrypt,
- aes_cbc_256_encrypt, aes_cbc_256_decrypt,
- blowfish_cbc_encrypt, blowfish_cbc_decrypt,
- blowfish_cfb64_encrypt, blowfish_cfb64_decrypt,
- blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt,
- %%
- rand_bytes,
- strong_rand_bytes,
- rand_uniform,
- rand_seed,
- mod_pow,
- exor,
- %% deprecated
- mod_exp,strong_rand_mpint,erlint, mpint,
- %%
- sign, verify, generate_key, compute_key,
- %% deprecated
- dss_verify,dss_sign,
- rsa_verify,rsa_sign,
- rsa_public_encrypt,rsa_private_decrypt,
- rsa_private_encrypt,rsa_public_decrypt,
- dh_generate_key, dh_compute_key,
- %%
- stream_init, stream_encrypt, stream_decrypt,
- %% deprecated
- rc4_encrypt, rc4_set_key, rc4_encrypt_with_state,
- aes_ctr_encrypt, aes_ctr_decrypt,
- aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
- %%
- next_iv,
- %% deprecated
- aes_cbc_ivec,
- des_cbc_ivec, des_cfb_ivec,
- info,
- %%
- info_lib, supports]).
-info() ->
- ?FUNC_LIST.
+%%--------------------------------------------------------------------
+%% Engine nifs
+engine_by_id_nif(_EngineId) -> ?nif_stub.
+engine_init_nif(_Engine) -> ?nif_stub.
+engine_finish_nif(_Engine) -> ?nif_stub.
+engine_free_nif(_Engine) -> ?nif_stub.
+engine_load_dynamic_nif() -> ?nif_stub.
+engine_ctrl_cmd_strings_nif(_Engine, _Cmds) -> ?nif_stub.
+engine_add_nif(_Engine) -> ?nif_stub.
+engine_remove_nif(_Engine) -> ?nif_stub.
+engine_register_nif(_Engine, _EngineMethod) -> ?nif_stub.
+engine_unregister_nif(_Engine, _EngineMethod) -> ?nif_stub.
+engine_get_first_nif() -> ?nif_stub.
+engine_get_next_nif(_Engine) -> ?nif_stub.
+engine_get_id_nif(_Engine) -> ?nif_stub.
+engine_get_all_methods_nif() -> ?nif_stub.
+
+%%--------------------------------------------------------------------
+%% Engine internals
+engine_nif_wrapper(ok) ->
+ ok;
+engine_nif_wrapper(notsup) ->
+ erlang:error(notsup);
+engine_nif_wrapper({error, Error}) ->
+ throw({error, Error}).
+
+ensure_bin_chardata(CharData) when is_binary(CharData) ->
+ CharData;
+ensure_bin_chardata(CharData) ->
+ unicode:characters_to_binary(CharData).
+
+ensure_bin_cmds(CMDs) ->
+ ensure_bin_cmds(CMDs, []).
+
+ensure_bin_cmds([], Acc) ->
+ lists:reverse(Acc);
+ensure_bin_cmds([{Key, Value} |CMDs], Acc) ->
+ ensure_bin_cmds(CMDs, [{ensure_bin_chardata(Key), ensure_bin_chardata(Value)} | Acc]);
+ensure_bin_cmds([Key | CMDs], Acc) ->
+ ensure_bin_cmds(CMDs, [{ensure_bin_chardata(Key), <<"">>} | Acc]).
+
+engine_methods_convert_to_bitmask([], BitMask) ->
+ BitMask;
+engine_methods_convert_to_bitmask(engine_method_all, _BitMask) ->
+ 16#FFFF;
+engine_methods_convert_to_bitmask(engine_method_none, _BitMask) ->
+ 16#0000;
+engine_methods_convert_to_bitmask([M |Ms], BitMask) ->
+ engine_methods_convert_to_bitmask(Ms, BitMask bor engine_method_atom_to_int(M)).
+
+engine_method_atom_to_int(engine_method_rsa) -> 16#0001;
+engine_method_atom_to_int(engine_method_dsa) -> 16#0002;
+engine_method_atom_to_int(engine_method_dh) -> 16#0004;
+engine_method_atom_to_int(engine_method_rand) -> 16#0008;
+engine_method_atom_to_int(engine_method_ecdh) -> 16#0010;
+engine_method_atom_to_int(engine_method_ecdsa) -> 16#0020;
+engine_method_atom_to_int(engine_method_ciphers) -> 16#0040;
+engine_method_atom_to_int(engine_method_digests) -> 16#0080;
+engine_method_atom_to_int(engine_method_store) -> 16#0100;
+engine_method_atom_to_int(engine_method_pkey_meths) -> 16#0200;
+engine_method_atom_to_int(engine_method_pkey_asn1_meths) -> 16#0400;
+engine_method_atom_to_int(engine_method_ec) -> 16#0800;
+engine_method_atom_to_int(X) ->
+ erlang:error(badarg, [X]).
+
+get_test_engine() ->
+ Type = erlang:system_info(system_architecture),
+ LibDir = filename:join([code:priv_dir(crypto), "lib"]),
+ ArchDir = filename:join([LibDir, Type]),
+ case filelib:is_dir(ArchDir) of
+ true -> check_otp_test_engine(ArchDir);
+ false -> check_otp_test_engine(LibDir)
+ end.
+
+check_otp_test_engine(LibDir) ->
+ case filelib:wildcard("otp_test_engine*", LibDir) of
+ [] ->
+ {error, notexist};
+ [LibName] ->
+ LibPath = filename:join(LibDir,LibName),
+ case filelib:is_file(LibPath) of
+ true ->
+ {ok, unicode:characters_to_binary(LibPath)};
+ false ->
+ {error, notexist}
+ end
+ end.
+