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.erl1029
1 files changed, 769 insertions, 260 deletions
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index a9d933f5d7..960fe46c09 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -66,12 +66,31 @@
ensure_engine_unloaded/2
]).
+-export_type([ %% A minimum exported: only what public_key needs.
+ dh_private/0,
+ dh_public/0,
+ dss_digest_type/0,
+ ec_named_curve/0,
+ ecdsa_digest_type/0,
+ pk_encrypt_decrypt_opts/0,
+ pk_sign_verify_opts/0,
+ rsa_digest_type/0,
+ sha1/0,
+ sha2/0
+ ]).
+
-export_type([engine_ref/0,
key_id/0,
password/0
]).
-
+%%% Opaque types must be exported :(
+-export_type([
+ stream_state/0,
+ hmac_state/0,
+ hash_state/0
+ ]).
+
%% Private. For tests.
-export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2, get_test_engine/0]).
@@ -83,16 +102,187 @@
%% 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'.
+
+%%% ===== BEGIN NEW TYPING ====
+
+%%% Basic
+-type key_integer() :: integer() | binary(). % Always binary() when used as return value
+
+%%% Keys
+-type rsa_public() :: [key_integer()] . % [E, N]
+-type rsa_private() :: [key_integer()] . % [E, N, D] | [E, N, D, P1, P2, E1, E2, C]
+-type rsa_params() :: {ModulusSizeInBits::integer(), PublicExponent::key_integer()} .
+
+-type dss_public() :: [key_integer()] . % [P, Q, G, Y]
+-type dss_private() :: [key_integer()] . % [P, Q, G, X]
+
+-type ecdsa_public() :: key_integer() .
+-type ecdsa_private() :: key_integer() .
+-type ecdsa_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() .
+
+-type srp_public() :: key_integer() .
+-type srp_private() :: key_integer() .
+-type srp_gen_params() :: {user,srp_user_gen_params()} | {host,srp_host_gen_params()}.
+-type srp_comp_params() :: {user,srp_user_comp_params()} | {host,srp_host_comp_params()}.
+-type srp_user_gen_params() :: list(binary() | atom() | list()) .
+-type srp_host_gen_params() :: list(binary() | atom() | list()) .
+-type srp_user_comp_params() :: list(binary() | atom()) .
+-type srp_host_comp_params() :: list(binary() | atom()) .
+
+-type dh_public() :: key_integer() .
+-type dh_private() :: key_integer() .
+-type dh_params() :: [key_integer()] . % [P, G] | [P, G, PrivateKeyBitLength]
+
+-type ecdh_public() :: key_integer() .
+-type ecdh_private() :: key_integer() .
+-type ecdh_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() .
+
+
+%%% Curves
+
+-type ec_explicit_curve() :: {Field :: ec_field(),
+ Curve :: ec_curve(),
+ BasePoint :: binary(),
+ Order :: binary(),
+ CoFactor :: none | % FIXME: Really?
+ binary()
+ } .
+
+-type ec_curve() :: {A :: binary(),
+ B :: binary(),
+ Seed :: none | binary()
+ } .
+
+-type ec_field() :: ec_prime_field() | ec_characteristic_two_field() .
+
+-type ec_prime_field() :: {prime_field, Prime :: integer()} .
+-type ec_characteristic_two_field() :: {characteristic_two_field, M :: integer(), Basis :: ec_basis()} .
+
+-type ec_basis() :: {tpbasis, K :: non_neg_integer()}
+ | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()}
+ | onbasis .
+
+-type ec_named_curve() :: brainpoolP160r1
+ | brainpoolP160t1
+ | brainpoolP192r1
+ | brainpoolP192t1
+ | brainpoolP224r1
+ | brainpoolP224t1
+ | brainpoolP256r1
+ | brainpoolP256t1
+ | brainpoolP320r1
+ | brainpoolP320t1
+ | brainpoolP384r1
+ | brainpoolP384t1
+ | brainpoolP512r1
+ | brainpoolP512t1
+ | c2pnb163v1
+ | c2pnb163v2
+ | c2pnb163v3
+ | c2pnb176v1
+ | c2pnb208w1
+ | c2pnb272w1
+ | c2pnb304w1
+ | c2pnb368w1
+ | c2tnb191v1
+ | c2tnb191v2
+ | c2tnb191v3
+ | c2tnb239v1
+ | c2tnb239v2
+ | c2tnb239v3
+ | c2tnb359v1
+ | c2tnb431r1
+ | ipsec3
+ | ipsec4
+ | prime192v1
+ | prime192v2
+ | prime192v3
+ | prime239v1
+ | prime239v2
+ | prime239v3
+ | prime256v1
+ | secp112r1
+ | secp112r2
+ | secp128r1
+ | secp128r2
+ | secp160k1
+ | secp160r1
+ | secp160r2
+ | secp192k1
+ | secp192r1
+ | secp224k1
+ | secp224r1
+ | secp256k1
+ | secp256r1
+ | secp384r1
+ | secp521r1
+ | sect113r1
+ | sect113r2
+ | sect131r1
+ | sect131r2
+ | sect163k1
+ | sect163r1
+ | sect163r2
+ | sect193r1
+ | sect193r2
+ | sect233k1
+ | sect233r1
+ | sect239k1
+ | sect283k1
+ | sect283r1
+ | sect409k1
+ | sect409r1
+ | sect571k1
+ | sect571r1
+ | wtls1
+ | wtls10
+ | wtls11
+ | wtls12
+ | wtls3
+ | wtls4
+ | wtls5
+ | wtls6
+ | wtls7
+ | wtls8
+ | wtls9
+ .
+
+-type edwards_curve() :: x25519
+ | x448 .
+
+%%%
+-type block_cipher_with_iv() :: cbc_cipher()
+ | cfb_cipher()
+ | aes_cbc128
+ | aes_cbc256
+ | aes_ige256
+ | blowfish_ofb64
+ | des3_cbf % cfb misspelled
+ | des_ede3
+ | rc2_cbc .
+
+-type cbc_cipher() :: des_cbc | des3_cbc | aes_cbc | blowfish_cbc .
+-type aead_cipher() :: aes_gcm | aes_ccm | chacha20_poly1305 .
+-type cfb_cipher() :: aes_cfb128 | aes_cfb8 | blowfish_cfb64 | des3_cfb | des_cfb .
+
+-type block_cipher_without_iv() :: ecb_cipher() .
+-type ecb_cipher() :: des_ecb | blowfish_ecb | aes_ecb .
+
+-type key() :: iodata().
+-type des3_key() :: [key()].
+
+%%%
+-type rsa_digest_type() :: sha1() | sha2() | md5 | ripemd160 .
+-type dss_digest_type() :: sha1() | sha2() .
+-type ecdsa_digest_type() :: sha1() | sha2() .
+
+-type sha1() :: sha .
+-type sha2() :: sha224 | sha256 | sha384 | sha512 .
+-type sha3() :: sha3_224 | sha3_256 | sha3_384 | sha3_512 .
+
+-type compatibility_only_hash() :: md5 | md4 .
+
-type crypto_integer() :: binary() | integer().
-%%-type ec_named_curve() :: atom().
-%%-type ec_point() :: crypto_integer().
-%%-type ec_basis() :: {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis.
-%%-type ec_field() :: {prime_field, Prime :: integer()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}.
-%%-type ec_prime() :: {A :: crypto_integer(), B :: crypto_integer(), Seed :: binary() | none}.
-%%-type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: crypto_integer(), Order :: integer(), CoFactor :: none | integer()}.
-%%-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).
@@ -108,150 +298,239 @@ nif_stub_error(Line) ->
%% Crypto app version history:
%% (no version): Driver implementation
%% 2.0 : NIF implementation, requires OTP R14
+
+%% When generating documentation from crypto.erl, the macro ?CRYPTO_VSN is not defined.
+%% That causes the doc generation to stop...
+-ifndef(CRYPTO_VSN).
+-define(CRYPTO_VSN, "??").
+-endif.
version() -> ?CRYPTO_VSN.
+-spec start() -> ok | {error, Reason::term()}.
start() ->
application:start(crypto).
+-spec stop() -> ok | {error, Reason::term()}.
stop() ->
application:stop(crypto).
+-spec supports() -> [Support]
+ when Support :: {hashs, Hashs}
+ | {ciphers, Ciphers}
+ | {public_keys, PKs}
+ | {macs, Macs}
+ | {curves, Curves}
+ | {rsa_opts, RSAopts},
+ Hashs :: [sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash()],
+ Ciphers :: [stream_cipher()
+ | block_cipher_with_iv() | block_cipher_without_iv()
+ | aead_cipher()
+ ],
+ PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m],
+ Macs :: [hmac | cmac | poly1305],
+ Curves :: [ec_named_curve() | edwards_curve()],
+ RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] .
supports()->
- {Hashs, PubKeys, Ciphers, Macs, Curves} = algorithms(),
+ {Hashs, PubKeys, Ciphers, Macs, Curves, RsaOpts} = algorithms(),
[{hashs, Hashs},
{ciphers, Ciphers},
{public_keys, PubKeys},
{macs, Macs},
- {curves, Curves}
+ {curves, Curves},
+ {rsa_opts, RsaOpts}
].
+-spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(),
+ VerNum :: integer(),
+ VerStr :: binary() .
info_lib() -> ?nif_stub.
-spec info_fips() -> not_supported | not_enabled | enabled.
info_fips() -> ?nif_stub.
--spec enable_fips_mode(boolean()) -> boolean().
-
+-spec enable_fips_mode(Enable) -> Result when Enable :: boolean(),
+ Result :: boolean().
enable_fips_mode(_) -> ?nif_stub.
--spec hash(_, iodata()) -> binary().
+%%%================================================================
+%%%
+%%% Hashing
+%%%
+%%%================================================================
-hash(Hash, Data0) ->
- Data = iolist_to_binary(Data0),
- MaxBytes = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
+-define(HASH_HASH_ALGORITHM, sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash() ).
--spec hash_init('md5'|'md4'|'ripemd160'|
- 'sha'|'sha224'|'sha256'|'sha384'|'sha512'|
- 'sha3_224' | 'sha3_256' | 'sha3_384' | 'sha3_512') -> any().
+-spec hash(Type, Data) -> Digest when Type :: ?HASH_HASH_ALGORITHM,
+ Data :: iodata(),
+ Digest :: binary().
+hash(Type, Data) ->
+ Data1 = iolist_to_binary(Data),
+ MaxBytes = max_bytes(),
+ hash(Type, Data1, erlang:byte_size(Data1), MaxBytes).
-hash_init(Hash) ->
- notsup_to_error(hash_init_nif(Hash)).
+-opaque hash_state() :: reference().
--spec hash_update(_, iodata()) -> any().
+-spec hash_init(Type) -> State when Type :: ?HASH_HASH_ALGORITHM,
+ State :: hash_state().
+hash_init(Type) ->
+ notsup_to_error(hash_init_nif(Type)).
-hash_update(State, Data0) ->
- Data = iolist_to_binary(Data0),
+-spec hash_update(State, Data) -> NewState when State :: hash_state(),
+ NewState :: hash_state(),
+ Data :: iodata() .
+hash_update(Context, Data) ->
+ Data1 = iolist_to_binary(Data),
MaxBytes = max_bytes(),
- hash_update(State, Data, erlang:byte_size(Data), MaxBytes).
+ hash_update(Context, Data1, erlang:byte_size(Data1), MaxBytes).
--spec hash_final(_) -> binary().
+-spec hash_final(State) -> Digest when State :: hash_state(),
+ Digest :: binary().
+hash_final(Context) ->
+ notsup_to_error(hash_final_nif(Context)).
-hash_final(State) ->
- notsup_to_error(hash_final_nif(State)).
+%%%================================================================
+%%%
+%%% MACs (Message Authentication Codes)
+%%%
+%%%================================================================
+%%%---- HMAC
--spec hmac(_, iodata(), iodata()) -> binary().
--spec hmac(_, iodata(), iodata(), integer()) -> binary().
--spec hmac_init(atom(), iodata()) -> binary().
--spec hmac_update(binary(), iodata()) -> binary().
--spec hmac_final(binary()) -> binary().
--spec hmac_final_n(binary(), integer()) -> binary().
+-define(HMAC_HASH_ALGORITHM, sha1() | sha2() | sha3() | compatibility_only_hash()).
-hmac(Type, Key, Data0) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()).
-hmac(Type, Key, Data0, MacSize) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac/3,4
+
+-spec hmac(Type, Key, Data) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary() .
+hmac(Type, Key, Data) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, undefined, erlang:byte_size(Data1), max_bytes()).
+
+-spec hmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary() .
+
+hmac(Type, Key, Data, MacLength) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, MacLength, erlang:byte_size(Data1), max_bytes()).
+%%%---- hmac_init, hamc_update, hmac_final
+
+-opaque hmac_state() :: binary().
+
+-spec hmac_init(Type, Key) ->
+ State when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ State :: hmac_state() .
hmac_init(Type, Key) ->
notsup_to_error(hmac_init_nif(Type, Key)).
+%%%---- hmac_update
+
+-spec hmac_update(State, Data) -> NewState when Data :: iodata(),
+ State :: hmac_state(),
+ NewState :: hmac_state().
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac_final
+
+-spec hmac_final(State) -> Mac when State :: hmac_state(),
+ Mac :: binary().
hmac_final(Context) ->
notsup_to_error(hmac_final_nif(Context)).
+
+-spec hmac_final_n(State, HashLen) -> Mac when State :: hmac_state(),
+ HashLen :: integer(),
+ Mac :: binary().
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
+
+-define(CMAC_CIPHER_ALGORITHM, cbc_cipher() | cfb_cipher() | blowfish_cbc | des_ede3 | rc2_cbc ).
+-spec cmac(Type, Key, Data) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: 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).
--spec poly1305(iodata(), iodata()) -> binary().
+-spec cmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary().
+cmac(Type, Key, Data, MacLength) ->
+ erlang:binary_part(cmac(Type, Key, Data), 0, MacLength).
-poly1305(Key, Data) ->
- poly1305_nif(Key, Data).
+%%%---- POLY1305
-%% Ecrypt/decrypt %%%
+-spec poly1305(iodata(), iodata()) -> Mac when Mac :: binary().
--spec block_encrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()};
- (aes_gcm, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), TagLength::1..16}) -> {binary(), binary()}.
+poly1305(Key, Data) ->
+ poly1305_nif(Key, Data).
-block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
- Type =:= des_cfb;
- Type =:= blowfish_cbc;
- Type =:= blowfish_cfb64;
- Type =:= blowfish_ofb64;
- Type =:= aes_cbc128;
- Type =:= aes_cfb8;
- Type =:= aes_cfb128;
- Type =:= aes_cbc256;
- Type =:= aes_cbc;
- Type =:= rc2_cbc ->
- block_crypt_nif(Type, Key, Ivec, Data, true);
-block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
- Type =:= des_ede3 ->
+%%%================================================================
+%%%
+%%% Encrypt/decrypt
+%%%
+%%%================================================================
+
+%%%---- Block ciphers
+
+-spec block_encrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata()}) ->
+ {binary(), binary()};
+ (aes_gcm | aes_ccm, Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata(), TagLength::1..16}) ->
+ {binary(), binary()}.
+
+block_encrypt(Type, Key, Ivec, PlainText) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= aes_cbc;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, PlainText, true);
+block_encrypt(Type, Key0, Ivec, PlainText) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true);
-block_encrypt(des3_cbf, Key0, Ivec, Data) ->
+ block_crypt_nif(des_ede3_cbc, Key, Ivec, PlainText, true);
+block_encrypt(des3_cbf, Key0, Ivec, PlainText) -> % cfb misspelled
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true);
-block_encrypt(des3_cfb, Key0, Ivec, Data) ->
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, PlainText, true);
+block_encrypt(des3_cfb, Key0, Ivec, PlainText) ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, true);
-block_encrypt(aes_ige256, Key, Ivec, Data) ->
- 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}) ->
- aes_gcm_encrypt(Key, Ivec, AAD, Data, TagLength);
-block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) ->
- chacha20_poly1305_encrypt(Key, Ivec, AAD, Data).
-
--spec block_decrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(),
+ block_crypt_nif(des_ede3_cfb, Key, Ivec, PlainText, true);
+block_encrypt(aes_ige256, Key, Ivec, PlainText) ->
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, PlainText, true));
+block_encrypt(Type, Key, Ivec, {AAD, PlainText}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText);
+block_encrypt(Type, Key, Ivec, {AAD, PlainText, TagLength}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText, TagLength);
+block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, PlainText}) ->
+ chacha20_poly1305_encrypt(Key, Ivec, AAD, PlainText).
+
+-spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(),
{AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error.
block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
Type =:= des_cfb;
@@ -269,7 +548,7 @@ block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
Type =:= des_ede3 ->
Key = check_des3_key(Key0),
block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false);
-block_decrypt(des3_cbf, Key0, Ivec, Data) ->
+block_decrypt(des3_cbf, Key0, Ivec, Data) -> % cfb misspelled
Key = check_des3_key(Key0),
block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false);
block_decrypt(des3_cfb, Key0, Ivec, Data) ->
@@ -277,23 +556,29 @@ block_decrypt(des3_cfb, Key0, Ivec, Data) ->
block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, false);
block_decrypt(aes_ige256, Key, Ivec, Data) ->
notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
-block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) ->
- aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag);
+block_decrypt(Type, Key, Ivec, {AAD, Data, Tag}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_decrypt(Type, Key, Ivec, AAD, Data, Tag);
block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) ->
chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag).
--spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
-block_encrypt(Type, Key, Data) ->
- block_crypt_nif(Type, Key, Data, true).
--spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
+-spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) -> binary().
+
+block_encrypt(Type, Key, PlainText) ->
+ block_crypt_nif(Type, Key, PlainText, true).
+
+
+-spec block_decrypt(Type::block_cipher_without_iv(), Key::key(), Data::iodata()) -> binary().
block_decrypt(Type, Key, Data) ->
block_crypt_nif(Type, Key, Data, false).
--spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary().
+-spec next_iv(Type:: cbc_cipher(), Data) -> NextIVec when % Type :: cbc_cipher(), %des_cbc | des3_cbc | aes_cbc | aes_ige,
+ Data :: iodata(),
+ NextIVec :: binary().
next_iv(Type, Data) when is_binary(Data) ->
IVecSize = case Type of
des_cbc -> 8;
@@ -306,7 +591,9 @@ next_iv(Type, Data) when is_binary(Data) ->
next_iv(Type, Data) when is_list(Data) ->
next_iv(Type, list_to_binary(Data)).
--spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
+-spec next_iv(des_cfb, Data, IVec) -> NextIVec when Data :: iodata(),
+ IVec :: binary(),
+ NextIVec :: binary().
next_iv(des_cfb, Data, IVec) ->
IVecAndData = list_to_binary([IVec, Data]),
@@ -315,41 +602,57 @@ next_iv(des_cfb, Data, IVec) ->
next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
+%%%---- Stream ciphers
+
+-opaque stream_state() :: {stream_cipher(), reference()}.
+
+-type stream_cipher() :: rc4 | aes_ctr | chacha20 .
+
+-spec stream_init(Type, Key, IVec) -> State when Type :: aes_ctr | chacha20,
+ Key :: iodata(),
+ IVec :: binary(),
+ State :: stream_state() .
stream_init(aes_ctr, Key, Ivec) ->
{aes_ctr, aes_ctr_stream_init(Key, Ivec)};
stream_init(chacha20, Key, Ivec) ->
{chacha20, chacha20_stream_init(Key,Ivec)}.
+-spec stream_init(Type, Key) -> State when Type :: rc4,
+ Key :: iodata(),
+ State :: stream_state() .
stream_init(rc4, Key) ->
{rc4, notsup_to_error(rc4_set_key(Key))}.
+-spec stream_encrypt(State, PlainText) -> {NewState, CipherText}
+ when State :: stream_state(),
+ PlainText :: iodata(),
+ NewState :: stream_state(),
+ CipherText :: iodata() .
stream_encrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_encrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+-spec stream_decrypt(State, CipherText) -> {NewState, PlainText}
+ when State :: stream_state(),
+ CipherText :: iodata(),
+ NewState :: stream_state(),
+ PlainText :: iodata() .
stream_decrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
-%%
-%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
-%%
+
+%%%================================================================
+%%%
+%%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
+%%%
+%%%================================================================
-type rand_cache_seed() ::
nonempty_improper_list(non_neg_integer(), binary()).
--spec strong_rand_bytes(non_neg_integer()) -> binary().
--spec rand_seed() -> rand:state().
--spec rand_seed_s() -> rand:state().
--spec rand_seed_alg(Alg :: atom()) ->
- {rand:alg_handler(),
- atom() | rand_cache_seed()}.
--spec rand_seed_alg_s(Alg :: atom()) ->
- {rand:alg_handler(),
- atom() | rand_cache_seed()}.
--spec rand_uniform(crypto_integer(), crypto_integer()) ->
- crypto_integer().
+-spec strong_rand_bytes(N::non_neg_integer()) -> binary().
strong_rand_bytes(Bytes) ->
case strong_rand_bytes_nif(Bytes) of
false -> erlang:error(low_entropy);
@@ -358,16 +661,24 @@ strong_rand_bytes(Bytes) ->
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+-spec rand_seed() -> rand:state().
rand_seed() ->
rand:seed(rand_seed_s()).
+-spec rand_seed_s() -> rand:state().
rand_seed_s() ->
rand_seed_alg_s(?MODULE).
+-spec rand_seed_alg(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
rand_seed_alg(Alg) ->
rand:seed(rand_seed_alg_s(Alg)).
-define(CRYPTO_CACHE_BITS, 56).
+-spec rand_seed_alg_s(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
rand_seed_alg_s(?MODULE) ->
{#{ type => ?MODULE,
bits => 64,
@@ -425,7 +736,9 @@ 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) ->
+-spec rand_uniform(crypto_integer(), crypto_integer()) ->
+ crypto_integer().
+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 ->
<<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
@@ -460,116 +773,228 @@ rand_seed(Seed) when is_binary(Seed) ->
rand_seed_nif(_Seed) -> ?nif_stub.
--spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
-mod_pow(Base, Exponent, Prime) ->
- case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
- <<0>> -> error;
- R -> R
- end.
+%%%================================================================
+%%%
+%%% Sign/verify
+%%%
+%%%================================================================
+-type pk_sign_verify_algs() :: rsa | dss | ecdsa .
-verify(Algorithm, Type, Data, Signature, Key) ->
- verify(Algorithm, Type, Data, Signature, Key, []).
+-type pk_sign_verify_opts() :: [ rsa_sign_verify_opt() ] .
+
+-type rsa_sign_verify_opt() :: {rsa_padding, rsa_sign_verify_padding()}
+ | {rsa_pss_saltlen, integer()} .
+
+-type rsa_sign_verify_padding() :: rsa_pkcs1_padding | rsa_pkcs1_pss_padding
+ | rsa_x931_padding | rsa_no_padding
+ .
-%% 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.
+%%%----------------------------------------------------------------
+%%% Sign
+
+-spec sign(Algorithm, DigestType, Msg, Key)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private()|ecdsa_params()]
+ | engine_key_ref(),
+ Signature :: binary() .
sign(Algorithm, Type, Data, Key) ->
sign(Algorithm, Type, Data, Key, []).
-%% Backwards compatible
-sign(Algorithm = dss, none, Digest, Key, Options) ->
- sign(Algorithm, sha, {digest, Digest}, Key, Options);
-sign(Algorithm, Type, Data, Key, Options) ->
+
+-spec sign(Algorithm, DigestType, Msg, Key, Options)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type()
+ | none,
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Signature :: binary() .
+
+sign(Algorithm0, Type0, Data, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
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.
+pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
+%%%----------------------------------------------------------------
+%%% Verify
+
+-spec verify(Algorithm, DigestType, Msg, Signature, Key)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Result :: boolean().
--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().
+verify(Algorithm, Type, Data, Signature, Key) ->
+ verify(Algorithm, Type, Data, Signature, Key, []).
-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]);
+-spec verify(Algorithm, DigestType, Msg, Signature, Key, Options)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_public()
+ | dss_public()
+ | [ecdsa_public() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Result :: boolean().
+
+verify(Algorithm0, Type0, Data, Signature, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
+ case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
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}]).
+ Boolean -> Boolean
+ end.
-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}]).
+pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
-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}]).
+%% Backwards compatible:
+sign_verify_compatibility(dss, none, Digest) ->
+ {sha, {digest, Digest}};
+sign_verify_compatibility(Algorithm0, Type0, _Digest) ->
+ {Algorithm0, Type0}.
-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]);
+%%%================================================================
+%%%
+%%% Public/private encrypt/decrypt
+%%%
+%%% Only rsa works so far (although ecdsa | dss should do it)
+%%%================================================================
+-type pk_encrypt_decrypt_algs() :: rsa .
+
+-type pk_encrypt_decrypt_opts() :: [rsa_opt()] | rsa_compat_opts().
+
+-type rsa_compat_opts() :: [{rsa_pad, rsa_padding()}]
+ | rsa_padding() .
+
+-type rsa_padding() :: rsa_pkcs1_padding
+ | rsa_pkcs1_oaep_padding
+ | rsa_sslv23_padding
+ | rsa_x931_padding
+ | rsa_no_padding.
+
+-type rsa_opt() :: {rsa_padding, rsa_padding()}
+ | {signature_md, atom()}
+ | {rsa_mgf1_md, sha}
+ | {rsa_oaep_label, binary()}
+ | {rsa_oaep_md, sha} .
+
+%%%---- Encrypt with public key
+
+-spec public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PublicKey, Options, false, true).
+
+%%%---- Decrypt with private key
+
+-spec private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PrivateKey, Options, true, false).
+
+%%%---- Encrypt with private key
+
+-spec private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PrivateKey, Options, true, true).
+
+%%%---- Decrypt with public key
+
+-spec public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PublicKey, Options, false, false).
+
+%%%---- Call the nif, but fix a compatibility issue first
+
+%% Backwards compatible (rsa_pad -> rsa_padding is handled by the pkey_crypt_nif):
+pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) ->
+ pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec);
+
+pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) ->
+ case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of
+ error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]);
+ error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, 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
-%% them and sends them to the driver
-%%
--spec exor(iodata(), iodata()) -> binary().
+ end.
-exor(Bin1, Bin2) ->
- Data1 = iolist_to_binary(Bin1),
- Data2 = iolist_to_binary(Bin2),
- MaxBytes = max_bytes(),
- exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
+%%%================================================================
+%%%
+%%%
+%%%
+%%%================================================================
+
+-spec generate_key(Type, Params)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_gen_params()
+ .
generate_key(Type, Params) ->
generate_key(Type, Params, undefined).
+-spec generate_key(Type, Params, PrivKeyIn)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_comp_params()
+ .
+
generate_key(dh, DHParameters0, PrivateKey) ->
{DHParameters, Len} =
case DHParameters0 of
@@ -616,6 +1041,14 @@ generate_key(ecdh, Curve, PrivKey) ->
evp_generate_key_nif(_Curve) -> ?nif_stub.
+-spec compute_key(Type, OthersPublicKey, MyPrivateKey, Params)
+ -> SharedSecret
+ when Type :: dh | ecdh | srp,
+ SharedSecret :: binary(),
+ OthersPublicKey :: dh_public() | ecdh_public() | srp_public(),
+ MyPrivateKey :: dh_private() | ecdh_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | srp_comp_params()
+ .
compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
@@ -668,9 +1101,59 @@ compute_key(ecdh, Others, My, Curve) ->
evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
-%%======================================================================
-%% Engine functions
-%%======================================================================
+
+%%%================================================================
+%%%
+%%% XOR - xor to iolists and return a binary
+%%% NB doesn't check that they are the same size, just concatenates
+%%% them and sends them to the driver
+%%%
+%%%================================================================
+
+-spec exor(iodata(), iodata()) -> binary().
+
+exor(Bin1, Bin2) ->
+ Data1 = iolist_to_binary(Bin1),
+ Data2 = iolist_to_binary(Bin2),
+ MaxBytes = max_bytes(),
+ exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+
+
+%%%================================================================
+%%%
+%%% Exponentiation modulo
+%%%
+%%%================================================================
+
+-spec mod_pow(N, P, M) -> Result when N :: binary() | integer(),
+ P :: binary() | integer(),
+ M :: binary() | integer(),
+ Result :: binary() | error .
+mod_pow(Base, Exponent, Prime) ->
+ case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
+ <<0>> -> error;
+ R -> R
+ end.
+
+%%%======================================================================
+%%%
+%%% Engine functions
+%%%
+%%%======================================================================
+
+%%%---- Refering to keys stored in an engine:
+-type key_id() :: string() | binary() .
+-type password() :: string() | binary() .
+
+-type engine_key_ref() :: #{engine := engine_ref(),
+ key_id := key_id(),
+ password => password(),
+ term() => term()
+ }.
+
+%%%---- Commands:
+-type engine_cmnd() :: {unicode:chardata(), unicode:chardata()}.
+
%%----------------------------------------------------------------------
%% Function: engine_get_all_methods/0
%%----------------------------------------------------------------------
@@ -682,18 +1165,18 @@ evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
-type engine_ref() :: term().
--spec engine_get_all_methods() ->
- [engine_method_type()].
+-spec engine_get_all_methods() -> Result when Result :: [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()}.
+-spec engine_load(EngineId, PreCmds, PostCmds) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ Result :: {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()).
@@ -701,11 +1184,12 @@ engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds),
%%----------------------------------------------------------------------
%% 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()}.
+-spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ EngineMethods::[engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
is_list(PostCmds) ->
try
@@ -750,13 +1234,14 @@ engine_load_2(Engine, PostCmds, EngineMethods) ->
%%----------------------------------------------------------------------
%% Function: engine_unload/1
%%----------------------------------------------------------------------
--spec engine_unload(Engine::term()) ->
- ok | {error, Reason::term()}.
+-spec engine_unload(Engine) -> Result when Engine :: engine_ref(),
+ Result :: 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()}.
+-spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
engine_unload(Engine, EngineMethods) ->
try
[ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
@@ -773,6 +1258,8 @@ engine_unload(Engine, EngineMethods) ->
%%----------------------------------------------------------------------
%% Function: engine_by_id/1
%%----------------------------------------------------------------------
+-spec engine_by_id(EngineId) -> Result when EngineId :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()} .
engine_by_id(EngineId) ->
try
notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)))
@@ -784,32 +1271,39 @@ engine_by_id(EngineId) ->
%%----------------------------------------------------------------------
%% Function: engine_add/1
%%----------------------------------------------------------------------
+-spec engine_add(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
engine_add(Engine) ->
notsup_to_error(engine_add_nif(Engine)).
%%----------------------------------------------------------------------
%% Function: engine_remove/1
%%----------------------------------------------------------------------
+-spec engine_remove(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
engine_remove(Engine) ->
notsup_to_error(engine_remove_nif(Engine)).
%%----------------------------------------------------------------------
%% Function: engine_get_id/1
%%----------------------------------------------------------------------
+-spec engine_get_id(Engine) -> EngineId when Engine :: engine_ref(),
+ EngineId :: unicode:chardata().
engine_get_id(Engine) ->
notsup_to_error(engine_get_id_nif(Engine)).
%%----------------------------------------------------------------------
%% Function: engine_get_name/1
%%----------------------------------------------------------------------
+-spec engine_get_name(Engine) -> EngineName when Engine :: engine_ref(),
+ EngineName :: unicode:chardata().
engine_get_name(Engine) ->
notsup_to_error(engine_get_name_nif(Engine)).
%%----------------------------------------------------------------------
%% Function: engine_list/0
%%----------------------------------------------------------------------
--spec engine_list() ->
- [EngineId::binary()].
+-spec engine_list() -> Result when Result :: [EngineId::unicode:chardata()].
engine_list() ->
case notsup_to_error(engine_get_first_nif()) of
{ok, <<>>} ->
@@ -839,21 +1333,23 @@ engine_list(Engine0, IdList) ->
%%----------------------------------------------------------------------
%% Function: engine_ctrl_cmd_string/3
%%----------------------------------------------------------------------
--spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
- CmdArg::unicode:chardata()) ->
- ok | {error, Reason::term()}.
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Result :: 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()}.
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Optional::boolean(),
+ Result :: ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
case engine_ctrl_cmd_strings_nif(Engine,
ensure_bin_cmds([{CmdName, CmdArg}]),
@@ -870,6 +1366,10 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
%% Function: ensure_engine_loaded/2
%% Special version of load that only uses dynamic engine to load
%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
ensure_engine_loaded(EngineId, LibPath) ->
ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()).
@@ -877,6 +1377,11 @@ ensure_engine_loaded(EngineId, LibPath) ->
%% Function: ensure_engine_loaded/3
%% Special version of load that only uses dynamic engine to load
%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ EngineMethods :: [engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
try
List = crypto:engine_list(),
@@ -928,12 +1433,18 @@ ensure_engine_loaded_2(Engine, Methods) ->
%%----------------------------------------------------------------------
%% Function: ensure_engine_unloaded/1
%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()}.
ensure_engine_unloaded(Engine) ->
ensure_engine_unloaded(Engine, engine_get_all_methods()).
%%----------------------------------------------------------------------
%% Function: ensure_engine_unloaded/2
%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine, EngineMethods) ->
+ Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
ensure_engine_unloaded(Engine, EngineMethods) ->
case engine_remove(Engine) of
ok ->
@@ -1008,9 +1519,13 @@ path2bin(Path) when is_list(Path) ->
Bin
end.
-%%--------------------------------------------------------------------
+%%%================================================================
+%%%================================================================
+%%%
%%% Internal functions
-%%--------------------------------------------------------------------
+%%%
+%%%================================================================
+
max_bytes() ->
?MAX_BYTES_TO_NIF.
@@ -1095,10 +1610,11 @@ check_des3_key(Key) ->
%% AES - in Galois/Counter Mode (GCM)
%%
%% The default tag length is EVP_GCM_TLS_TAG_LEN(16),
-aes_gcm_encrypt(Key, Ivec, AAD, In) ->
- aes_gcm_encrypt(Key, Ivec, AAD, In, 16).
-aes_gcm_encrypt(_Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
-aes_gcm_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_encrypt(Type=aes_ccm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 12);
+aead_encrypt(Type=aes_gcm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 16).
+
+aead_encrypt(_Type, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
+aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
%%
%% Chacha20/Ppoly1305
@@ -1149,14 +1665,6 @@ do_stream_decrypt({chacha20, State0}, Data) ->
%%
%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
--type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary().
-
--spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state().
--spec aes_ctr_stream_encrypt(ctr_state(), binary()) ->
- { 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.
@@ -1170,11 +1678,6 @@ rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
%%
%% CHACHA20 - stream cipher
%%
--type chacha20_state() :: term().
--spec chacha20_stream_init(iodata(), binary()) -> chacha20_state().
--spec chacha20_stream_encrypt(chacha20_state(), binary()) -> {chacha20_state(), binary()}.
--spec chacha20_stream_decrypt(chacha20_state(), binary()) -> {chacha20_state(), binary()}.
-
chacha20_stream_init(_Key, _IVec) -> ?nif_stub.
chacha20_stream_encrypt(_State, _Data) -> ?nif_stub.
chacha20_stream_decrypt(_State, _Data) -> ?nif_stub.
@@ -1245,11 +1748,6 @@ srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?
srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
-%% Digital signatures --------------------------------------------------------------------
-
-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
%%
@@ -1271,13 +1769,20 @@ ec_key_generate(_Curve, _Key) -> ?nif_stub.
ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
+-spec ec_curves() -> [EllipticCurve] when EllipticCurve :: ec_named_curve() | edwards_curve() .
+
ec_curves() ->
crypto_ec_curves:curves().
+-spec ec_curve(CurveName) -> ExplicitCurve when CurveName :: ec_named_curve(),
+ ExplicitCurve :: ec_explicit_curve() .
ec_curve(X) ->
crypto_ec_curves:curve(X).
+-spec privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey when Type :: rsa | dss,
+ EnginePrivateKeyRef :: engine_key_ref(),
+ PublicKey :: rsa_public() | dss_public() .
privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap))
of
@@ -1303,10 +1808,16 @@ term_to_nif_prime({prime_field, Prime}) ->
{prime_field, ensure_int_as_bin(Prime)};
term_to_nif_prime(PrimeField) ->
PrimeField.
+
term_to_nif_curve({A, B, Seed}) ->
{ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}.
+
nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) ->
- {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), ensure_int_as_bin(Order), ensure_int_as_bin(CoFactor)};
+ {term_to_nif_prime(PrimeField),
+ term_to_nif_curve(Curve),
+ ensure_int_as_bin(BasePoint),
+ ensure_int_as_bin(Order),
+ ensure_int_as_bin(CoFactor)};
nif_curve_params(Curve) when is_atom(Curve) ->
%% named curve
case Curve of
@@ -1346,6 +1857,7 @@ int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
int_to_bin_neg(X,Ds) ->
int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
+-spec bytes_to_integer(binary()) -> integer() .
bytes_to_integer(Bin) ->
bin_to_int(Bin).
@@ -1393,9 +1905,6 @@ format_pwd(M) -> M.
%%--------------------------------------------------------------------
%%
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
-
-pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
%% large integer in a binary with 32bit length
%% MP representaion (SSH2)