From 2702f65e834a65d05d82cebf77bc7385becbf3a7 Mon Sep 17 00:00:00 2001
From: Andreas Schultz
Date: Thu, 31 May 2012 13:08:03 +0200
Subject: crypto: Add rsa and dss hash signing support
---
lib/crypto/c_src/crypto.c | 139 +++++++++++++++++++++++++++++++++++++++
lib/crypto/src/crypto.erl | 30 +++++++--
lib/crypto/test/crypto_SUITE.erl | 63 +++++++++++++++++-
3 files changed, 227 insertions(+), 5 deletions(-)
(limited to 'lib')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 4be593e208..62e745db6c 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -168,6 +168,7 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM rsa_verify_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -175,7 +176,9 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM rsa_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM dss_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -256,6 +259,7 @@ static ErlNifFunc nif_funcs[] = {
{"mod_exp_nif", 3, mod_exp_nif},
{"dss_verify", 4, dss_verify},
{"rsa_verify_nif", 4, rsa_verify_nif},
+ {"rsa_verify_hash_nif", 4, rsa_verify_hash_nif},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
{"exor", 2, exor},
{"rc4_encrypt", 2, rc4_encrypt},
@@ -263,7 +267,9 @@ static ErlNifFunc nif_funcs[] = {
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
{"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
+ {"rsa_sign_hash_nif", 3, rsa_sign_hash_nif},
{"dss_sign_nif", 3, dss_sign_nif},
+ {"dss_sign_hash_nif", 3, dss_sign_hash_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
{"rsa_private_crypt", 4, rsa_private_crypt},
{"dh_generate_parameters_nif", 2, dh_generate_parameters_nif},
@@ -1327,6 +1333,46 @@ done:
return ret;
}
+static ERL_NIF_TERM rsa_verify_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Data, Signature, Key=[E,N]) */
+ ErlNifBinary data_bin, sign_bin;
+ ERL_NIF_TERM head, tail, ret;
+ int i, type;
+ RSA* rsa = RSA_new();
+
+ if (!enif_inspect_binary(env,argv[1],&data_bin)) {
+ ret = enif_make_badarg(env);
+ goto done;
+ }
+
+ if (argv[0] == atom_sha && data_bin.size == SHA_DIGEST_LENGTH) type = NID_sha1;
+ else if (argv[0] == atom_sha256 && data_bin.size == SHA256_DIGEST_LENGTH) type = NID_sha256;
+ else if (argv[0] == atom_sha512 && data_bin.size == SHA512_DIGEST_LENGTH) type = NID_sha512;
+ else if (argv[0] == atom_md5 && data_bin.size == MD5_DIGEST_LENGTH) type = NID_md5;
+ else {
+ ret = enif_make_badarg(env);
+ goto done;
+ }
+
+ if (!inspect_mpint(env, argv[2], &sign_bin)
+ || !enif_get_list_cell(env, argv[3], &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->n)
+ || !enif_is_empty_list(env, tail)) {
+
+ ret = enif_make_badarg(env);
+ }
+ else {
+ i = RSA_verify(type, data_bin.data, data_bin.size,
+ sign_bin.data+4, sign_bin.size-4, rsa);
+ ret = (i==1 ? atom_true : atom_false);
+ }
+done:
+ RSA_free(rsa);
+ return ret;
+}
+
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data, IsEncrypt) */
ErlNifBinary key_bin, ivec_bin, data_bin;
@@ -1530,6 +1576,52 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
}
+static ERL_NIF_TERM rsa_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type,Data,Key=[E,N,D]) */
+ ErlNifBinary data_bin, ret_bin;
+ ERL_NIF_TERM head, tail;
+ unsigned rsa_s_len;
+ RSA *rsa = RSA_new();
+ int i, type;
+
+ if (!enif_inspect_binary(env,argv[1],&data_bin))
+ goto badarg;
+
+ if (argv[0] == atom_sha && data_bin.size == SHA_DIGEST_LENGTH) type = NID_sha1;
+ else if (argv[0] == atom_sha256 && data_bin.size == SHA256_DIGEST_LENGTH) type = NID_sha256;
+ else if (argv[0] == atom_sha512 && data_bin.size == SHA512_DIGEST_LENGTH) type = NID_sha512;
+ else if (argv[0] == atom_md5 && data_bin.size == MD5_DIGEST_LENGTH) type = NID_md5;
+ else goto badarg;
+
+ if (!enif_get_list_cell(env, argv[2], &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->n)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &rsa->d)
+ || !enif_is_empty_list(env,tail)) {
+ badarg:
+ RSA_free(rsa);
+ return enif_make_badarg(env);
+ }
+ enif_alloc_binary(RSA_size(rsa), &ret_bin);
+ i = RSA_sign(type, data_bin.data, data_bin.size,
+ ret_bin.data, &rsa_s_len, rsa);
+ RSA_free(rsa);
+ if (i) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
+ if (rsa_s_len != data_bin.size) {
+ enif_realloc_binary(&ret_bin, rsa_s_len);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(ret_bin.data, rsa_s_len);
+ }
+ return enif_make_binary(env,&ret_bin);
+ }
+ else {
+ enif_release_binary(&ret_bin);
+ return atom_error;
+ }
+}
+
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (DigesType, Data, Key=[P,Q,G,PrivKey]) */
ErlNifBinary data_bin, ret_bin;
@@ -1579,6 +1671,53 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
}
+static ERL_NIF_TERM dss_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (DigesType, Data, Key=[P,Q,G,PrivKey]) */
+ ErlNifBinary data_bin, ret_bin;
+ ERL_NIF_TERM head, tail;
+ unsigned int dsa_s_len;
+ DSA* dsa = DSA_new();
+ int i, type;
+
+ if (!enif_inspect_binary(env,argv[1],&data_bin))
+ goto badarg;
+
+ if (argv[0] == atom_sha && data_bin.size == SHA_DIGEST_LENGTH) type = NID_sha1;
+ else if (argv[0] == atom_sha256 && data_bin.size == SHA256_DIGEST_LENGTH) type = NID_sha256;
+ else if (argv[0] == atom_sha512 && data_bin.size == SHA512_DIGEST_LENGTH) type = NID_sha512;
+ else if (argv[0] == atom_md5 && data_bin.size == MD5_DIGEST_LENGTH) type = NID_md5;
+ else goto badarg;
+
+ dsa->pub_key = NULL;
+ if (!enif_get_list_cell(env, argv[2], &head, &tail)
+ || !get_bn_from_mpint(env, head, &dsa->p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &dsa->q)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &dsa->g)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+ || !get_bn_from_mpint(env, head, &dsa->priv_key)
+ || !enif_is_empty_list(env,tail)) {
+ badarg:
+ DSA_free(dsa);
+ return enif_make_badarg(env);
+ }
+
+ enif_alloc_binary(DSA_size(dsa), &ret_bin);
+ i = DSA_sign(type, data_bin.data, data_bin.size,
+ ret_bin.data, &dsa_s_len, dsa);
+ DSA_free(dsa);
+ if (i) {
+ if (dsa_s_len != ret_bin.size) {
+ enif_realloc_binary(&ret_bin, dsa_s_len);
+ }
+ return enif_make_binary(env, &ret_bin);
+ }
+ else {
+ return atom_error;
+ }
+}
+
static int rsa_pad(ERL_NIF_TERM term, int* padding)
{
if (term == atom_rsa_pkcs1_padding) {
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index d7aac27825..f4f4e20b4d 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -43,8 +43,8 @@
-export([exor/2]).
-export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]).
-export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3, rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
--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]).
+-export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4, rsa_verify_hash/4]).
+-export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3, dss_sign_hash/3, rsa_sign_hash/3]).
-export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
-export([rsa_private_encrypt/3, rsa_public_decrypt/3]).
-export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]).
@@ -80,8 +80,8 @@
strong_rand_mpint,
rand_uniform,
mod_exp,
- dss_verify,dss_sign,
- rsa_verify,rsa_sign,
+ dss_verify,dss_sign,dss_sign_hash,
+ rsa_verify,rsa_verify_hash,rsa_sign,rsa_sign_hash,
rsa_public_encrypt,rsa_private_decrypt,
rsa_private_encrypt,rsa_public_decrypt,
dh_generate_key, dh_compute_key,
@@ -581,6 +581,8 @@ mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub.
-spec rsa_verify(binary(), binary(), [binary()]) -> boolean().
-spec rsa_verify(rsa_digest_type(), binary(), binary(), [binary()]) ->
boolean().
+-spec rsa_verify_hash(rsa_digest_type(), binary(), binary(), [binary()]) ->
+ boolean().
%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
dss_verify(Data,Signature,Key) ->
@@ -595,8 +597,14 @@ rsa_verify(Type, Data, Signature, Key) ->
notsup -> erlang:error(notsup);
Bool -> Bool
end.
+rsa_verify_hash(Type, Hash, Signature, Key) ->
+ case rsa_verify_hash_nif(Type, Hash, Signature, Key) of
+ notsup -> erlang:error(notsup);
+ Bool -> Bool
+ end.
rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
+rsa_verify_hash_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
%%
@@ -605,8 +613,10 @@ rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
-spec dss_sign(binary(), [binary()]) -> binary().
-spec dss_sign(dss_digest_type(), binary(), [binary()]) -> binary().
+-spec dss_sign_hash(dss_digest_type(), binary(), [binary()]) -> binary().
-spec rsa_sign(binary(), [binary()]) -> binary().
-spec rsa_sign(rsa_digest_type(), binary(), [binary()]) -> binary().
+-spec rsa_sign_hash(rsa_digest_type(), binary(), [binary()]) -> binary().
dss_sign(Data,Key) ->
dss_sign(sha,Data,Key).
@@ -615,8 +625,14 @@ dss_sign(Type, Data, Key) ->
error -> erlang:error(badkey, [Data, Key]);
Sign -> Sign
end.
+dss_sign_hash(Type, Hash, Key) ->
+ case dss_sign_hash_nif(Type,Hash,Key) of
+ error -> erlang:error(badkey, [Hash, Key]);
+ Sign -> Sign
+ end.
dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
+dss_sign_hash_nif(_Type,_Data,_Key) -> ?nif_stub.
%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
rsa_sign(Data,Key) ->
@@ -626,8 +642,14 @@ rsa_sign(Type, Data, Key) ->
error -> erlang:error(badkey, [Type,Data,Key]);
Sign -> Sign
end.
+rsa_sign_hash(Type, Hash, Key) ->
+ case rsa_sign_hash_nif(Type,Hash,Key) of
+ error -> erlang:error(badkey, [Type,Hash,Key]);
+ Sign -> Sign
+ end.
rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
+rsa_sign_hash_nif(_Type,_Data,_Key) -> ?nif_stub.
%%
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 627c966dfb..a399511de0 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -61,7 +61,9 @@
rsa_verify_test/1,
dsa_verify_test/1,
rsa_sign_test/1,
+ rsa_sign_hash_test/1,
dsa_sign_test/1,
+ dsa_sign_hash_test/1,
rsa_encrypt_decrypt/1,
dh/1,
exor_test/1,
@@ -88,7 +90,8 @@ groups() ->
aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb,
rand_uniform_test, strong_rand_test,
rsa_verify_test, dsa_verify_test, rsa_sign_test,
- dsa_sign_test, rsa_encrypt_decrypt, dh, exor_test,
+ rsa_sign_hash_test, dsa_sign_test, dsa_sign_hash_test,
+ rsa_encrypt_decrypt, dh, exor_test,
rc4_test, rc4_stream_test, mod_exp_test, blowfish_cfb64,
smp]}].
@@ -1207,6 +1210,33 @@ rsa_sign_test(Config) when is_list(Config) ->
ok.
+rsa_sign_hash_test(doc) ->
+ "rsa_sign_hash testing";
+rsa_sign_hash_test(suite) ->
+ [];
+rsa_sign_hash_test(Config) when is_list(Config) ->
+ PubEx = 65537,
+ PrivEx = 7531712708607620783801185371644749935066152052780368689827275932079815492940396744378735701395659435842364793962992309884847527234216715366607660219930945,
+ Mod = 7919488123861148172698919999061127847747888703039837999377650217570191053151807772962118671509138346758471459464133273114654252861270845708312601272799123,
+ Msg = <<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
+ "09812312908312378623487263487623412039812 huagasd">>,
+
+ PrivKey = [crypto:mpint(PubEx), crypto:mpint(Mod), crypto:mpint(PrivEx)],
+ PubKey = [crypto:mpint(PubEx), crypto:mpint(Mod)],
+ MD5 = crypto:md5(sized_binary(Msg)),
+ SHA = crypto:sha(sized_binary(Msg)),
+ ?line Sig1 = crypto:rsa_sign_hash(sha, SHA, PrivKey),
+ ?line m(crypto:rsa_verify_hash(sha, SHA, sized_binary(Sig1),PubKey), true),
+
+ ?line Sig2 = crypto:rsa_sign_hash(md5, MD5, PrivKey),
+ ?line m(crypto:rsa_verify_hash(md5, MD5, sized_binary(Sig2),PubKey), true),
+
+ ?line m(Sig1 =:= Sig2, false),
+ ?line m(crypto:rsa_verify_hash(md5, MD5, sized_binary(Sig1),PubKey), false),
+ ?line m(crypto:rsa_verify_hash(sha, SHA, sized_binary(Sig2),PubKey), false),
+
+ ok.
+
dsa_sign_test(doc) ->
"dsa_sign testing";
dsa_sign_test(suite) ->
@@ -1237,6 +1267,37 @@ dsa_sign_test(Config) when is_list(Config) ->
ok.
+dsa_sign_hash_test(doc) ->
+ "dsa_sign_hash testing";
+dsa_sign_hash_test(suite) ->
+ [];
+dsa_sign_hash_test(Config) when is_list(Config) ->
+ Msg = <<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
+ "09812312908312378623487263487623412039812 huagasd">>,
+ SHA = crypto:sha(sized_binary(Msg)),
+
+ PubKey = _Y = 25854665488880835237281628794585130313500176551981812527054397586638455298000483144002221850980183404910190346416063318160497344811383498859129095184158800144312512447497510551471331451396405348497845813002058423110442376886564659959543650802132345311573634832461635601376738282831340827591903548964194832978,
+ PrivKey = _X = 441502407453038284293378221372000880210588566361,
+ ParamP = 109799869232806890760655301608454668257695818999841877165019612946154359052535682480084145133201304812979481136659521529774182959764860329095546511521488413513097576425638476458000255392402120367876345280670101492199681798674053929238558140260669578407351853803102625390950534052428162468100618240968893110797,
+ ParamQ = 1349199015905534965792122312016505075413456283393,
+ ParamG = 18320614775012672475365915366944922415598782131828709277168615511695849821411624805195787607930033958243224786899641459701930253094446221381818858674389863050420226114787005820357372837321561754462061849169568607689530279303056075793886577588606958623645901271866346406773590024901668622321064384483571751669,
+
+ Params = [crypto:mpint(ParamP), crypto:mpint(ParamQ), crypto:mpint(ParamG)],
+ ?line Sig1 = crypto:dss_sign_hash(sha, SHA, Params ++ [crypto:mpint(PrivKey)]),
+
+ ?line m(crypto:dss_verify(none, SHA, sized_binary(Sig1),
+ Params ++ [crypto:mpint(PubKey)]), true),
+
+ ?line m(crypto:dss_verify(sized_binary(one_bit_wrong(Msg)), sized_binary(Sig1),
+ Params ++ [crypto:mpint(PubKey)]), false),
+
+ ?line m(crypto:dss_verify(sized_binary(Msg), sized_binary(one_bit_wrong(Sig1)),
+ Params ++ [crypto:mpint(PubKey)]), false),
+
+ %%?line Bad = crypto:dss_sign(sized_binary(Msg), [Params, crypto:mpint(PubKey)]),
+
+ ok.
+
rsa_encrypt_decrypt(doc) ->
["Test rsa_public_encrypt and rsa_private_decrypt functions."];
--
cgit v1.2.3
From 90167202a4ce3dc6d4822fad04c51cc35913d796 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Wed, 27 Jun 2012 15:35:26 +0200
Subject: crypto: Redo interface for rsa and dss hash signing
Replace _hash functions with {digest,_} argument
to existing sign/verify functions.
---
lib/crypto/c_src/crypto.c | 435 ++++++++++++++++++++-------------------
lib/crypto/doc/src/crypto.xml | 66 +++---
lib/crypto/src/crypto.erl | 73 +++----
lib/crypto/test/crypto_SUITE.erl | 14 +-
4 files changed, 292 insertions(+), 296 deletions(-)
(limited to 'lib')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 62e745db6c..25616410be 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -168,7 +168,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rsa_verify_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -176,9 +175,7 @@ static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rsa_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM dss_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -204,6 +201,7 @@ static void dyn_destroy_function(struct CRYPTO_dynlock_value *ptr,
#endif /* OPENSSL_THREADS */
/* helpers */
+static void init_digest_types(ErlNifEnv* env);
static void hmac_md5(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
unsigned char *hmacbuf);
@@ -259,7 +257,6 @@ static ErlNifFunc nif_funcs[] = {
{"mod_exp_nif", 3, mod_exp_nif},
{"dss_verify", 4, dss_verify},
{"rsa_verify_nif", 4, rsa_verify_nif},
- {"rsa_verify_hash_nif", 4, rsa_verify_hash_nif},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
{"exor", 2, exor},
{"rc4_encrypt", 2, rc4_encrypt},
@@ -267,9 +264,7 @@ static ErlNifFunc nif_funcs[] = {
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
{"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
- {"rsa_sign_hash_nif", 3, rsa_sign_hash_nif},
{"dss_sign_nif", 3, dss_sign_nif},
- {"dss_sign_hash_nif", 3, dss_sign_hash_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
{"rsa_private_crypt", 4, rsa_private_crypt},
{"dh_generate_parameters_nif", 2, dh_generate_parameters_nif},
@@ -326,6 +321,7 @@ static ERL_NIF_TERM atom_check_failed;
static ERL_NIF_TERM atom_unknown;
static ERL_NIF_TERM atom_none;
static ERL_NIF_TERM atom_notsup;
+static ERL_NIF_TERM atom_digest;
static int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info)
@@ -399,6 +395,9 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_unknown = enif_make_atom(env,"unknown");
atom_none = enif_make_atom(env,"none");
atom_notsup = enif_make_atom(env,"notsup");
+ atom_digest = enif_make_atom(env,"digest");
+
+ init_digest_types(env);
*priv_data = NULL;
library_refc++;
@@ -1214,14 +1213,43 @@ static int inspect_mpint(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin)
}
static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigestType,Data,Signature,Key=[P, Q, G, Y]) */
+{/* (DigestType|none, Data|{digest,Digest}, Signature,Key=[P, Q, G, Y]) */
ErlNifBinary data_bin, sign_bin;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
+ unsigned char* digest;
ERL_NIF_TERM head, tail;
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
DSA *dsa;
int i;
+ if (argv[0] == atom_sha) {
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != SHA_DIGEST_LENGTH) {
+
+ return enif_make_badarg(env);
+ }
+ digest = data_bin.data;
+ }
+ else {
+ if (!inspect_mpint(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ digest = hmacbuf;
+ }
+ }
+ else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
+ && data_bin.size == SHA_DIGEST_LENGTH) {
+ digest = data_bin.data;
+ }
+ else {
+ return enif_make_badarg(env);
+ }
+
if (!inspect_mpint(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_p)
@@ -1232,23 +1260,13 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa_y)
|| !enif_is_empty_list(env,tail)) {
- badarg:
+
if (dsa_p) BN_free(dsa_p);
if (dsa_q) BN_free(dsa_q);
if (dsa_g) BN_free(dsa_g);
if (dsa_y) BN_free(dsa_y);
return enif_make_badarg(env);
}
- if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
- }
- else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
- memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH);
- }
- else {
- goto badarg;
- }
dsa = DSA_new();
dsa->p = dsa_p;
@@ -1256,23 +1274,121 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
dsa->g = dsa_g;
dsa->priv_key = NULL;
dsa->pub_key = dsa_y;
- i = DSA_verify(0, hmacbuf, SHA_DIGEST_LENGTH,
+ i = DSA_verify(0, digest, SHA_DIGEST_LENGTH,
sign_bin.data+4, sign_bin.size-4, dsa);
DSA_free(dsa);
return(i > 0) ? atom_true : atom_false;
}
+
+static void md5_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ MD5(in, in_len, out);
+}
+static void sha1_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA1(in, in_len, out);
+}
+#ifdef HAVE_SHA256
+static void sha256_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA256(in, in_len, out);
+}
+#endif
+#ifdef HAVE_SHA384
+static void sha384_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA384(in, in_len, out);
+}
+#endif
+#ifdef HAVE_SHA512
+static void sha512_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA512(in, in_len, out);
+}
+#endif
+
+struct digest_type_t {
+ const char* type_str;
+ unsigned len; /* 0 if notsup */
+ int NID_type;
+ void (*funcp)(unsigned char* in, unsigned int in_len, unsigned char* out);
+ ERL_NIF_TERM type_atom;
+};
+
+struct digest_type_t digest_types[] =
+{
+ {"md5", MD5_DIGEST_LENGTH, NID_md5, md5_digest},
+ {"sha", SHA_DIGEST_LENGTH, NID_sha1, sha1_digest},
+ {"sha256",
+#ifdef HAVE_SHA256
+ SHA256_LEN, NID_sha256, sha256_digest
+#else
+ 0
+#endif
+ },
+ {"sha384",
+#ifdef HAVE_SHA384
+ SHA384_LEN, NID_sha384, sha384_digest
+#else
+ 0
+#endif
+ },
+ {"sha512",
+#ifdef HAVE_SHA512
+ SHA512_LEN, NID_sha512, sha512_digest
+#else
+ 0
+#endif
+ },
+ {NULL}
+};
+
+static void init_digest_types(ErlNifEnv* env)
+{
+ struct digest_type_t* p = digest_types;
+
+ for (p = digest_types; p->type_str; p++) {
+ p->type_atom = enif_make_atom(env, p->type_str);
+ }
+
+}
+
+static struct digest_type_t* get_digest_type(ERL_NIF_TERM type)
+{
+ struct digest_type_t* p = NULL;
+ for (p = digest_types; p->type_str; p++) {
+ if (type == p->type_atom) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data, Signature, Key=[E,N]) */
+{/* (Type, Data|{digest,Digest}, Signature, Key=[E,N]) */
ErlNifBinary data_bin, sign_bin;
unsigned char hmacbuf[SHA512_LEN];
ERL_NIF_TERM head, tail, ret;
int i;
- RSA* rsa = RSA_new();
+ RSA* rsa;
const ERL_NIF_TERM type = argv[0];
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
+ struct digest_type_t* digp = NULL;
+ unsigned char* digest = NULL;
+
+ digp = get_digest_type(type);
+ if (!digp) {
+ return enif_make_badarg(env);
+ }
+ if (!digp->len) {
+ return atom_notsup;
+ }
+
+ rsa = RSA_new();
- if (!inspect_mpint(env, argv[1], &data_bin)
- || !inspect_mpint(env, argv[2], &sign_bin)
+ if (!inspect_mpint(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_mpint(env, head, &rsa->e)
|| !enif_get_list_cell(env, tail, &head, &tail)
@@ -1280,99 +1396,38 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
|| !enif_is_empty_list(env, tail)) {
ret = enif_make_badarg(env);
+ goto done;
}
- else {
- if (type == atom_sha) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
- i = RSA_verify(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH,
- sign_bin.data+4, sign_bin.size-4, rsa);
- }
- else if (type == atom_sha256) {
- #ifdef HAVE_SHA256
- SHA256(data_bin.data+4, data_bin.size-4, hmacbuf);
- i = RSA_verify(NID_sha256, hmacbuf, SHA256_LEN,
- sign_bin.data+4, sign_bin.size-4, rsa);
- #else
- ret = atom_notsup;
- goto done;
- #endif
- }
- else if (type == atom_sha384) {
- #ifdef HAVE_SHA384
- SHA384(data_bin.data+4, data_bin.size-4, hmacbuf);
- i = RSA_verify(NID_sha384, hmacbuf, SHA384_LEN,
- sign_bin.data+4, sign_bin.size-4, rsa);
- #else
- ret = atom_notsup;
- goto done;
- #endif
- }
- else if (type == atom_sha512) {
- #ifdef HAVE_SHA512
- SHA512(data_bin.data+4, data_bin.size-4, hmacbuf);
- i = RSA_verify(NID_sha512, hmacbuf, SHA512_LEN,
- sign_bin.data+4, sign_bin.size-4, rsa);
- #else
- ret = atom_notsup;
- goto done;
- #endif
- }
- else if (type == atom_md5) {
- MD5(data_bin.data+4, data_bin.size-4, hmacbuf);
- i = RSA_verify(NID_md5, hmacbuf, MD5_DIGEST_LENGTH,
- sign_bin.data+4, sign_bin.size-4, rsa);
- }
- else {
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != digp->len) {
+
ret = enif_make_badarg(env);
goto done;
}
- ret = (i==1 ? atom_true : atom_false);
- }
-done:
- RSA_free(rsa);
- return ret;
-}
-
-static ERL_NIF_TERM rsa_verify_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data, Signature, Key=[E,N]) */
- ErlNifBinary data_bin, sign_bin;
- ERL_NIF_TERM head, tail, ret;
- int i, type;
- RSA* rsa = RSA_new();
-
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- ret = enif_make_badarg(env);
- goto done;
+ digest = data_bin.data;
+ }
+ else if (inspect_mpint(env, argv[1], &data_bin)) {
+ digest = hmacbuf;
+ digp->funcp(data_bin.data+4, data_bin.size-4, digest);
}
-
- if (argv[0] == atom_sha && data_bin.size == SHA_DIGEST_LENGTH) type = NID_sha1;
- else if (argv[0] == atom_sha256 && data_bin.size == SHA256_DIGEST_LENGTH) type = NID_sha256;
- else if (argv[0] == atom_sha512 && data_bin.size == SHA512_DIGEST_LENGTH) type = NID_sha512;
- else if (argv[0] == atom_md5 && data_bin.size == MD5_DIGEST_LENGTH) type = NID_md5;
else {
ret = enif_make_badarg(env);
goto done;
}
- if (!inspect_mpint(env, argv[2], &sign_bin)
- || !enif_get_list_cell(env, argv[3], &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->e)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->n)
- || !enif_is_empty_list(env, tail)) {
+ i = RSA_verify(digp->NID_type, digest, digp->len,
+ sign_bin.data+4, sign_bin.size-4, rsa);
+
+ ret = (i==1 ? atom_true : atom_false);
- ret = enif_make_badarg(env);
- }
- else {
- i = RSA_verify(type, data_bin.data, data_bin.size,
- sign_bin.data+4, sign_bin.size-4, rsa);
- ret = (i==1 ? atom_true : atom_false);
- }
done:
RSA_free(rsa);
return ret;
}
+
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data, IsEncrypt) */
ErlNifBinary key_bin, ivec_bin, data_bin;
@@ -1531,86 +1586,59 @@ static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
}
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type,Data,Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
+{/* (Type, Data|{digest,Digest}, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
ErlNifBinary data_bin, ret_bin;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
unsigned rsa_s_len;
- RSA *rsa = RSA_new();
- int i, is_sha;
-
- if (argv[0] == atom_sha) is_sha = 1;
- else if (argv[0] == atom_md5) is_sha = 0;
- else goto badarg;
+ RSA* rsa;
+ int i;
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
+ struct digest_type_t *digp;
+ unsigned char* digest;
- if (!inspect_mpint(env,argv[1],&data_bin)
- || !get_rsa_private_key(env, argv[2], rsa)) {
- badarg:
- RSA_free(rsa);
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- enif_alloc_binary(RSA_size(rsa), &ret_bin);
- if (is_sha) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(hmacbuf, SHA_DIGEST_LENGTH);
- i = RSA_sign(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH,
- ret_bin.data, &rsa_s_len, rsa);
- }
- else {
- MD5(data_bin.data+4, data_bin.size-4, hmacbuf);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(hmacbuf, MD5_DIGEST_LENGTH);
- i = RSA_sign(NID_md5, hmacbuf,MD5_DIGEST_LENGTH,
- ret_bin.data, &rsa_s_len, rsa);
+ if (!digp->len) {
+ return atom_notsup;
}
- RSA_free(rsa);
- if (i) {
- ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
- if (rsa_s_len != data_bin.size) {
- enif_realloc_binary(&ret_bin, rsa_s_len);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(ret_bin.data, rsa_s_len);
+
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != digp->len) {
+
+ return enif_make_badarg(env);
}
- return enif_make_binary(env,&ret_bin);
+ digest = data_bin.data;
}
else {
- enif_release_binary(&ret_bin);
- return atom_error;
+ if (!inspect_mpint(env,argv[1],&data_bin)) {
+ return enif_make_badarg(env);
+ }
+ digest = hmacbuf;
+ digp->funcp(data_bin.data+4, data_bin.size-4, digest);
}
-}
-static ERL_NIF_TERM rsa_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type,Data,Key=[E,N,D]) */
- ErlNifBinary data_bin, ret_bin;
- ERL_NIF_TERM head, tail;
- unsigned rsa_s_len;
- RSA *rsa = RSA_new();
- int i, type;
-
- if (!enif_inspect_binary(env,argv[1],&data_bin))
- goto badarg;
-
- if (argv[0] == atom_sha && data_bin.size == SHA_DIGEST_LENGTH) type = NID_sha1;
- else if (argv[0] == atom_sha256 && data_bin.size == SHA256_DIGEST_LENGTH) type = NID_sha256;
- else if (argv[0] == atom_sha512 && data_bin.size == SHA512_DIGEST_LENGTH) type = NID_sha512;
- else if (argv[0] == atom_md5 && data_bin.size == MD5_DIGEST_LENGTH) type = NID_md5;
- else goto badarg;
-
- if (!enif_get_list_cell(env, argv[2], &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->e)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->n)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &rsa->d)
- || !enif_is_empty_list(env,tail)) {
- badarg:
+ rsa = RSA_new();
+ if (!get_rsa_private_key(env, argv[2], rsa)) {
RSA_free(rsa);
return enif_make_badarg(env);
}
+
+
enif_alloc_binary(RSA_size(rsa), &ret_bin);
- i = RSA_sign(type, data_bin.data, data_bin.size,
+
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(digest, digp->len);
+ i = RSA_sign(digp->NID_type, digest, digp->len,
ret_bin.data, &rsa_s_len, rsa);
+
RSA_free(rsa);
if (i) {
ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
- if (rsa_s_len != data_bin.size) {
+ if (rsa_s_len != ret_bin.size) {
enif_realloc_binary(&ret_bin, rsa_s_len);
ERL_VALGRIND_ASSERT_MEM_DEFINED(ret_bin.data, rsa_s_len);
}
@@ -1622,71 +1650,48 @@ static ERL_NIF_TERM rsa_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
}
}
+
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigesType, Data, Key=[P,Q,G,PrivKey]) */
+{/* (DigesType|none, Data|{digest,Digest}, Key=[P,Q,G,PrivKey]) */
ErlNifBinary data_bin, ret_bin;
ERL_NIF_TERM head, tail;
unsigned char hmacbuf[SHA_DIGEST_LENGTH];
unsigned int dsa_s_len;
- DSA* dsa = DSA_new();
+ const ERL_NIF_TERM* tpl_terms;
+ int tpl_arity;
+ unsigned char* digest = NULL;
+ DSA* dsa;
int i;
- dsa->pub_key = NULL;
- if (!enif_get_list_cell(env, argv[2], &head, &tail)
- || !get_bn_from_mpint(env, head, &dsa->p)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &dsa->q)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &dsa->g)
- || !enif_get_list_cell(env, tail, &head, &tail)
- || !get_bn_from_mpint(env, head, &dsa->priv_key)
- || !enif_is_empty_list(env,tail)) {
- goto badarg;
- }
- if (argv[0] == atom_sha && inspect_mpint(env, argv[1], &data_bin)) {
- SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ if (argv[0] == atom_sha) {
+ if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
+ if (tpl_arity != 2 || tpl_terms[0] != atom_digest
+ || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
+ || data_bin.size != SHA_DIGEST_LENGTH) {
+
+ return enif_make_badarg(env);
+ }
+ digest = data_bin.data;
+ }
+ else {
+ if (!inspect_mpint(env,argv[1],&data_bin)) {
+ return enif_make_badarg(env);
+ }
+ SHA1(data_bin.data+4, data_bin.size-4, hmacbuf);
+ digest = hmacbuf;
+ }
}
- else if (argv[0] == atom_none && enif_inspect_binary(env,argv[1],&data_bin)
+ else if (argv[0] == atom_none
+ && enif_inspect_binary(env,argv[1],&data_bin)
&& data_bin.size == SHA_DIGEST_LENGTH) {
- memcpy(hmacbuf, data_bin.data, SHA_DIGEST_LENGTH);
- }
- else {
- badarg:
- DSA_free(dsa);
- return enif_make_badarg(env);
- }
- enif_alloc_binary(DSA_size(dsa), &ret_bin);
- i = DSA_sign(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH,
- ret_bin.data, &dsa_s_len, dsa);
- DSA_free(dsa);
- if (i) {
- if (dsa_s_len != ret_bin.size) {
- enif_realloc_binary(&ret_bin, dsa_s_len);
- }
- return enif_make_binary(env, &ret_bin);
+ digest = data_bin.data;
}
else {
- return atom_error;
+ return enif_make_badarg(env);
}
-}
-static ERL_NIF_TERM dss_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigesType, Data, Key=[P,Q,G,PrivKey]) */
- ErlNifBinary data_bin, ret_bin;
- ERL_NIF_TERM head, tail;
- unsigned int dsa_s_len;
- DSA* dsa = DSA_new();
- int i, type;
-
- if (!enif_inspect_binary(env,argv[1],&data_bin))
- goto badarg;
-
- if (argv[0] == atom_sha && data_bin.size == SHA_DIGEST_LENGTH) type = NID_sha1;
- else if (argv[0] == atom_sha256 && data_bin.size == SHA256_DIGEST_LENGTH) type = NID_sha256;
- else if (argv[0] == atom_sha512 && data_bin.size == SHA512_DIGEST_LENGTH) type = NID_sha512;
- else if (argv[0] == atom_md5 && data_bin.size == MD5_DIGEST_LENGTH) type = NID_md5;
- else goto badarg;
+ dsa = DSA_new();
dsa->pub_key = NULL;
if (!enif_get_list_cell(env, argv[2], &head, &tail)
@@ -1698,13 +1703,12 @@ static ERL_NIF_TERM dss_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_mpint(env, head, &dsa->priv_key)
|| !enif_is_empty_list(env,tail)) {
- badarg:
- DSA_free(dsa);
- return enif_make_badarg(env);
+ DSA_free(dsa);
+ return enif_make_badarg(env);
}
enif_alloc_binary(DSA_size(dsa), &ret_bin);
- i = DSA_sign(type, data_bin.data, data_bin.size,
+ i = DSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH,
ret_bin.data, &dsa_s_len, dsa);
DSA_free(dsa);
if (i) {
@@ -1718,6 +1722,7 @@ static ERL_NIF_TERM dss_sign_hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
}
}
+
static int rsa_pad(ERL_NIF_TERM term, int* padding)
{
if (term == atom_rsa_pkcs1_padding) {
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 19db6c9dd4..36f8bc6deb 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -865,11 +865,13 @@ Mpint() = >]]>
- rsa_sign(Data, Key) -> Signature
- rsa_sign(DigestType, Data, Key) -> Signature
+ rsa_sign(DataOrDigest, Key) -> Signature
+ rsa_sign(DigestType, DataOrDigest, Key) -> Signature
Sign the data using rsa with the given key.
+ DataOrDigest = Data | {digest,Digest}
Data = Mpint
+ Digest = binary()
Key = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]
E, N, D = Mpint
Where E is the public exponent, N is public modulus and
@@ -879,37 +881,40 @@ Mpint() = >]]>
the calculation faster. P1,P2 are first and second prime factors.
E1,E2 are first and second exponents. C is the CRT coefficient.
Terminology is taken from RFC 3447.
- DigestType = md5 | sha
+ DigestType = md5 | sha | sha256 | sha384 | sha512
The default DigestType is sha.
Mpint = binary()
Signature = binary()
- Calculates a DigestType digest of the Data
- and creates a RSA signature with the private key Key
- of the digest.
+ Creates a RSA signature with the private key Key
+ of a digest. The digest is either calculated as a
+ DigestType digest of Data or a precalculated
+ binary Digest.
- rsa_verify(Data, Signature, Key) -> Verified
- rsa_verify(DigestType, Data, Signature, Key) -> Verified
+ rsa_verify(DataOrDigest, Signature, Key) -> Verified
+ rsa_verify(DigestType, DataOrDigest, Signature, Key) -> Verified
Verify the digest and signature using rsa with given public key.
Verified = boolean()
+ DataOrDigest = Data | {digest|Digest}
Data, Signature = Mpint
+ Digest = binary()
Key = [E, N]
E, N = Mpint
Where E is the public exponent and N is public modulus.
DigestType = md5 | sha | sha256 | sha384 | sha512
- The default DigestType is sha.
+ The default DigestType is sha.
Mpint = binary()
- Calculates a DigestType digest of the Data
- and verifies that the digest matches the RSA signature using the
+
Verifies that a digest matches the RSA signature using the
signer's public key Key.
-
+ The digest is either calculated as a DigestType
+ digest of Data or a precalculated binary Digest.
May throw exception notsup in case the chosen DigestType
is not supported by the underlying OpenSSL implementation.
@@ -1022,45 +1027,52 @@ Mpint() = >]]>
- dss_sign(Data, Key) -> Signature
- dss_sign(DigestType, Data, Key) -> Signature
+ dss_sign(DataOrDigest, Key) -> Signature
+ dss_sign(DigestType, DataOrDigest, Key) -> Signature
Sign the data using dsa with given private key.
- DigestType = sha | none (default is sha)
- Data = Mpint | ShaDigest
+ DigestType = sha
+ DataOrDigest = Mpint | {digest,Digest}
Key = [P, Q, G, X]
P, Q, G, X = Mpint
Where P, Q and G are the dss
parameters and X is the private key.
- ShaDigest = binary() with length 20 bytes
+ Digest = binary() with length 20 bytes
Signature = binary()
- Creates a DSS signature with the private key Key of a digest.
- If DigestType is 'sha', the digest is calculated as SHA1 of Data.
- If DigestType is 'none', Data is the precalculated SHA1 digest.
+ Creates a DSS signature with the private key Key of
+ a digest. The digest is either calculated as a SHA1
+ digest of Data or a precalculated binary Digest.
+ A deprecated feature is having DigestType = 'none'
+ in which case DataOrDigest is a precalculated SHA1
+ digest.
- dss_verify(Data, Signature, Key) -> Verified
- dss_verify(DigestType, Data, Signature, Key) -> Verified
+ dss_verify(DataOrDigest, Signature, Key) -> Verified
+ dss_verify(DigestType, DataOrDigest, Signature, Key) -> Verified
Verify the data and signature using dsa with given public key.
Verified = boolean()
- DigestType = sha | none
+ DigestType = sha
+ DataOrDigest = Mpint | {digest,Digest}
Data = Mpint | ShaDigest
Signature = Mpint
Key = [P, Q, G, Y]
P, Q, G, Y = Mpint
Where P, Q and G are the dss
parameters and Y is the public key.
- ShaDigest = binary() with length 20 bytes
+ Digest = binary() with length 20 bytes
- Verifies that a digest matches the DSS signature using the public key Key.
- If DigestType is 'sha', the digest is calculated as SHA1 of Data.
- If DigestType is 'none', Data is the precalculated SHA1 digest.
+ Verifies that a digest matches the DSS signature using the
+ public key Key. The digest is either calculated as a SHA1
+ digest of Data or is a precalculated binary Digest.
+ A deprecated feature is having DigestType = 'none'
+ in which case DataOrDigest is a precalculated SHA1
+ digest binary.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index f4f4e20b4d..69ab51d11e 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -43,8 +43,8 @@
-export([exor/2]).
-export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]).
-export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3, rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
--export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4, rsa_verify_hash/4]).
--export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3, dss_sign_hash/3, rsa_sign_hash/3]).
+-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]).
-export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
-export([rsa_private_encrypt/3, rsa_public_decrypt/3]).
-export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]).
@@ -80,8 +80,8 @@
strong_rand_mpint,
rand_uniform,
mod_exp,
- dss_verify,dss_sign,dss_sign_hash,
- rsa_verify,rsa_verify_hash,rsa_sign,rsa_sign_hash,
+ 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,
@@ -97,6 +97,7 @@
-type rsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'.
-type dss_digest_type() :: 'none' | 'sha'.
+-type data_or_digest() :: binary() | {digest, binary()}.
-type crypto_integer() :: binary() | integer().
-define(nif_stub,nif_stub_error(?LINE)).
@@ -576,12 +577,10 @@ mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub.
%%
%% DSS, RSA - verify
%%
--spec dss_verify(binary(), binary(), [binary()]) -> boolean().
--spec dss_verify(dss_digest_type(), binary(), binary(), [binary()]) -> boolean().
--spec rsa_verify(binary(), binary(), [binary()]) -> boolean().
--spec rsa_verify(rsa_digest_type(), binary(), binary(), [binary()]) ->
- boolean().
--spec rsa_verify_hash(rsa_digest_type(), binary(), binary(), [binary()]) ->
+-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
@@ -592,64 +591,44 @@ dss_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub.
% Key = [E,N] E=PublicExponent N=PublicModulus
rsa_verify(Data,Signature,Key) ->
rsa_verify_nif(sha, Data,Signature,Key).
-rsa_verify(Type, Data, Signature, Key) ->
- case rsa_verify_nif(Type, Data, Signature, Key) of
+rsa_verify(Type, DataOrDigest, Signature, Key) ->
+ case rsa_verify_nif(Type, DataOrDigest, Signature, Key) of
notsup -> erlang:error(notsup);
Bool -> Bool
end.
-rsa_verify_hash(Type, Hash, Signature, Key) ->
- case rsa_verify_hash_nif(Type, Hash, Signature, Key) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end.
rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-rsa_verify_hash_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
%%
%% DSS, RSA - sign
%%
%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
--spec dss_sign(binary(), [binary()]) -> binary().
--spec dss_sign(dss_digest_type(), binary(), [binary()]) -> binary().
--spec dss_sign_hash(dss_digest_type(), binary(), [binary()]) -> binary().
--spec rsa_sign(binary(), [binary()]) -> binary().
--spec rsa_sign(rsa_digest_type(), binary(), [binary()]) -> binary().
--spec rsa_sign_hash(rsa_digest_type(), binary(), [binary()]) -> binary().
-
-dss_sign(Data,Key) ->
- dss_sign(sha,Data,Key).
-dss_sign(Type, Data, Key) ->
- case dss_sign_nif(Type,Data,Key) of
- error -> erlang:error(badkey, [Data, Key]);
- Sign -> Sign
- end.
-dss_sign_hash(Type, Hash, Key) ->
- case dss_sign_hash_nif(Type,Hash,Key) of
- error -> erlang:error(badkey, [Hash, Key]);
+-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, DataOrDigest, Key) ->
+ case dss_sign_nif(Type,DataOrDigest,Key) of
+ error -> erlang:error(badkey, [DataOrDigest, Key]);
Sign -> Sign
end.
dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-dss_sign_hash_nif(_Type,_Data,_Key) -> ?nif_stub.
%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
-rsa_sign(Data,Key) ->
- rsa_sign(sha, Data, Key).
-rsa_sign(Type, Data, Key) ->
- case rsa_sign_nif(Type,Data,Key) of
- error -> erlang:error(badkey, [Type,Data,Key]);
- Sign -> Sign
- end.
-rsa_sign_hash(Type, Hash, Key) ->
- case rsa_sign_hash_nif(Type,Hash,Key) of
- error -> erlang:error(badkey, [Type,Hash,Key]);
+rsa_sign(DataOrDigest,Key) ->
+ rsa_sign(sha, DataOrDigest, Key).
+rsa_sign(Type, DataOrDigest, Key) ->
+ case rsa_sign_nif(Type,DataOrDigest,Key) of
+ error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
Sign -> Sign
end.
rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-rsa_sign_hash_nif(_Type,_Data,_Key) -> ?nif_stub.
%%
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index a399511de0..6cc00d85ad 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1225,15 +1225,15 @@ rsa_sign_hash_test(Config) when is_list(Config) ->
PubKey = [crypto:mpint(PubEx), crypto:mpint(Mod)],
MD5 = crypto:md5(sized_binary(Msg)),
SHA = crypto:sha(sized_binary(Msg)),
- ?line Sig1 = crypto:rsa_sign_hash(sha, SHA, PrivKey),
- ?line m(crypto:rsa_verify_hash(sha, SHA, sized_binary(Sig1),PubKey), true),
+ ?line Sig1 = crypto:rsa_sign(sha, {digest,SHA}, PrivKey),
+ ?line m(crypto:rsa_verify(sha, {digest,SHA}, sized_binary(Sig1),PubKey), true),
- ?line Sig2 = crypto:rsa_sign_hash(md5, MD5, PrivKey),
- ?line m(crypto:rsa_verify_hash(md5, MD5, sized_binary(Sig2),PubKey), true),
+ ?line Sig2 = crypto:rsa_sign(md5, {digest,MD5}, PrivKey),
+ ?line m(crypto:rsa_verify(md5, {digest,MD5}, sized_binary(Sig2),PubKey), true),
?line m(Sig1 =:= Sig2, false),
- ?line m(crypto:rsa_verify_hash(md5, MD5, sized_binary(Sig1),PubKey), false),
- ?line m(crypto:rsa_verify_hash(sha, SHA, sized_binary(Sig2),PubKey), false),
+ ?line m(crypto:rsa_verify(md5, {digest,MD5}, sized_binary(Sig1),PubKey), false),
+ ?line m(crypto:rsa_verify(sha, {digest,SHA}, sized_binary(Sig2),PubKey), false),
ok.
@@ -1283,7 +1283,7 @@ dsa_sign_hash_test(Config) when is_list(Config) ->
ParamG = 18320614775012672475365915366944922415598782131828709277168615511695849821411624805195787607930033958243224786899641459701930253094446221381818858674389863050420226114787005820357372837321561754462061849169568607689530279303056075793886577588606958623645901271866346406773590024901668622321064384483571751669,
Params = [crypto:mpint(ParamP), crypto:mpint(ParamQ), crypto:mpint(ParamG)],
- ?line Sig1 = crypto:dss_sign_hash(sha, SHA, Params ++ [crypto:mpint(PrivKey)]),
+ ?line Sig1 = crypto:dss_sign(sha, {digest,SHA}, Params ++ [crypto:mpint(PrivKey)]),
?line m(crypto:dss_verify(none, SHA, sized_binary(Sig1),
Params ++ [crypto:mpint(PubKey)]), true),
--
cgit v1.2.3
From 95b2d97ecfeb4f1f254e4b7c16ea2ec8b4698dd0 Mon Sep 17 00:00:00 2001
From: Andreas Schultz
Date: Thu, 31 May 2012 13:08:16 +0200
Subject: public_key: Add rsa and dss hash signing support
---
lib/public_key/src/public_key.erl | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
(limited to 'lib')
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 9f1a0b3af5..1c5c6d1d2e 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -34,6 +34,7 @@
decrypt_private/2, decrypt_private/3,
encrypt_public/2, encrypt_public/3,
decrypt_public/2, decrypt_public/3,
+ sign_hash/3, verify_hash/4,
sign/3, verify/4,
pkix_sign/2, pkix_verify/2,
pkix_is_self_signed/1,
@@ -331,6 +332,25 @@ format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E,
privateExponent = D}) ->
[crypto:mpint(K) || K <- [E, N, D]].
+%%--------------------------------------------------------------------
+-spec sign_hash(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
+ rsa_private_key() |
+ dsa_private_key()) -> Signature :: binary().
+%%
+%% Description: Create a PKCS digital signature.
+%%--------------------------------------------------------------------
+sign_hash(Hash, DigestType, #'RSAPrivateKey'{modulus = N, publicExponent = E,
+ privateExponent = D})
+ when is_binary(Hash) ->
+ crypto:rsa_sign_hash(DigestType, Hash, [crypto:mpint(E),
+ crypto:mpint(N),
+ crypto:mpint(D)]);
+sign_hash(Hash, DigestType, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X})
+ when is_binary(Hash)->
+ crypto:dss_sign_hash(DigestType, Hash,
+ [crypto:mpint(P), crypto:mpint(Q),
+ crypto:mpint(G), crypto:mpint(X)]).
+
%%--------------------------------------------------------------------
-spec sign(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
rsa_private_key() |
@@ -358,6 +378,23 @@ sign(PlainText, sha, #'DSAPrivateKey'{p = P, q = Q, g = G, x = X})
[crypto:mpint(P), crypto:mpint(Q),
crypto:mpint(G), crypto:mpint(X)]).
+%%--------------------------------------------------------------------
+-spec verify_hash(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
+ Signature :: binary(), rsa_public_key()
+ | dsa_public_key()) -> boolean().
+%%
+%% Description: Verifies a PKCS digital signature.
+%%--------------------------------------------------------------------
+verify_hash(Hash, DigestType, Signature,
+ #'RSAPublicKey'{modulus = Mod, publicExponent = Exp})
+ when is_binary (Hash) and (DigestType == sha orelse
+ DigestType == sha256 orelse
+ DigestType == sha512 orelse
+ DigestType == md5) ->
+ crypto:rsa_verify_hash(DigestType, Hash,
+ sized_binary(Signature),
+ [crypto:mpint(Exp), crypto:mpint(Mod)]).
+
%%--------------------------------------------------------------------
-spec verify(PlainTextOrDigest :: binary(), rsa_digest_type() | dss_digest_type(),
Signature :: binary(), rsa_public_key()
--
cgit v1.2.3
From 3cde11a94c2761aa8980931f455734d8870446b3 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin
Date: Tue, 12 Jun 2012 16:26:35 +0200
Subject: public_key: Generalised API
---
lib/public_key/doc/src/public_key.xml | 12 ++--
lib/public_key/src/public_key.erl | 116 ++++++++++++++++------------------
2 files changed, 59 insertions(+), 69 deletions(-)
(limited to 'lib')
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 0b6673e826..0c9e0c9013 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -5,7 +5,7 @@