diff options
Diffstat (limited to 'lib/crypto/src')
-rw-r--r-- | lib/crypto/src/Makefile | 18 | ||||
-rw-r--r-- | lib/crypto/src/crypto.app.src | 6 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 1238 | ||||
-rw-r--r-- | lib/crypto/src/crypto_ec_curves.erl | 25 |
4 files changed, 548 insertions, 739 deletions
diff --git a/lib/crypto/src/Makefile b/lib/crypto/src/Makefile index 456b8be64d..edad0e6b61 100644 --- a/lib/crypto/src/Makefile +++ b/lib/crypto/src/Makefile @@ -39,8 +39,7 @@ MODULES= \ crypto \ crypto_ec_curves -HRL_FILES= - +HRL_FILES= ERL_FILES= $(MODULES:%=%.erl) TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR)) @@ -56,16 +55,16 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE) # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- -ERL_COMPILE_FLAGS += +warn_obsolete_guard -DCRYPTO_VSN=\"$(VSN)\" -Werror +ERL_COMPILE_FLAGS += -DCRYPTO_VSN=\"$(VSN)\" -Werror -I../include # ---------------------------------------------------- # Targets # ---------------------------------------------------- -debug opt valgrind: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) +debug opt valgrind: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) clean: - rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) + rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) rm -f errs core *~ $(APP_TARGET): $(APP_SRC) ../vsn.mk @@ -78,7 +77,7 @@ docs: # ---------------------------------------------------- # Release Target -# ---------------------------------------------------- +# ---------------------------------------------------- include $(ERL_TOP)/make/otp_release_targets.mk release_spec: opt @@ -89,10 +88,3 @@ release_spec: opt $(APPUP_TARGET) "$(RELSYSDIR)/ebin" release_docs_spec: - - - - - - - diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src index 8a47b8a78b..1d3f35e465 100644 --- a/lib/crypto/src/crypto.app.src +++ b/lib/crypto/src/crypto.app.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ crypto_ec_curves]}, {registered, []}, {applications, [kernel, stdlib]}, - {env, []}, - {runtime_dependencies, ["erts-6.0","stdlib-2.0","kernel-3.0"]}]}. + {env, [{fips_mode, false}]}, + {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 60e0affda0..1a1b4f98b5 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,38 @@ -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, + engine_ctrl_cmd_string/3, + engine_ctrl_cmd_string/4 + ]). -%% 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 +84,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 +107,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 +177,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 +220,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 +315,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 +331,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 +396,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 +409,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 +539,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 +556,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 +595,174 @@ 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), 0)), + 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), 0)), + [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. + +%%---------------------------------------------------------------------- +%% Function: engine_ctrl_cmd_string/3 +%%---------------------------------------------------------------------- +-spec engine_ctrl_cmd_string(Engine::term(), + CmdName::unicode:chardata(), + CmdArg::unicode:chardata()) -> + ok | {error, Reason::term()}. +engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> + engine_ctrl_cmd_string(Engine, CmdName, CmdArg, false). + +%%---------------------------------------------------------------------- +%% Function: engine_ctrl_cmd_string/4 +%%---------------------------------------------------------------------- +-spec engine_ctrl_cmd_string(Engine::term(), + CmdName::unicode:chardata(), + CmdArg::unicode:chardata(), + Optional::boolean()) -> + ok | {error, Reason::term()}. +engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> + case engine_ctrl_cmd_strings_nif(Engine, + ensure_bin_cmds([{CmdName, CmdArg}]), + bool_to_int(Optional)) of + ok -> + ok; + notsup -> + erlang:error(notsup); + {error, Error} -> + {error, Error} + end. + %%-------------------------------------------------------------------- %%% On load %%-------------------------------------------------------------------- - on_load() -> LibBaseName = "crypto", PrivDir = code:priv_dir(crypto), @@ -649,7 +788,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 +802,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 +822,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 +852,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 +882,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). +%% CMAC -md5_mac_96(Key, Data) -> hmac(md5, Key, Data, 12). - -%% -%% 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 +902,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 +917,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 +949,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 +960,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 +1018,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 +1038,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 +1074,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 +1090,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 +1175,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 +1218,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 +1235,110 @@ 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, _Optional) -> ?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)). + +bool_to_int(true) -> 1; +bool_to_int(false) -> 0. + +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. + diff --git a/lib/crypto/src/crypto_ec_curves.erl b/lib/crypto/src/crypto_ec_curves.erl index 002b03b80c..9602a7e24b 100644 --- a/lib/crypto/src/crypto_ec_curves.erl +++ b/lib/crypto/src/crypto_ec_curves.erl @@ -7,29 +7,36 @@ curves() -> PubKeys = proplists:get_value(public_keys, CryptoSupport), HasEC = proplists:get_bool(ecdh, PubKeys), HasGF2m = proplists:get_bool(ec_gf2m, PubKeys), - prime_curves(HasEC) ++ characteristic_two_curves(HasGF2m). + FIPSMode = crypto:info_fips() == enabled, + prime_curves(HasEC, FIPSMode) ++ characteristic_two_curves(HasGF2m, FIPSMode). -prime_curves(true) -> - [secp112r1,secp112r2,secp128r1,secp128r2,secp160k1,secp160r1,secp160r2, +prime_curves(true, true) -> + [secp160k1,secp160r1,secp160r2, secp192r1,secp192k1,secp224k1,secp224r1,secp256k1,secp256r1,secp384r1, secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3, - prime256v1,wtls6,wtls7,wtls8,wtls9,wtls12, + prime256v1,wtls7,wtls9,wtls12, brainpoolP160r1,brainpoolP160t1,brainpoolP192r1,brainpoolP192t1, brainpoolP224r1,brainpoolP224t1,brainpoolP256r1,brainpoolP256t1, brainpoolP320r1,brainpoolP320t1,brainpoolP384r1,brainpoolP384t1, brainpoolP512r1,brainpoolP512t1]; -prime_curves(_) -> +prime_curves(true, false) -> + [secp112r1,secp112r2,secp128r1,secp128r2,wtls6,wtls8] + ++ prime_curves(true, true); +prime_curves(_, _) -> []. -characteristic_two_curves(true) -> - [sect113r1,sect113r2,sect131r1,sect131r2,sect163k1,sect163r1, +characteristic_two_curves(true, true) -> + [sect163k1,sect163r1, sect163r2,sect193r1,sect193r2,sect233k1,sect233r1,sect239k1,sect283k1, sect283r1,sect409k1,sect409r1,sect571k1,sect571r1,c2pnb163v1,c2pnb163v2, c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1, c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359v1,c2pnb368w1,c2tnb431r1, - wtls1,wtls3,wtls4,wtls5,wtls10,wtls11,ipsec3,ipsec4]; -characteristic_two_curves(_) -> + wtls3,wtls5,wtls10,wtls11]; +characteristic_two_curves(true, _) -> + [sect113r1,sect113r2,sect131r1,sect131r2,wtls1,wtls4,ipsec3,ipsec4] + ++ characteristic_two_curves(true, true); +characteristic_two_curves(_, _) -> []. curve(secp112r1) -> |