From 9dea5a397111f1e049f10b9e1a2d6f70a9db6a95 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 21 Mar 2013 11:59:42 +0100 Subject: crypto: Refactor mod_exp_nif As a preparation for the new mod_exp_prime and in the quest to reduce to use of the old mpint format. --- lib/crypto/src/crypto.erl | 79 ++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 35 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 1328a95e87..f5c1cd2845 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -787,17 +787,15 @@ rand_uniform_nif(_From,_To) -> ?nif_stub. %% mod_exp(Base, Exponent, Modulo) when is_integer(Base), is_integer(Exponent), is_integer(Modulo) -> - erlint(mod_exp(mpint(Base), mpint(Exponent), mpint(Modulo))); + bin_to_int(mod_exp_nif(int_to_bin(Base), int_to_bin(Exponent), int_to_bin(Modulo), 0)); mod_exp(Base, Exponent, Modulo) -> - case mod_exp_nif(Base,Exponent,Modulo) of - <> when MSB > 127 -> - <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; - Whatever -> - Whatever + mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4). + end. -mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub. + +mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub. %% %% DSS, RSA - verify @@ -1071,43 +1069,54 @@ dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. %% large integer in a binary with 32bit length %% MP representaion (SSH2) -mpint(X) when X < 0 -> - case X of - -1 -> - <<0,0,0,1,16#ff>>; - _ -> - mpint_neg(X,0,[]) - end; -mpint(X) -> - case X of - 0 -> - <<0,0,0,0>>; - _ -> - mpint_pos(X,0,[]) - end. +mpint(X) when X < 0 -> mpint_neg(X); +mpint(X) -> mpint_pos(X). -define(UINT32(X), X:32/unsigned-big-integer). -mpint_neg(-1,I,Ds=[MSB|_]) -> - if MSB band 16#80 =/= 16#80 -> - <>; - true -> - (<>) - end; -mpint_neg(X,I,Ds) -> - mpint_neg(X bsr 8,I+1,[(X band 255)|Ds]). + +mpint_neg(X) -> + Bin = int_to_bin_neg(X, []), + Sz = byte_size(Bin), + <>. -mpint_pos(0,I,Ds=[MSB|_]) -> +mpint_pos(X) -> + Bin = int_to_bin_pos(X, []), + <> = Bin, + Sz = byte_size(Bin), if MSB band 16#80 == 16#80 -> - <>; + <>; true -> - (<>) - end; -mpint_pos(X,I,Ds) -> - mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]). + <> + end. + +int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []); +int_to_bin(X) -> int_to_bin_pos(X, []). + +int_to_bin_pos(X) when X >= 0 -> + int_to_bin_pos(X, []). + +int_to_bin_pos(0,Ds=[_|_]) -> + list_to_binary(Ds); +int_to_bin_pos(X,Ds) -> + int_to_bin_pos(X bsr 8, [(X band 255)|Ds]). + +int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 -> + list_to_binary(Ds); +int_to_bin_neg(X,Ds) -> + int_to_bin_neg(X bsr 8, [(X band 255)|Ds]). + + +bin_to_int(Bin) -> + Bits = bit_size(Bin), + <> = Bin, + Integer. %% int from integer in a binary with 32bit length erlint(<>) -> Bits= MPIntSize * 8, <> = MPIntValue, Integer. + +mpint_to_bin(<>) -> + Bin. -- cgit v1.2.3 From d8144ef38f7e18230349100bbdee1da4c723fd94 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Wed, 12 Sep 2012 20:57:01 +0200 Subject: CRYPTO: add support for RFC-2945 SRP-3 and RFC-5054 SRP-6a authentication --- lib/crypto/src/crypto.erl | 71 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index f5c1cd2845..0a0ebc05c4 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -57,7 +57,11 @@ -export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]). -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). -export([strong_rand_bytes/1, strong_rand_mpint/3]). --export([mod_exp/3, mpint/1, erlint/1]). +-export([mod_exp/3, mod_exp_prime/3, mpint/1, erlint/1]). +-export([srp_value_B/5]). +-export([srp3_value_u/1, srp6_value_u/3, srp6a_multiplier/2]). +-export([srp_client_secret/7, srp_server_secret/5]). + %% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]). -export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). -export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]). @@ -88,7 +92,7 @@ strong_rand_bytes, strong_rand_mpint, rand_uniform, - mod_exp, + mod_exp, mod_exp_prime, dss_verify,dss_sign, rsa_verify,rsa_sign, rsa_public_encrypt,rsa_private_decrypt, @@ -109,6 +113,9 @@ hash, hash_init, hash_update, hash_final, hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, + srp_value_B, + srp3_value_u, srp6_value_u, srp6a_multiplier, + srp_client_secret, srp_server_secret, info_lib]). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. @@ -783,7 +790,7 @@ rand_uniform_pos(_,_) -> rand_uniform_nif(_From,_To) -> ?nif_stub. %% -%% mod_exp - utility for rsa generation +%% mod_exp - utility for rsa generation and SRP %% mod_exp(Base, Exponent, Modulo) when is_integer(Base), is_integer(Exponent), is_integer(Modulo) -> @@ -792,6 +799,11 @@ mod_exp(Base, Exponent, Modulo) mod_exp(Base, Exponent, Modulo) -> mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4). +-spec mod_exp_prime(binary(), binary(), binary()) -> binary(). +mod_exp_prime(Base, Exponent, Prime) -> + case mod_exp_nif(Base, Exponent, Prime, 0) of + <<0>> -> error; + R -> R end. @@ -1062,10 +1074,63 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) -> dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. + +-spec srp_value_B(binary(), integer(), binary(), binary(), binary()) -> binary(). +srp_value_B(Multiplier, Verifier, Generator, Exponent, Prime) -> + srp_value_B_nif(srp_multiplier(Multiplier), Verifier, Generator, Exponent, Prime). + +srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. + +-spec srp_client_secret(binary(), binary(), binary(), integer()|binary(), binary(), binary(), binary()) -> binary(). +srp_client_secret(A, U, B, Multiplier, Generator, Exponent, Prime) -> + srp_client_secret_nif(A, U, B, srp_multiplier(Multiplier), Generator, Exponent, Prime). + +srp_client_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. + +-spec srp_server_secret(binary(), binary(), binary(), binary(), binary()) -> binary(). +srp_server_secret(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. + +-spec srp6a_multiplier(binary(), binary()) -> binary(). +srp6a_multiplier(Generator, Prime) -> + %% k = SHA1(N | PAD(g)) + C0 = sha_init(), + C1 = sha_update(C0, Prime), + C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)), + sha_final(C2). + +-spec srp3_value_u(binary()) -> binary(). +srp3_value_u(B) -> + %% 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. + <> = sha(B), + U. + +-spec srp6_value_u(binary(), binary(), binary()) -> binary(). +srp6_value_u(A, B, Prime) -> + %% SHA1(PAD(A) | PAD(B)) + PadLength = erlang:byte_size(Prime), + C0 = sha_init(), + C1 = sha_update(C0, srp_pad_to(PadLength, A)), + C2 = sha_update(C1, srp_pad_to(PadLength, B)), + sha_final(C2). + %% %% LOCAL FUNCTIONS %% +srp_pad_length(Width, Length) -> + (Width - Length rem Width) rem Width. + +srp_pad_to(Width, Binary) -> + case srp_pad_length(Width, size(Binary)) of + 0 -> Binary; + N -> << 0:(N*8), Binary/binary>> + end. + +srp_multiplier(Multiplier) when is_binary(Multiplier) -> + Multiplier; +srp_multiplier(Multiplier) when is_integer(Multiplier) -> + int_to_bin_pos(Multiplier). %% large integer in a binary with 32bit length %% MP representaion (SSH2) -- cgit v1.2.3 From 71f8eb83a9088ebedc2b557ae7f86b3db71d1a13 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Tue, 19 Feb 2013 17:36:57 +0100 Subject: CRYPTO: add algorithms/0 function that returns a list off compiled in crypto algorithms add algorithms/0 function that returns a list off compiled in crypto algorithms and make tests suites with SHA226, SHA256, SHA384 and SHA512 conditional based on that --- lib/crypto/src/crypto.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 0a0ebc05c4..e8867236ac 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -21,7 +21,7 @@ -module(crypto). --export([start/0, stop/0, info/0, info_lib/0, version/0]). +-export([start/0, stop/0, info/0, info_lib/0, algorithms/0, version/0]). -export([hash/2, hash_init/1, hash_update/2, hash_final/1]). -export([md4/1, md4_init/0, md4_update/2, md4_final/1]). -export([md5/1, md5_init/0, md5_update/2, md5_final/1]). @@ -116,7 +116,7 @@ srp_value_B, srp3_value_u, srp6_value_u, srp6a_multiplier, srp_client_secret, srp_server_secret, - info_lib]). + info_lib, algorithms]). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. -type dss_digest_type() :: 'none' | 'sha'. @@ -191,6 +191,8 @@ info() -> info_lib() -> ?nif_stub. +algorithms() -> ?nif_stub. + %% Crypto app version history: %% (no version): Driver implementation %% 2.0 : NIF implementation, requires OTP R14 -- cgit v1.2.3 From 45bbae42ef31a478487c8be19ddb44f34823fe57 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 27 Mar 2013 10:29:57 +0100 Subject: crypto: New SRP API Adjust API to better fit in with similar funtions in crypto --- lib/crypto/src/crypto.erl | 178 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 133 insertions(+), 45 deletions(-) (limited to 'lib/crypto/src') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index e8867236ac..1d0a9943c3 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -58,9 +58,8 @@ -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). -export([strong_rand_bytes/1, strong_rand_mpint/3]). -export([mod_exp/3, mod_exp_prime/3, mpint/1, erlint/1]). --export([srp_value_B/5]). --export([srp3_value_u/1, srp6_value_u/3, srp6a_multiplier/2]). --export([srp_client_secret/7, srp_server_secret/5]). +-export([srp_generate_key/4, srp_generate_key/3, + srp_generate_key/5, srp_compute_key/6, srp_compute_key/7, srp_compute_key/8]). %% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]). -export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). @@ -113,9 +112,7 @@ hash, hash_init, hash_update, hash_final, hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, - srp_value_B, - srp3_value_u, srp6_value_u, srp6a_multiplier, - srp_client_secret, srp_server_secret, + srp_generate_key, srp_compute_key, info_lib, algorithms]). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. @@ -801,7 +798,7 @@ mod_exp(Base, Exponent, Modulo) mod_exp(Base, Exponent, Modulo) -> mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4). --spec mod_exp_prime(binary(), binary(), binary()) -> binary(). +-spec mod_exp_prime(binary(), binary(), binary()) -> binary() | error. mod_exp_prime(Base, Exponent, Prime) -> case mod_exp_nif(Base, Exponent, Prime, 0) of <<0>> -> error; @@ -1077,49 +1074,130 @@ dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) -> dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. --spec srp_value_B(binary(), integer(), binary(), binary(), binary()) -> binary(). -srp_value_B(Multiplier, Verifier, Generator, Exponent, Prime) -> - srp_value_B_nif(srp_multiplier(Multiplier), Verifier, Generator, Exponent, Prime). +%%% SRP +-spec srp_generate_key(binary(), binary(), atom() | binary(), atom() | binary() ) -> {Public::binary(), Private::binary()}. +srp_generate_key(Verifier, Generator, Prime, Version) when is_binary(Verifier), + is_binary(Generator), + is_binary(Prime), + is_atom(Version) -> + Private = random_bytes(32), + server_srp_gen_key(Private, Verifier, Generator, Prime, Version); + +srp_generate_key(Generator, Prime, Version, Private) when is_binary(Generator), + is_binary(Prime), + is_atom(Version), + is_binary(Private) -> + client_srp_gen_key(Private, Generator, Prime). + +-spec srp_generate_key(binary(), binary(), binary(), atom(), binary()) -> {Public::binary(), Private::binary()}. +srp_generate_key(Verifier, Generator, Prime, Version, Private) when is_binary(Verifier), + is_binary(Generator), + is_binary(Prime), + is_atom(Version), + is_binary(Private) + -> + server_srp_gen_key(Private, Verifier, Generator, Prime, Version). + +-spec srp_generate_key(binary(), binary(), atom()) -> {Public::binary(), Private::binary()}. +srp_generate_key(Generator, Prime, Version) when is_binary(Generator), + is_binary(Prime), + is_atom(Version) -> + Private = random_bytes(32), + client_srp_gen_key(Private, Generator, Prime). + +-spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), atom()| binary(), atom() | binary() ) -> binary(). +srp_compute_key(DerivedKey, Prime, Generator, ClientPublic, ClientPrivate, ServerPublic, Version) when + is_binary(Prime), + is_binary(Generator), + is_binary(ClientPublic), + is_binary(ClientPrivate), + is_binary(ServerPublic), + is_atom(Version) -> + Multiplier = srp_multiplier(Version, Generator, Prime), + Scrambler = srp_scrambler(Version, ClientPublic, ServerPublic, Prime), + srp_client_secret_nif(ClientPrivate, Scrambler, ServerPublic, Multiplier, + Generator, DerivedKey, Prime); + +srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Version, Scrambler) when + is_binary(Verifier), + is_binary(Prime), + is_binary(ClientPublic), + is_binary(ServerPublic), + is_binary(ServerPrivate), + is_atom(Version), + is_binary(Scrambler) -> + srp_server_secret_nif(Verifier, ServerPrivate, Scrambler, ClientPublic, Prime). + +-spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), binary(), atom(), binary()) -> binary(). +srp_compute_key(DerivedKey, Prime, Generator, ClientPublic, ClientPrivate, + ServerPublic, Version, Scrambler) when is_binary(DerivedKey), + is_binary(Prime), + is_binary(Generator), + is_binary(ClientPublic), + is_binary(ClientPrivate), + is_binary(ServerPublic), + is_atom(Version), + is_binary(Scrambler) -> + Multiplier = srp_multiplier(Version, Generator, Prime), + srp_client_secret_nif(ClientPrivate, Scrambler, ServerPublic, Multiplier, + Generator, DerivedKey, Prime). + +-spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), atom()) -> binary(). +srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Version) when + is_binary(Verifier), + is_binary(Prime), + is_binary(ClientPublic), + is_binary(ServerPublic), + is_binary(ServerPrivate), + is_atom(Version) -> + Scrambler = srp_scrambler(Version, ClientPublic, ServerPublic, Prime), + srp_server_secret_nif(Verifier, ServerPrivate, Scrambler, ClientPublic, Prime). -srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. - --spec srp_client_secret(binary(), binary(), binary(), integer()|binary(), binary(), binary(), binary()) -> binary(). -srp_client_secret(A, U, B, Multiplier, Generator, Exponent, Prime) -> - srp_client_secret_nif(A, U, B, srp_multiplier(Multiplier), Generator, Exponent, Prime). +%% +%% LOCAL FUNCTIONS +%% -srp_client_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. +client_srp_gen_key(Private, Generator, Prime) -> + case mod_exp_prime(Generator, Private, Prime) of + error -> + error; + Public -> + {Public, Private} + end. --spec srp_server_secret(binary(), binary(), binary(), binary(), binary()) -> binary(). -srp_server_secret(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. +server_srp_gen_key(Private, Verifier, Generator, Prime, Version) -> + Multiplier = srp_multiplier(Version, Generator, Prime), + case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of + error -> + error; + Public -> + {Public, Private} + end. --spec srp6a_multiplier(binary(), binary()) -> binary(). -srp6a_multiplier(Generator, Prime) -> - %% k = SHA1(N | PAD(g)) +srp_multiplier('6a', Generator, Prime) -> + %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html C0 = sha_init(), C1 = sha_update(C0, Prime), C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)), - sha_final(C2). - --spec srp3_value_u(binary()) -> binary(). -srp3_value_u(B) -> + sha_final(C2); +srp_multiplier('6', _, _) -> + <<3/integer>>; +srp_multiplier('3', _, _) -> + <<1/integer>>. + +srp_scrambler(Version, ClientPublic, ServerPublic, Prime) when Version == '6'; Version == '6a'-> + %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html + PadLength = erlang:byte_size(Prime), + C0 = sha_init(), + C1 = sha_update(C0, srp_pad_to(PadLength, ClientPublic)), + C2 = sha_update(C1, srp_pad_to(PadLength, ServerPublic)), + sha_final(C2); +srp_scrambler('3', _, ServerPublic, _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. - <> = sha(B), + <> = sha(ServerPublic), U. --spec srp6_value_u(binary(), binary(), binary()) -> binary(). -srp6_value_u(A, B, Prime) -> - %% SHA1(PAD(A) | PAD(B)) - PadLength = erlang:byte_size(Prime), - C0 = sha_init(), - C1 = sha_update(C0, srp_pad_to(PadLength, A)), - C2 = sha_update(C1, srp_pad_to(PadLength, B)), - sha_final(C2). - -%% -%% LOCAL FUNCTIONS -%% - srp_pad_length(Width, Length) -> (Width - Length rem Width) rem Width. @@ -1129,10 +1207,11 @@ srp_pad_to(Width, Binary) -> N -> << 0:(N*8), Binary/binary>> end. -srp_multiplier(Multiplier) when is_binary(Multiplier) -> - Multiplier; -srp_multiplier(Multiplier) when is_integer(Multiplier) -> - int_to_bin_pos(Multiplier). +srp_server_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. + +srp_client_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. + +srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. %% large integer in a binary with 32bit length %% MP representaion (SSH2) @@ -1160,8 +1239,8 @@ mpint_pos(X) -> int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []); int_to_bin(X) -> int_to_bin_pos(X, []). -int_to_bin_pos(X) when X >= 0 -> - int_to_bin_pos(X, []). +%%int_to_bin_pos(X) when X >= 0 -> +%% int_to_bin_pos(X, []). int_to_bin_pos(0,Ds=[_|_]) -> list_to_binary(Ds); @@ -1187,3 +1266,12 @@ erlint(<>) -> mpint_to_bin(<>) -> Bin. + +random_bytes(N) -> + try strong_rand_bytes(N) of + RandBytes -> + RandBytes + catch + error:low_entropy -> + rand_bytes(N) + end. -- cgit v1.2.3