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/crypto')
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/crypto')
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 208f9ad3828313f6c659a501d53f5534ec1bdf2e Mon Sep 17 00:00:00 2001
From: Andreas Schultz
Date: Fri, 15 Jun 2012 17:34:28 +0200
Subject: crypto: Add SHA256 and SHA512 based MACs
---
lib/crypto/c_src/crypto.c | 144 ++++++++++++++++++++++++++++++++++++++-
lib/crypto/src/crypto.erl | 63 ++++++++++++++++-
lib/crypto/test/crypto_SUITE.erl | 49 +++++++++++--
3 files changed, 249 insertions(+), 7 deletions(-)
(limited to 'lib/crypto')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 25616410be..a1f2614f69 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2012. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -149,6 +149,8 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha256_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha512_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -208,6 +210,16 @@ static void hmac_md5(unsigned char *key, int klen,
static void hmac_sha1(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
unsigned char *hmacbuf);
+#ifdef HAVE_SHA256
+static void hmac_sha256(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
+#ifdef HAVE_SHA512
+static void hmac_sha512(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
static int library_refc = 0; /* number of users of this dynamic library */
@@ -235,6 +247,8 @@ static ErlNifFunc nif_funcs[] = {
{"md4_final", 1, md4_final},
{"md5_mac_n", 3, md5_mac_n},
{"sha_mac_n", 3, sha_mac_n},
+ {"sha256_mac_n_nif", 3, sha256_mac_n_nif},
+ {"sha512_mac_n_nif", 3, sha512_mac_n_nif},
{"hmac_init", 2, hmac_init},
{"hmac_update", 2, hmac_update},
{"hmac_final", 1, hmac_final},
@@ -292,6 +306,7 @@ ERL_NIF_INIT(crypto,nif_funcs,load,reload,upgrade,unload)
#define SHA384_LEN (384/8)
#define SHA512_LEN (512/8)
#define HMAC_INT_LEN 64
+#define HMAC_INT2_LEN 128
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
@@ -765,6 +780,50 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
+static ERL_NIF_TERM sha256_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA256
+ unsigned char hmacbuf[SHA256_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM sha512_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA512
+ unsigned char hmacbuf[SHA512_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key) */
ErlNifBinary key;
@@ -773,6 +832,8 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
const EVP_MD *md;
if (argv[0] == atom_sha) md = EVP_sha1();
+ else if (argv[0] == atom_sha256) md = EVP_sha256();
+ else if (argv[0] == atom_sha512) md = EVP_sha512();
else if (argv[0] == atom_md5) md = EVP_md5();
else if (argv[0] == atom_ripemd160) md = EVP_ripemd160();
else goto badarg;
@@ -2184,3 +2245,84 @@ static void hmac_sha1(unsigned char *key, int klen,
SHA1_Final((unsigned char *) hmacbuf, &ctx);
}
+#ifdef HAVE_SHA256
+static void hmac_sha256(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA256_CTX ctx;
+ char ipad[HMAC_INT_LEN];
+ char opad[HMAC_INT_LEN];
+ unsigned char nkey[SHA256_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT_LEN) {
+ SHA256(key, klen, nkey);
+ key = nkey;
+ klen = SHA256_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, ipad, HMAC_INT_LEN);
+ SHA256_Update(&ctx, dbuf, dlen);
+ SHA256_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA256_Init(&ctx);
+ SHA256_Update(&ctx, opad, HMAC_INT_LEN);
+ SHA256_Update(&ctx, hmacbuf, SHA256_DIGEST_LENGTH);
+ SHA256_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
+
+#ifdef HAVE_SHA512
+static void hmac_sha512(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA512_CTX ctx;
+ char ipad[HMAC_INT2_LEN];
+ char opad[HMAC_INT2_LEN];
+ unsigned char nkey[SHA512_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT2_LEN) {
+ SHA512(key, klen, nkey);
+ key = nkey;
+ klen = SHA512_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT2_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, ipad, HMAC_INT2_LEN);
+ SHA512_Update(&ctx, dbuf, dlen);
+ SHA512_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, opad, HMAC_INT2_LEN);
+ SHA512_Update(&ctx, hmacbuf, SHA512_DIGEST_LENGTH);
+ SHA512_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 69ab51d11e..0f14092f87 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -22,12 +22,14 @@
-module(crypto).
-export([start/0, stop/0, info/0, info_lib/0, version/0]).
+-export([hash/2]).
-export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
-export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]).
+-export([sha256_mac/2, sha256_mac_96/2, sha512_mac/2, sha512_mac/3, sha512_mac_96/2]).
-export([hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
-export([des_ecb_encrypt/2, des_ecb_decrypt/2]).
@@ -68,6 +70,8 @@
sha512, sha512_init, sha512_update, sha512_final,
md5_mac, md5_mac_96,
sha_mac, sha_mac_96,
+ sha256_mac, sha256_mac_96,
+ sha512_mac, sha512_mac_96,
sha_mac_init, sha_mac_update, sha_mac_final,
des_cbc_encrypt, des_cbc_decrypt,
des_cfb_encrypt, des_cfb_decrypt,
@@ -172,7 +176,7 @@ info_lib() -> ?nif_stub.
%% (no version): Driver implementation
%% 2.0 : NIF implementation, requires OTP R14
version() -> ?CRYPTO_VSN.
-
+
%% Below Key and Data are binaries or IO-lists. IVec is a binary.
%% Output is always a binary. Context is a binary.
@@ -180,6 +184,15 @@ version() -> ?CRYPTO_VSN.
%% MESSAGE DIGESTS
%%
+-spec hash(_, iodata()) -> binary().
+hash(md5, Data) -> md5(Data);
+hash(md4, Data) -> md4(Data);
+hash(sha, Data) -> sha(Data);
+hash(sha1, Data) -> sha(Data);
+hash(sha256, Data) -> sha256(Data);
+hash(sha512, Data) -> sha512(Data).
+
+
%%
%% MD5
%%
@@ -336,6 +349,52 @@ sha_mac_96(Key, Data) ->
sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
+%%
+%% SHA256_MAC
+%%
+-spec sha256_mac(iodata(), iodata()) -> binary().
+-spec sha256_mac_96(iodata(), iodata()) -> binary().
+
+sha256_mac(Key, Data) ->
+ sha256_mac_n(Key,Data,32).
+
+sha256_mac(Key, Data, Size) ->
+ sha256_mac_n(Key, Data, Size).
+
+sha256_mac_96(Key, Data) ->
+ sha256_mac_n(Key,Data,12).
+
+sha256_mac_n(Key, Data, MacSz) ->
+ case sha256_mac_n_nif(Key, Data, MacSz) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha256_mac_n_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+
+%%
+%% SHA512_MAC
+%%
+-spec sha512_mac(iodata(), iodata()) -> binary().
+-spec sha512_mac_96(iodata(), iodata()) -> binary().
+
+sha512_mac(Key, Data) ->
+ sha512_mac_n(Key,Data,64).
+
+sha512_mac(Key, Data, Size) ->
+ sha512_mac_n(Key, Data, Size).
+
+sha512_mac_96(Key, Data) ->
+ sha512_mac_n(Key,Data,12).
+
+sha512_mac_n(Key, Data, MacSz) ->
+ case sha512_mac_n_nif(Key, Data, MacSz) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha512_mac_n_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+
%%
%% CRYPTO FUNCTIONS
%%
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 6cc00d85ad..01cdf9f001 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -33,6 +33,8 @@
sha_update/1,
hmac_update_sha/1,
hmac_update_sha_n/1,
+ hmac_update_sha256/1,
+ hmac_update_sha512/1,
hmac_update_md5/1,
hmac_update_md5_io/1,
hmac_update_md5_n/1,
@@ -84,8 +86,8 @@ groups() ->
{rest, [],
[md5, md5_update, md4, md4_update, md5_mac,
md5_mac_io, sha, sha_update,
- hmac_update_sha, hmac_update_sha_n, hmac_update_md5_n,
- hmac_update_md5_io, hmac_update_md5,
+ hmac_update_sha, hmac_update_sha_n, hmac_update_sha256, hmac_update_sha512,
+ hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5,
des_cbc, aes_cfb, aes_cbc,
aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb,
rand_uniform_test, strong_rand_test,
@@ -338,6 +340,44 @@ hmac_update_sha(Config) when is_list(Config) ->
?line Mac = crypto:hmac_final(Ctx3),
?line Exp = crypto:sha_mac(Key, lists:flatten([Data, Data2])),
?line m(Exp, Mac).
+
+hmac_update_sha256(doc) ->
+ ["Generate an SHA256 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:sha256_mac." ];
+hmac_update_sha256(suite) ->
+ [];
+hmac_update_sha256(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("00010203101112132021222330313233"
+ "04050607141516172425262734353637"
+ "08090a0b18191a1b28292a2b38393a3b"
+ "0c0d0e0f1c1d1e1f2c2d2e2f3c3d3e3f"),
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(sha256, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final(Ctx3),
+ ?line Exp = crypto:sha256_mac(Key, lists:flatten([Data, Data2])),
+ ?line m(Exp, Mac).
+
+hmac_update_sha512(doc) ->
+ ["Generate an SHA512 HMAC using hmac_init, hmac_update, and hmac_final. "
+ "Expected values for examples are generated using crypto:sha512_mac." ];
+hmac_update_sha512(suite) ->
+ [];
+hmac_update_sha512(Config) when is_list(Config) ->
+ ?line Key = hexstr2bin("00010203101112132021222330313233"
+ "04050607141516172425262734353637"
+ "08090a0b18191a1b28292a2b38393a3b"
+ "0c0d0e0f1c1d1e1f2c2d2e2f3c3d3e3f"),
+ ?line Data = "Sampl",
+ ?line Data2 = "e #1",
+ ?line Ctx = crypto:hmac_init(sha512, Key),
+ ?line Ctx2 = crypto:hmac_update(Ctx, Data),
+ ?line Ctx3 = crypto:hmac_update(Ctx2, Data2),
+ ?line Mac = crypto:hmac_final(Ctx3),
+ ?line Exp = crypto:sha512_mac(Key, lists:flatten([Data, Data2])),
+ ?line m(Exp, Mac).
hmac_update_md5(doc) ->
["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. "
@@ -1482,7 +1522,8 @@ worker_loop(N, Config) ->
Funcs = { md5, md5_update, md5_mac, md5_mac_io, sha, sha_update, des_cbc,
aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, strong_rand_test,
rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test,
- hmac_update_md5, hmac_update_sha, aes_ctr_stream },
+ hmac_update_md5, hmac_update_sha, hmac_update_sha256, hmac_update_sha512,
+ aes_ctr_stream },
F = element(random:uniform(size(Funcs)),Funcs),
%%io:format("worker ~p calling ~p\n",[self(),F]),
--
cgit v1.2.3
From 807fc6ec56e3e7a65d9de5884cf6ac9927e5c1aa Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Wed, 27 Jun 2012 20:53:34 +0200
Subject: crypto: Cleanup code for sha256 and sha512
---
lib/crypto/c_src/crypto.c | 16 ++++++++++------
lib/crypto/src/crypto.erl | 35 +++++++++++++----------------------
2 files changed, 23 insertions(+), 28 deletions(-)
(limited to 'lib/crypto')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index a1f2614f69..3b412e3c1b 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -149,8 +149,8 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -247,8 +247,8 @@ static ErlNifFunc nif_funcs[] = {
{"md4_final", 1, md4_final},
{"md5_mac_n", 3, md5_mac_n},
{"sha_mac_n", 3, sha_mac_n},
- {"sha256_mac_n_nif", 3, sha256_mac_n_nif},
- {"sha512_mac_n_nif", 3, sha512_mac_n_nif},
+ {"sha256_mac_nif", 3, sha256_mac_nif},
+ {"sha512_mac_nif", 3, sha512_mac_nif},
{"hmac_init", 2, hmac_init},
{"hmac_update", 2, hmac_update},
{"hmac_final", 1, hmac_final},
@@ -780,7 +780,7 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
-static ERL_NIF_TERM sha256_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Data, MacSize) */
#ifdef HAVE_SHA256
unsigned char hmacbuf[SHA256_DIGEST_LENGTH];
@@ -802,7 +802,7 @@ static ERL_NIF_TERM sha256_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
#endif
}
-static ERL_NIF_TERM sha512_mac_n_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Data, MacSize) */
#ifdef HAVE_SHA512
unsigned char hmacbuf[SHA512_DIGEST_LENGTH];
@@ -832,8 +832,12 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
const EVP_MD *md;
if (argv[0] == atom_sha) md = EVP_sha1();
+#ifdef HAVE_SHA256
else if (argv[0] == atom_sha256) md = EVP_sha256();
+#endif
+#ifdef HAVE_SHA512
else if (argv[0] == atom_sha512) md = EVP_sha512();
+#endif
else if (argv[0] == atom_md5) md = EVP_md5();
else if (argv[0] == atom_ripemd160) md = EVP_ripemd160();
else goto badarg;
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 0f14092f87..cb1173f6be 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -29,7 +29,8 @@
-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]).
--export([sha256_mac/2, sha256_mac_96/2, sha512_mac/2, sha512_mac/3, sha512_mac_96/2]).
+-export([sha256_mac/2, sha256_mac/3]).
+-export([sha512_mac/2, sha512_mac/3]).
-export([hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
-export([des_ecb_encrypt/2, des_ecb_decrypt/2]).
@@ -70,8 +71,7 @@
sha512, sha512_init, sha512_update, sha512_final,
md5_mac, md5_mac_96,
sha_mac, sha_mac_96,
- sha256_mac, sha256_mac_96,
- sha512_mac, sha512_mac_96,
+ sha256_mac, sha512_mac,
sha_mac_init, sha_mac_update, sha_mac_final,
des_cbc_encrypt, des_cbc_decrypt,
des_cfb_encrypt, des_cfb_decrypt,
@@ -353,47 +353,38 @@ sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
%% SHA256_MAC
%%
-spec sha256_mac(iodata(), iodata()) -> binary().
--spec sha256_mac_96(iodata(), iodata()) -> binary().
sha256_mac(Key, Data) ->
- sha256_mac_n(Key,Data,32).
+ sha256_mac(Key, Data, 256 div 8).
sha256_mac(Key, Data, Size) ->
- sha256_mac_n(Key, Data, Size).
+ case sha256_mac_nif(Key, Data, Size) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
-sha256_mac_96(Key, Data) ->
- sha256_mac_n(Key,Data,12).
+sha256_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-sha256_mac_n(Key, Data, MacSz) ->
- case sha256_mac_n_nif(Key, Data, MacSz) of
notsup -> erlang:error(notsup);
Bin -> Bin
end.
-sha256_mac_n_nif(_Key,_Data,_MacSz) -> ?nif_stub.
%%
%% SHA512_MAC
%%
-spec sha512_mac(iodata(), iodata()) -> binary().
--spec sha512_mac_96(iodata(), iodata()) -> binary().
sha512_mac(Key, Data) ->
- sha512_mac_n(Key,Data,64).
-
-sha512_mac(Key, Data, Size) ->
- sha512_mac_n(Key, Data, Size).
-
-sha512_mac_96(Key, Data) ->
- sha512_mac_n(Key,Data,12).
+ sha512_mac(Key, Data, 512 div 8).
-sha512_mac_n(Key, Data, MacSz) ->
- case sha512_mac_n_nif(Key, Data, MacSz) of
+sha512_mac(Key, Data, MacSz) ->
+ case sha512_mac_nif(Key, Data, MacSz) of
notsup -> erlang:error(notsup);
Bin -> Bin
end.
-sha512_mac_n_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
%%
%% CRYPTO FUNCTIONS
--
cgit v1.2.3
From 7553817a73f8409a789496964a5292627002e785 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Wed, 27 Jun 2012 20:55:04 +0200
Subject: crypto: Add sha384
---
lib/crypto/c_src/crypto.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++
lib/crypto/src/crypto.erl | 51 ++++++++++++++++-
2 files changed, 193 insertions(+), 1 deletion(-)
(limited to 'lib/crypto')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 3b412e3c1b..2ae34c9741 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -139,6 +139,10 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -150,6 +154,7 @@ static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -215,6 +220,11 @@ static void hmac_sha256(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
unsigned char *hmacbuf);
#endif
+#ifdef HAVE_SHA384
+static void hmac_sha384(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
#ifdef HAVE_SHA512
static void hmac_sha512(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
@@ -237,6 +247,10 @@ static ErlNifFunc nif_funcs[] = {
{"sha256_init_nif", 0, sha256_init_nif},
{"sha256_update_nif", 2, sha256_update_nif},
{"sha256_final_nif", 1, sha256_final_nif},
+ {"sha384_nif", 1, sha384_nif},
+ {"sha384_init_nif", 0, sha384_init_nif},
+ {"sha384_update_nif", 2, sha384_update_nif},
+ {"sha384_final_nif", 1, sha384_final_nif},
{"sha512_nif", 1, sha512_nif},
{"sha512_init_nif", 0, sha512_init_nif},
{"sha512_update_nif", 2, sha512_update_nif},
@@ -248,6 +262,7 @@ static ErlNifFunc nif_funcs[] = {
{"md5_mac_n", 3, md5_mac_n},
{"sha_mac_n", 3, sha_mac_n},
{"sha256_mac_nif", 3, sha256_mac_nif},
+ {"sha384_mac_nif", 3, sha384_mac_nif},
{"sha512_mac_nif", 3, sha512_mac_nif},
{"hmac_init", 2, hmac_init},
{"hmac_update", 2, hmac_update},
@@ -638,6 +653,67 @@ static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
#endif
}
+static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Data) */
+#ifdef HAVE_SHA384
+ ErlNifBinary ibin;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+ return enif_make_badarg(env);
+ }
+ SHA384((unsigned char *) ibin.data, ibin.size,
+ enif_make_new_binary(env,SHA384_LEN, &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAVE_SHA384
+ ERL_NIF_TERM ret;
+ SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+#ifdef HAVE_SHA384
+ SHA512_CTX* new_ctx;
+ ErlNifBinary ctx_bin, data_bin;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
+ memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
+ SHA384_Update(new_ctx, data_bin.data, data_bin.size);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) */
+#ifdef HAVE_SHA384
+ ErlNifBinary ctx_bin;
+ SHA512_CTX ctx_clone;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
+ SHA384_Final(enif_make_new_binary(env, SHA384_LEN, &ret), &ctx_clone);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data) */
#ifdef HAVE_SHA512
@@ -802,6 +878,29 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
#endif
}
+static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA384
+ unsigned char hmacbuf[SHA384_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
+
static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Data, MacSize) */
#ifdef HAVE_SHA512
@@ -835,6 +934,9 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
#ifdef HAVE_SHA256
else if (argv[0] == atom_sha256) md = EVP_sha256();
#endif
+#ifdef HAVE_SHA384
+ else if (argv[0] == atom_sha384) md = EVP_sha384();
+#endif
#ifdef HAVE_SHA512
else if (argv[0] == atom_sha512) md = EVP_sha512();
#endif
@@ -2290,6 +2392,47 @@ static void hmac_sha256(unsigned char *key, int klen,
}
#endif
+#ifdef HAVE_SHA384
+static void hmac_sha384(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA512_CTX ctx;
+ char ipad[HMAC_INT_LEN];
+ char opad[HMAC_INT_LEN];
+ unsigned char nkey[SHA384_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT_LEN) {
+ SHA384(key, klen, nkey);
+ key = nkey;
+ klen = SHA384_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA384_Init(&ctx);
+ SHA384_Update(&ctx, ipad, HMAC_INT_LEN);
+ SHA384_Update(&ctx, dbuf, dlen);
+ SHA384_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA384_Init(&ctx);
+ SHA384_Update(&ctx, opad, HMAC_INT_LEN);
+ SHA384_Update(&ctx, hmacbuf, SHA384_DIGEST_LENGTH);
+ SHA384_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
+
#ifdef HAVE_SHA512
static void hmac_sha512(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index cb1173f6be..177ccfeef7 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -27,9 +27,11 @@
-export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
+-export([sha384/1, sha384_init/0, sha384_update/2, sha384_final/1]).
-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]).
-export([sha256_mac/2, sha256_mac/3]).
+-export([sha384_mac/2, sha384_mac/3]).
-export([sha512_mac/2, sha512_mac/3]).
-export([hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
@@ -68,10 +70,11 @@
md5, md5_init, md5_update, md5_final,
sha, sha_init, sha_update, sha_final,
sha256, sha256_init, sha256_update, sha256_final,
+ sha384, sha384_init, sha384_update, sha384_final,
sha512, sha512_init, sha512_update, sha512_final,
md5_mac, md5_mac_96,
sha_mac, sha_mac_96,
- sha256_mac, sha512_mac,
+ sha256_mac, sha384_mac, sha512_mac,
sha_mac_init, sha_mac_update, sha_mac_final,
des_cbc_encrypt, des_cbc_decrypt,
des_cfb_encrypt, des_cfb_decrypt,
@@ -190,6 +193,7 @@ hash(md4, Data) -> md4(Data);
hash(sha, Data) -> sha(Data);
hash(sha1, Data) -> sha(Data);
hash(sha256, Data) -> sha256(Data);
+hash(sha384, Data) -> sha384(Data);
hash(sha512, Data) -> sha512(Data).
@@ -267,6 +271,40 @@ sha256_init_nif() -> ?nif_stub.
sha256_update_nif(_Context, _Data) -> ?nif_stub.
sha256_final_nif(_Context) -> ?nif_stub.
+%
+%% SHA384
+%%
+-spec sha384(iodata()) -> binary().
+-spec sha384_init() -> binary().
+-spec sha384_update(binary(), iodata()) -> binary().
+-spec sha384_final(binary()) -> binary().
+
+sha384(Data) ->
+ case sha384_nif(Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha384_init() ->
+ case sha384_init_nif() of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha384_update(Context, Data) ->
+ case sha384_update_nif(Context, Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha384_final(Context) ->
+ case sha384_final_nif(Context) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha384_nif(_Data) -> ?nif_stub.
+sha384_init_nif() -> ?nif_stub.
+sha384_update_nif(_Context, _Data) -> ?nif_stub.
+sha384_final_nif(_Context) -> ?nif_stub.
+
%
%% SHA512
%%
@@ -365,10 +403,21 @@ sha256_mac(Key, Data, Size) ->
sha256_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+%%
+%% SHA384_MAC
+%%
+-spec sha384_mac(iodata(), iodata()) -> binary().
+
+sha384_mac(Key, Data) ->
+ sha384_mac(Key, Data, 384 div 8).
+
+sha384_mac(Key, Data, Size) ->
+ case sha384_mac_nif(Key, Data, Size) of
notsup -> erlang:error(notsup);
Bin -> Bin
end.
+sha384_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
%%
%% SHA512_MAC
--
cgit v1.2.3
From 29ecf2ad4b046b6b76b9cefb18fcc1d635a06037 Mon Sep 17 00:00:00 2001
From: Andreas Schultz
Date: Thu, 19 Jul 2012 12:12:17 +0200
Subject: crypto: fix hmac_sha384 and add hmac test cases from RFC-4231
---
lib/crypto/c_src/crypto.c | 12 +--
lib/crypto/test/crypto_SUITE.erl | 214 +++++++++++++++++++++++++++++++++++++++
2 files changed, 220 insertions(+), 6 deletions(-)
(limited to 'lib/crypto')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 2ae34c9741..c64ad2b82d 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -2398,13 +2398,13 @@ static void hmac_sha384(unsigned char *key, int klen,
unsigned char *hmacbuf)
{
SHA512_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
+ char ipad[HMAC_INT2_LEN];
+ char opad[HMAC_INT2_LEN];
unsigned char nkey[SHA384_DIGEST_LENGTH];
int i;
/* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
+ if (klen > HMAC_INT2_LEN) {
SHA384(key, klen, nkey);
key = nkey;
klen = SHA384_DIGEST_LENGTH;
@@ -2415,19 +2415,19 @@ static void hmac_sha384(unsigned char *key, int klen,
memcpy(ipad, key, klen);
memcpy(opad, key, klen);
- for (i = 0; i < HMAC_INT_LEN; i++) {
+ for (i = 0; i < HMAC_INT2_LEN; i++) {
ipad[i] ^= HMAC_IPAD;
opad[i] ^= HMAC_OPAD;
}
/* inner SHA */
SHA384_Init(&ctx);
- SHA384_Update(&ctx, ipad, HMAC_INT_LEN);
+ SHA384_Update(&ctx, ipad, HMAC_INT2_LEN);
SHA384_Update(&ctx, dbuf, dlen);
SHA384_Final((unsigned char *) hmacbuf, &ctx);
/* outer SHA */
SHA384_Init(&ctx);
- SHA384_Update(&ctx, opad, HMAC_INT_LEN);
+ SHA384_Update(&ctx, opad, HMAC_INT2_LEN);
SHA384_Update(&ctx, hmacbuf, SHA384_DIGEST_LENGTH);
SHA384_Final((unsigned char *) hmacbuf, &ctx);
}
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 01cdf9f001..a21b74d5ae 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -38,6 +38,7 @@
hmac_update_md5/1,
hmac_update_md5_io/1,
hmac_update_md5_n/1,
+ hmac_rfc4231/1,
sha256/1,
sha256_update/1,
sha512/1,
@@ -88,6 +89,7 @@ groups() ->
md5_mac_io, sha, sha_update,
hmac_update_sha, hmac_update_sha_n, hmac_update_sha256, hmac_update_sha512,
hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5,
+ hmac_rfc4231,
des_cbc, aes_cfb, aes_cbc,
aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb,
rand_uniform_test, strong_rand_test,
@@ -397,7 +399,218 @@ hmac_update_md5(Config) when is_list(Config) ->
?line Mac2 = crypto:hmac_final(CtxD),
?line Exp2 = crypto:md5_mac(Key2, lists:flatten([Long1, Long2, Long3])),
?line m(Exp2, Mac2).
+
+hmac_rfc4231(doc) ->
+ ["Generate an HMAC using crypto:shaXXX_mac and hmac_init, hmac_update, and hmac_final. "
+ "Testvectors are take from RFC4231." ];
+hmac_rfc4231(suite) ->
+ [];
+hmac_rfc4231(Config) when is_list(Config) ->
+ %% Test Case 1
+ Case1Key = binary:copy(<<16#0b>>, 20),
+ Case1Data = <<"Hi There">>,
+ Case1Exp256 = hexstr2bin("b0344c61d8db38535ca8afceaf0bf12b"
+ "881dc200c9833da726e9376c2e32cff7"),
+ Case1Exp384 = hexstr2bin("afd03944d84895626b0825f4ab46907f"
+ "15f9dadbe4101ec682aa034c7cebc59c"
+ "faea9ea9076ede7f4af152e8b2fa9cb6"),
+ Case1Exp512 = hexstr2bin("87aa7cdea5ef619d4ff0b4241a1d6cb0"
+ "2379f4e2ce4ec2787ad0b30545e17cde"
+ "daa833b7d6b8a702038b274eaea3f4e4"
+ "be9d914eeb61f1702e696c203a126854"),
+
+ ?line Case1Ctx256 = crypto:hmac_init(sha256, Case1Key),
+ ?line Case1Ctx256_2 = crypto:hmac_update(Case1Ctx256, Case1Data),
+ ?line Case1Mac256_1 = crypto:hmac_final(Case1Ctx256_2),
+ ?line Case1Mac256_2 = crypto:sha256_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp256, Case1Mac256_1),
+ ?line m(Case1Exp256, Case1Mac256_2),
+
+ ?line Case1Ctx384 = crypto:hmac_init(sha384, Case1Key),
+ ?line Case1Ctx384_2 = crypto:hmac_update(Case1Ctx384, Case1Data),
+ ?line Case1Mac384_1 = crypto:hmac_final(Case1Ctx384_2),
+ ?line Case1Mac384_2 = crypto:sha384_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp384, Case1Mac384_1),
+ ?line m(Case1Exp384, Case1Mac384_2),
+
+ ?line Case1Ctx512 = crypto:hmac_init(sha512, Case1Key),
+ ?line Case1Ctx512_2 = crypto:hmac_update(Case1Ctx512, Case1Data),
+ ?line Case1Mac512_1 = crypto:hmac_final(Case1Ctx512_2),
+ ?line Case1Mac512_2 = crypto:sha512_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp512, Case1Mac512_1),
+ ?line m(Case1Exp512, Case1Mac512_2),
+
+ %% Test Case 2
+ Case2Key = <<"Jefe">>,
+ Case2Data = <<"what do ya want for nothing?">>,
+ Case2Exp256 = hexstr2bin("5bdcc146bf60754e6a042426089575c7"
+ "5a003f089d2739839dec58b964ec3843"),
+ Case2Exp384 = hexstr2bin("af45d2e376484031617f78d2b58a6b1b"
+ "9c7ef464f5a01b47e42ec3736322445e"
+ "8e2240ca5e69e2c78b3239ecfab21649"),
+ Case2Exp512 = hexstr2bin("164b7a7bfcf819e2e395fbe73b56e0a3"
+ "87bd64222e831fd610270cd7ea250554"
+ "9758bf75c05a994a6d034f65f8f0e6fd"
+ "caeab1a34d4a6b4b636e070a38bce737"),
+
+ ?line Case2Ctx256 = crypto:hmac_init(sha256, Case2Key),
+ ?line Case2Ctx256_2 = crypto:hmac_update(Case2Ctx256, Case2Data),
+ ?line Case2Mac256_1 = crypto:hmac_final(Case2Ctx256_2),
+ ?line Case2Mac256_2 = crypto:sha256_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp256, Case2Mac256_1),
+ ?line m(Case2Exp256, Case2Mac256_2),
+
+ ?line Case2Ctx384 = crypto:hmac_init(sha384, Case2Key),
+ ?line Case2Ctx384_2 = crypto:hmac_update(Case2Ctx384, Case2Data),
+ ?line Case2Mac384_1 = crypto:hmac_final(Case2Ctx384_2),
+ ?line Case2Mac384_2 = crypto:sha384_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp384, Case2Mac384_1),
+ ?line m(Case2Exp384, Case2Mac384_2),
+
+ ?line Case2Ctx512 = crypto:hmac_init(sha512, Case2Key),
+ ?line Case2Ctx512_2 = crypto:hmac_update(Case2Ctx512, Case2Data),
+ ?line Case2Mac512_1 = crypto:hmac_final(Case2Ctx512_2),
+ ?line Case2Mac512_2 = crypto:sha512_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp512, Case2Mac512_1),
+ ?line m(Case2Exp512, Case2Mac512_2),
+
+ %% Test Case 3
+ Case3Key = binary:copy(<<16#aa>>, 20),
+ Case3Data = binary:copy(<<16#dd>>, 50),
+ Case3Exp256 = hexstr2bin("773ea91e36800e46854db8ebd09181a7"
+ "2959098b3ef8c122d9635514ced565fe"),
+ Case3Exp384 = hexstr2bin("88062608d3e6ad8a0aa2ace014c8a86f"
+ "0aa635d947ac9febe83ef4e55966144b"
+ "2a5ab39dc13814b94e3ab6e101a34f27"),
+ Case3Exp512 = hexstr2bin("fa73b0089d56a284efb0f0756c890be9"
+ "b1b5dbdd8ee81a3655f83e33b2279d39"
+ "bf3e848279a722c806b485a47e67c807"
+ "b946a337bee8942674278859e13292fb"),
+
+ ?line Case3Ctx256 = crypto:hmac_init(sha256, Case3Key),
+ ?line Case3Ctx256_2 = crypto:hmac_update(Case3Ctx256, Case3Data),
+ ?line Case3Mac256_1 = crypto:hmac_final(Case3Ctx256_2),
+ ?line Case3Mac256_2 = crypto:sha256_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp256, Case3Mac256_1),
+ ?line m(Case3Exp256, Case3Mac256_2),
+
+ ?line Case3Ctx384 = crypto:hmac_init(sha384, Case3Key),
+ ?line Case3Ctx384_2 = crypto:hmac_update(Case3Ctx384, Case3Data),
+ ?line Case3Mac384_1 = crypto:hmac_final(Case3Ctx384_2),
+ ?line Case3Mac384_2 = crypto:sha384_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp384, Case3Mac384_1),
+ ?line m(Case3Exp384, Case3Mac384_2),
+
+ ?line Case3Ctx512 = crypto:hmac_init(sha512, Case3Key),
+ ?line Case3Ctx512_2 = crypto:hmac_update(Case3Ctx512, Case3Data),
+ ?line Case3Mac512_1 = crypto:hmac_final(Case3Ctx512_2),
+ ?line Case3Mac512_2 = crypto:sha512_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp512, Case3Mac512_1),
+ ?line m(Case3Exp512, Case3Mac512_2),
+
+ %% Test Case 4
+ Case4Key = list_to_binary(lists:seq(1, 16#19)),
+ Case4Data = binary:copy(<<16#cd>>, 50),
+ Case4Exp256 = hexstr2bin("82558a389a443c0ea4cc819899f2083a"
+ "85f0faa3e578f8077a2e3ff46729665b"),
+ Case4Exp384 = hexstr2bin("3e8a69b7783c25851933ab6290af6ca7"
+ "7a9981480850009cc5577c6e1f573b4e"
+ "6801dd23c4a7d679ccf8a386c674cffb"),
+ Case4Exp512 = hexstr2bin("b0ba465637458c6990e5a8c5f61d4af7"
+ "e576d97ff94b872de76f8050361ee3db"
+ "a91ca5c11aa25eb4d679275cc5788063"
+ "a5f19741120c4f2de2adebeb10a298dd"),
+
+ ?line Case4Ctx256 = crypto:hmac_init(sha256, Case4Key),
+ ?line Case4Ctx256_2 = crypto:hmac_update(Case4Ctx256, Case4Data),
+ ?line Case4Mac256_1 = crypto:hmac_final(Case4Ctx256_2),
+ ?line Case4Mac256_2 = crypto:sha256_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp256, Case4Mac256_1),
+ ?line m(Case4Exp256, Case4Mac256_2),
+
+ ?line Case4Ctx384 = crypto:hmac_init(sha384, Case4Key),
+ ?line Case4Ctx384_2 = crypto:hmac_update(Case4Ctx384, Case4Data),
+ ?line Case4Mac384_1 = crypto:hmac_final(Case4Ctx384_2),
+ ?line Case4Mac384_2 = crypto:sha384_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp384, Case4Mac384_1),
+ ?line m(Case4Exp384, Case4Mac384_2),
+
+ ?line Case4Ctx512 = crypto:hmac_init(sha512, Case4Key),
+ ?line Case4Ctx512_2 = crypto:hmac_update(Case4Ctx512, Case4Data),
+ ?line Case4Mac512_1 = crypto:hmac_final(Case4Ctx512_2),
+ ?line Case4Mac512_2 = crypto:sha512_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp512, Case4Mac512_1),
+ ?line m(Case4Exp512, Case4Mac512_2),
+
+ %% Test Case 6
+ Case6Key = binary:copy(<<16#aa>>, 131),
+ Case6Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>,
+ Case6Exp256 = hexstr2bin("60e431591ee0b67f0d8a26aacbf5b77f"
+ "8e0bc6213728c5140546040f0ee37f54"),
+ Case6Exp384 = hexstr2bin("4ece084485813e9088d2c63a041bc5b4"
+ "4f9ef1012a2b588f3cd11f05033ac4c6"
+ "0c2ef6ab4030fe8296248df163f44952"),
+ Case6Exp512 = hexstr2bin("80b24263c7c1a3ebb71493c1dd7be8b4"
+ "9b46d1f41b4aeec1121b013783f8f352"
+ "6b56d037e05f2598bd0fd2215d6a1e52"
+ "95e64f73f63f0aec8b915a985d786598"),
+
+ ?line Case6Ctx256 = crypto:hmac_init(sha256, Case6Key),
+ ?line Case6Ctx256_2 = crypto:hmac_update(Case6Ctx256, Case6Data),
+ ?line Case6Mac256_1 = crypto:hmac_final(Case6Ctx256_2),
+ ?line Case6Mac256_2 = crypto:sha256_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp256, Case6Mac256_1),
+ ?line m(Case6Exp256, Case6Mac256_2),
+
+ ?line Case6Ctx384 = crypto:hmac_init(sha384, Case6Key),
+ ?line Case6Ctx384_2 = crypto:hmac_update(Case6Ctx384, Case6Data),
+ ?line Case6Mac384_1 = crypto:hmac_final(Case6Ctx384_2),
+ ?line Case6Mac384_2 = crypto:sha384_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp384, Case6Mac384_1),
+ ?line m(Case6Exp384, Case6Mac384_2),
+
+ ?line Case6Ctx512 = crypto:hmac_init(sha512, Case6Key),
+ ?line Case6Ctx512_2 = crypto:hmac_update(Case6Ctx512, Case6Data),
+ ?line Case6Mac512_1 = crypto:hmac_final(Case6Ctx512_2),
+ ?line Case6Mac512_2 = crypto:sha512_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp512, Case6Mac512_1),
+ ?line m(Case6Exp512, Case6Mac512_2),
+ %% Test Case 7
+ Case7Key = binary:copy(<<16#aa>>, 131),
+ Case7Data = <<"This is a test using a larger than block-size key and a larger t",
+ "han block-size data. The key needs to be hashed before being use",
+ "d by the HMAC algorithm.">>,
+ Case7Exp256 = hexstr2bin("9b09ffa71b942fcb27635fbcd5b0e944"
+ "bfdc63644f0713938a7f51535c3a35e2"),
+ Case7Exp384 = hexstr2bin("6617178e941f020d351e2f254e8fd32c"
+ "602420feb0b8fb9adccebb82461e99c5"
+ "a678cc31e799176d3860e6110c46523e"),
+ Case7Exp512 = hexstr2bin("e37b6a775dc87dbaa4dfa9f96e5e3ffd"
+ "debd71f8867289865df5a32d20cdc944"
+ "b6022cac3c4982b10d5eeb55c3e4de15"
+ "134676fb6de0446065c97440fa8c6a58"),
+
+ ?line Case7Ctx256 = crypto:hmac_init(sha256, Case7Key),
+ ?line Case7Ctx256_2 = crypto:hmac_update(Case7Ctx256, Case7Data),
+ ?line Case7Mac256_1 = crypto:hmac_final(Case7Ctx256_2),
+ ?line Case7Mac256_2 = crypto:sha256_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp256, Case7Mac256_1),
+ ?line m(Case7Exp256, Case7Mac256_2),
+
+ ?line Case7Ctx384 = crypto:hmac_init(sha384, Case7Key),
+ ?line Case7Ctx384_2 = crypto:hmac_update(Case7Ctx384, Case7Data),
+ ?line Case7Mac384_1 = crypto:hmac_final(Case7Ctx384_2),
+ ?line Case7Mac384_2 = crypto:sha384_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp384, Case7Mac384_1),
+ ?line m(Case7Exp384, Case7Mac384_2),
+
+ ?line Case7Ctx512 = crypto:hmac_init(sha512, Case7Key),
+ ?line Case7Ctx512_2 = crypto:hmac_update(Case7Ctx512, Case7Data),
+ ?line Case7Mac512_1 = crypto:hmac_final(Case7Ctx512_2),
+ ?line Case7Mac512_2 = crypto:sha512_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp512, Case7Mac512_1),
+ ?line m(Case7Exp512, Case7Mac512_2).
hmac_update_md5_io(doc) ->
["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. "
@@ -1523,6 +1736,7 @@ worker_loop(N, Config) ->
aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, strong_rand_test,
rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test,
hmac_update_md5, hmac_update_sha, hmac_update_sha256, hmac_update_sha512,
+ hmac_rfc4231,
aes_ctr_stream },
F = element(random:uniform(size(Funcs)),Funcs),
--
cgit v1.2.3
From d830b644d86f07dbebd9c12926c22867442e1726 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Fri, 17 Aug 2012 19:28:08 +0200
Subject: crypto: Add sha224
---
lib/crypto/c_src/crypto.c | 149 +++++++++++++++++++++++++++++++++++++++
lib/crypto/src/crypto.erl | 59 +++++++++++++++-
lib/crypto/test/crypto_SUITE.erl | 54 ++++++++++++++
3 files changed, 259 insertions(+), 3 deletions(-)
(limited to 'lib/crypto')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index c64ad2b82d..d9ae8a87a3 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -53,6 +53,10 @@
#include
#include
+#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA224) && defined(NID_sha224)\
+ && !defined(OPENSSL_NO_SHA256) /* disabled like this in my sha.h (?) */
+# define HAVE_SHA224
+#endif
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA256) && defined(NID_sha256)
# define HAVE_SHA256
#endif
@@ -135,6 +139,10 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -153,6 +161,7 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -215,6 +224,11 @@ static void hmac_md5(unsigned char *key, int klen,
static void hmac_sha1(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
unsigned char *hmacbuf);
+#ifdef HAVE_SHA224
+static void hmac_sha224(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf);
+#endif
#ifdef HAVE_SHA256
static void hmac_sha256(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
@@ -243,6 +257,10 @@ static ErlNifFunc nif_funcs[] = {
{"sha_init", 0, sha_init},
{"sha_update", 2, sha_update},
{"sha_final", 1, sha_final},
+ {"sha224_nif", 1, sha224_nif},
+ {"sha224_init_nif", 0, sha224_init_nif},
+ {"sha224_update_nif", 2, sha224_update_nif},
+ {"sha224_final_nif", 1, sha224_final_nif},
{"sha256_nif", 1, sha256_nif},
{"sha256_init_nif", 0, sha256_init_nif},
{"sha256_update_nif", 2, sha256_update_nif},
@@ -261,6 +279,7 @@ static ErlNifFunc nif_funcs[] = {
{"md4_final", 1, md4_final},
{"md5_mac_n", 3, md5_mac_n},
{"sha_mac_n", 3, sha_mac_n},
+ {"sha224_mac_nif", 3, sha224_mac_nif},
{"sha256_mac_nif", 3, sha256_mac_nif},
{"sha384_mac_nif", 3, sha384_mac_nif},
{"sha512_mac_nif", 3, sha512_mac_nif},
@@ -317,6 +336,7 @@ ERL_NIF_INIT(crypto,nif_funcs,load,reload,upgrade,unload)
#define SHA_CTX_LEN (sizeof(SHA_CTX))
#define SHA_LEN 20
#define SHA_LEN_96 12
+#define SHA224_LEN (224/8)
#define SHA256_LEN (256/8)
#define SHA384_LEN (384/8)
#define SHA512_LEN (512/8)
@@ -331,6 +351,7 @@ static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
static ERL_NIF_TERM atom_true;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_sha;
+static ERL_NIF_TERM atom_sha224;
static ERL_NIF_TERM atom_sha256;
static ERL_NIF_TERM atom_sha384;
static ERL_NIF_TERM atom_sha512;
@@ -406,6 +427,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_true = enif_make_atom(env,"true");
atom_false = enif_make_atom(env,"false");
atom_sha = enif_make_atom(env,"sha");
+ atom_sha224 = enif_make_atom(env,"sha224");
atom_sha256 = enif_make_atom(env,"sha256");
atom_sha384 = enif_make_atom(env,"sha384");
atom_sha512 = enif_make_atom(env,"sha512");
@@ -592,6 +614,67 @@ static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
+static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Data) */
+#ifdef HAVE_SHA224
+ ErlNifBinary ibin;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+ return enif_make_badarg(env);
+ }
+ SHA224((unsigned char *) ibin.data, ibin.size,
+ enif_make_new_binary(env,SHA224_LEN, &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* () */
+#ifdef HAVE_SHA224
+ ERL_NIF_TERM ret;
+ SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+#ifdef HAVE_SHA224
+ SHA256_CTX* new_ctx;
+ ErlNifBinary ctx_bin, data_bin;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
+ memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
+ SHA224_Update(new_ctx, data_bin.data, data_bin.size);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context) */
+#ifdef HAVE_SHA224
+ ErlNifBinary ctx_bin;
+ SHA256_CTX ctx_clone;
+ ERL_NIF_TERM ret;
+ if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
+ return enif_make_badarg(env);
+ }
+ memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
+ SHA224_Final(enif_make_new_binary(env, SHA224_LEN, &ret), &ctx_clone);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data) */
#ifdef HAVE_SHA256
@@ -856,6 +939,28 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return ret;
}
+static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Data, MacSize) */
+#ifdef HAVE_SHA224
+ unsigned char hmacbuf[SHA224_DIGEST_LENGTH];
+ ErlNifBinary key, data;
+ unsigned mac_sz;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data)
+ || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) {
+ return enif_make_badarg(env);
+ }
+ hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
+ memcpy(enif_make_new_binary(env, mac_sz, &ret),
+ hmacbuf, mac_sz);
+ return ret;
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Data, MacSize) */
#ifdef HAVE_SHA256
@@ -931,6 +1036,9 @@ static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
const EVP_MD *md;
if (argv[0] == atom_sha) md = EVP_sha1();
+#ifdef HAVE_SHA224
+ else if (argv[0] == atom_sha224) md = EVP_sha224();
+#endif
#ifdef HAVE_SHA256
else if (argv[0] == atom_sha256) md = EVP_sha256();
#endif
@@ -2351,6 +2459,47 @@ static void hmac_sha1(unsigned char *key, int klen,
SHA1_Final((unsigned char *) hmacbuf, &ctx);
}
+#ifdef HAVE_SHA224
+static void hmac_sha224(unsigned char *key, int klen,
+ unsigned char *dbuf, int dlen,
+ unsigned char *hmacbuf)
+{
+ SHA256_CTX ctx;
+ char ipad[HMAC_INT_LEN];
+ char opad[HMAC_INT_LEN];
+ unsigned char nkey[SHA224_DIGEST_LENGTH];
+ int i;
+
+ /* Change key if longer than 64 bytes */
+ if (klen > HMAC_INT_LEN) {
+ SHA224(key, klen, nkey);
+ key = nkey;
+ klen = SHA224_DIGEST_LENGTH;
+ }
+
+ memset(ipad, '\0', sizeof(ipad));
+ memset(opad, '\0', sizeof(opad));
+ memcpy(ipad, key, klen);
+ memcpy(opad, key, klen);
+
+ for (i = 0; i < HMAC_INT_LEN; i++) {
+ ipad[i] ^= HMAC_IPAD;
+ opad[i] ^= HMAC_OPAD;
+ }
+
+ /* inner SHA */
+ SHA224_Init(&ctx);
+ SHA224_Update(&ctx, ipad, HMAC_INT_LEN);
+ SHA224_Update(&ctx, dbuf, dlen);
+ SHA224_Final((unsigned char *) hmacbuf, &ctx);
+ /* outer SHA */
+ SHA224_Init(&ctx);
+ SHA224_Update(&ctx, opad, HMAC_INT_LEN);
+ SHA224_Update(&ctx, hmacbuf, SHA224_DIGEST_LENGTH);
+ SHA224_Final((unsigned char *) hmacbuf, &ctx);
+}
+#endif
+
#ifdef HAVE_SHA256
static void hmac_sha256(unsigned char *key, int klen,
unsigned char *dbuf, int dlen,
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 177ccfeef7..a07e7a30b4 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -26,10 +26,12 @@
-export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
-export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
+-export([sha224/1, sha224_init/0, sha224_update/2, sha224_final/1]).
-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
-export([sha384/1, sha384_init/0, sha384_update/2, sha384_final/1]).
-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]).
+-export([sha224_mac/2, sha224_mac/3]).
-export([sha256_mac/2, sha256_mac/3]).
-export([sha384_mac/2, sha384_mac/3]).
-export([sha512_mac/2, sha512_mac/3]).
@@ -69,12 +71,13 @@
-define(FUNC_LIST, [md4, md4_init, md4_update, md4_final,
md5, md5_init, md5_update, md5_final,
sha, sha_init, sha_update, sha_final,
- sha256, sha256_init, sha256_update, sha256_final,
+ sha224, sha224_init, sha224_update, sha224_final,
+ sha256, sha256_init, sha256_update, sha256_final,
sha384, sha384_init, sha384_update, sha384_final,
- sha512, sha512_init, sha512_update, sha512_final,
+ sha512, sha512_init, sha512_update, sha512_final,
md5_mac, md5_mac_96,
sha_mac, sha_mac_96,
- sha256_mac, sha384_mac, sha512_mac,
+ sha224_mac, sha256_mac, sha384_mac, sha512_mac,
sha_mac_init, sha_mac_update, sha_mac_final,
des_cbc_encrypt, des_cbc_decrypt,
des_cfb_encrypt, des_cfb_decrypt,
@@ -237,6 +240,40 @@ sha_init() -> ?nif_stub.
sha_update(_Context, _Data) -> ?nif_stub.
sha_final(_Context) -> ?nif_stub.
+%
+%% SHA224
+%%
+-spec sha224(iodata()) -> binary().
+-spec sha224_init() -> binary().
+-spec sha224_update(binary(), iodata()) -> binary().
+-spec sha224_final(binary()) -> binary().
+
+sha224(Data) ->
+ case sha224_nif(Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha224_init() ->
+ case sha224_init_nif() of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha224_update(Context, Data) ->
+ case sha224_update_nif(Context, Data) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+sha224_final(Context) ->
+ case sha224_final_nif(Context) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha224_nif(_Data) -> ?nif_stub.
+sha224_init_nif() -> ?nif_stub.
+sha224_update_nif(_Context, _Data) -> ?nif_stub.
+sha224_final_nif(_Context) -> ?nif_stub.
+
%
%% SHA256
%%
@@ -387,6 +424,22 @@ sha_mac_96(Key, Data) ->
sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
+%%
+%% SHA224_MAC
+%%
+-spec sha224_mac(iodata(), iodata()) -> binary().
+
+sha224_mac(Key, Data) ->
+ sha224_mac(Key, Data, 224 div 8).
+
+sha224_mac(Key, Data, Size) ->
+ case sha224_mac_nif(Key, Data, Size) of
+ notsup -> erlang:error(notsup);
+ Bin -> Bin
+ end.
+
+sha224_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+
%%
%% SHA256_MAC
%%
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index a21b74d5ae..bcd80c5a0f 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -409,6 +409,8 @@ hmac_rfc4231(Config) when is_list(Config) ->
%% Test Case 1
Case1Key = binary:copy(<<16#0b>>, 20),
Case1Data = <<"Hi There">>,
+ Case1Exp224 = hexstr2bin("896fb1128abbdf196832107cd49df33f"
+ "47b4b1169912ba4f53684b22"),
Case1Exp256 = hexstr2bin("b0344c61d8db38535ca8afceaf0bf12b"
"881dc200c9833da726e9376c2e32cff7"),
Case1Exp384 = hexstr2bin("afd03944d84895626b0825f4ab46907f"
@@ -419,6 +421,13 @@ hmac_rfc4231(Config) when is_list(Config) ->
"daa833b7d6b8a702038b274eaea3f4e4"
"be9d914eeb61f1702e696c203a126854"),
+ ?line Case1Ctx224 = crypto:hmac_init(sha224, Case1Key),
+ ?line Case1Ctx224_2 = crypto:hmac_update(Case1Ctx224, Case1Data),
+ ?line Case1Mac224_1 = crypto:hmac_final(Case1Ctx224_2),
+ ?line Case1Mac224_2 = crypto:sha224_mac(Case1Key, Case1Data),
+ ?line m(Case1Exp224, Case1Mac224_1),
+ ?line m(Case1Exp224, Case1Mac224_2),
+
?line Case1Ctx256 = crypto:hmac_init(sha256, Case1Key),
?line Case1Ctx256_2 = crypto:hmac_update(Case1Ctx256, Case1Data),
?line Case1Mac256_1 = crypto:hmac_final(Case1Ctx256_2),
@@ -443,6 +452,8 @@ hmac_rfc4231(Config) when is_list(Config) ->
%% Test Case 2
Case2Key = <<"Jefe">>,
Case2Data = <<"what do ya want for nothing?">>,
+ Case2Exp224 = hexstr2bin("a30e01098bc6dbbf45690f3a7e9e6d0f"
+ "8bbea2a39e6148008fd05e44"),
Case2Exp256 = hexstr2bin("5bdcc146bf60754e6a042426089575c7"
"5a003f089d2739839dec58b964ec3843"),
Case2Exp384 = hexstr2bin("af45d2e376484031617f78d2b58a6b1b"
@@ -453,6 +464,13 @@ hmac_rfc4231(Config) when is_list(Config) ->
"9758bf75c05a994a6d034f65f8f0e6fd"
"caeab1a34d4a6b4b636e070a38bce737"),
+ ?line Case2Ctx224 = crypto:hmac_init(sha224, Case2Key),
+ ?line Case2Ctx224_2 = crypto:hmac_update(Case2Ctx224, Case2Data),
+ ?line Case2Mac224_1 = crypto:hmac_final(Case2Ctx224_2),
+ ?line Case2Mac224_2 = crypto:sha224_mac(Case2Key, Case2Data),
+ ?line m(Case2Exp224, Case2Mac224_1),
+ ?line m(Case2Exp224, Case2Mac224_2),
+
?line Case2Ctx256 = crypto:hmac_init(sha256, Case2Key),
?line Case2Ctx256_2 = crypto:hmac_update(Case2Ctx256, Case2Data),
?line Case2Mac256_1 = crypto:hmac_final(Case2Ctx256_2),
@@ -477,6 +495,8 @@ hmac_rfc4231(Config) when is_list(Config) ->
%% Test Case 3
Case3Key = binary:copy(<<16#aa>>, 20),
Case3Data = binary:copy(<<16#dd>>, 50),
+ Case3Exp224 = hexstr2bin("7fb3cb3588c6c1f6ffa9694d7d6ad264"
+ "9365b0c1f65d69d1ec8333ea"),
Case3Exp256 = hexstr2bin("773ea91e36800e46854db8ebd09181a7"
"2959098b3ef8c122d9635514ced565fe"),
Case3Exp384 = hexstr2bin("88062608d3e6ad8a0aa2ace014c8a86f"
@@ -487,6 +507,13 @@ hmac_rfc4231(Config) when is_list(Config) ->
"bf3e848279a722c806b485a47e67c807"
"b946a337bee8942674278859e13292fb"),
+ ?line Case3Ctx224 = crypto:hmac_init(sha224, Case3Key),
+ ?line Case3Ctx224_2 = crypto:hmac_update(Case3Ctx224, Case3Data),
+ ?line Case3Mac224_1 = crypto:hmac_final(Case3Ctx224_2),
+ ?line Case3Mac224_2 = crypto:sha224_mac(Case3Key, Case3Data),
+ ?line m(Case3Exp224, Case3Mac224_1),
+ ?line m(Case3Exp224, Case3Mac224_2),
+
?line Case3Ctx256 = crypto:hmac_init(sha256, Case3Key),
?line Case3Ctx256_2 = crypto:hmac_update(Case3Ctx256, Case3Data),
?line Case3Mac256_1 = crypto:hmac_final(Case3Ctx256_2),
@@ -511,6 +538,8 @@ hmac_rfc4231(Config) when is_list(Config) ->
%% Test Case 4
Case4Key = list_to_binary(lists:seq(1, 16#19)),
Case4Data = binary:copy(<<16#cd>>, 50),
+ Case4Exp224 = hexstr2bin("6c11506874013cac6a2abc1bb382627c"
+ "ec6a90d86efc012de7afec5a"),
Case4Exp256 = hexstr2bin("82558a389a443c0ea4cc819899f2083a"
"85f0faa3e578f8077a2e3ff46729665b"),
Case4Exp384 = hexstr2bin("3e8a69b7783c25851933ab6290af6ca7"
@@ -521,6 +550,13 @@ hmac_rfc4231(Config) when is_list(Config) ->
"a91ca5c11aa25eb4d679275cc5788063"
"a5f19741120c4f2de2adebeb10a298dd"),
+ ?line Case4Ctx224 = crypto:hmac_init(sha224, Case4Key),
+ ?line Case4Ctx224_2 = crypto:hmac_update(Case4Ctx224, Case4Data),
+ ?line Case4Mac224_1 = crypto:hmac_final(Case4Ctx224_2),
+ ?line Case4Mac224_2 = crypto:sha224_mac(Case4Key, Case4Data),
+ ?line m(Case4Exp224, Case4Mac224_1),
+ ?line m(Case4Exp224, Case4Mac224_2),
+
?line Case4Ctx256 = crypto:hmac_init(sha256, Case4Key),
?line Case4Ctx256_2 = crypto:hmac_update(Case4Ctx256, Case4Data),
?line Case4Mac256_1 = crypto:hmac_final(Case4Ctx256_2),
@@ -545,6 +581,8 @@ hmac_rfc4231(Config) when is_list(Config) ->
%% Test Case 6
Case6Key = binary:copy(<<16#aa>>, 131),
Case6Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>,
+ Case6Exp224 = hexstr2bin("95e9a0db962095adaebe9b2d6f0dbce2"
+ "d499f112f2d2b7273fa6870e"),
Case6Exp256 = hexstr2bin("60e431591ee0b67f0d8a26aacbf5b77f"
"8e0bc6213728c5140546040f0ee37f54"),
Case6Exp384 = hexstr2bin("4ece084485813e9088d2c63a041bc5b4"
@@ -555,6 +593,13 @@ hmac_rfc4231(Config) when is_list(Config) ->
"6b56d037e05f2598bd0fd2215d6a1e52"
"95e64f73f63f0aec8b915a985d786598"),
+ ?line Case6Ctx224 = crypto:hmac_init(sha224, Case6Key),
+ ?line Case6Ctx224_2 = crypto:hmac_update(Case6Ctx224, Case6Data),
+ ?line Case6Mac224_1 = crypto:hmac_final(Case6Ctx224_2),
+ ?line Case6Mac224_2 = crypto:sha224_mac(Case6Key, Case6Data),
+ ?line m(Case6Exp224, Case6Mac224_1),
+ ?line m(Case6Exp224, Case6Mac224_2),
+
?line Case6Ctx256 = crypto:hmac_init(sha256, Case6Key),
?line Case6Ctx256_2 = crypto:hmac_update(Case6Ctx256, Case6Data),
?line Case6Mac256_1 = crypto:hmac_final(Case6Ctx256_2),
@@ -581,6 +626,8 @@ hmac_rfc4231(Config) when is_list(Config) ->
Case7Data = <<"This is a test using a larger than block-size key and a larger t",
"han block-size data. The key needs to be hashed before being use",
"d by the HMAC algorithm.">>,
+ Case7Exp224 = hexstr2bin("3a854166ac5d9f023f54d517d0b39dbd"
+ "946770db9c2b95c9f6f565d1"),
Case7Exp256 = hexstr2bin("9b09ffa71b942fcb27635fbcd5b0e944"
"bfdc63644f0713938a7f51535c3a35e2"),
Case7Exp384 = hexstr2bin("6617178e941f020d351e2f254e8fd32c"
@@ -591,6 +638,13 @@ hmac_rfc4231(Config) when is_list(Config) ->
"b6022cac3c4982b10d5eeb55c3e4de15"
"134676fb6de0446065c97440fa8c6a58"),
+ ?line Case7Ctx224 = crypto:hmac_init(sha224, Case7Key),
+ ?line Case7Ctx224_2 = crypto:hmac_update(Case7Ctx224, Case7Data),
+ ?line Case7Mac224_1 = crypto:hmac_final(Case7Ctx224_2),
+ ?line Case7Mac224_2 = crypto:sha224_mac(Case7Key, Case7Data),
+ ?line m(Case7Exp224, Case7Mac224_1),
+ ?line m(Case7Exp224, Case7Mac224_2),
+
?line Case7Ctx256 = crypto:hmac_init(sha256, Case7Key),
?line Case7Ctx256_2 = crypto:hmac_update(Case7Ctx256, Case7Data),
?line Case7Mac256_1 = crypto:hmac_final(Case7Ctx256_2),
--
cgit v1.2.3
From 42e65ffe5f2659d998ff0a7e5ebea2573c23a86f Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Thu, 16 Aug 2012 16:38:31 +0200
Subject: crypto: Add more generic hash interface
---
lib/crypto/doc/src/crypto.xml | 51 +++++++++++++++++++++++++++++++++++++++++++
lib/crypto/src/crypto.erl | 33 ++++++++++++++++++++++++++--
2 files changed, 82 insertions(+), 2 deletions(-)
(limited to 'lib/crypto')
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 36f8bc6deb..0d78dbc426 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -255,6 +255,57 @@ Mpint() = >]]>
the computed SHA message digest.
+
+ hash(Type, Data) -> Digest
+
+
+ Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512
+ Data = iodata()
+ Digest = binary()
+
+
+ Computes a message digest of type Type from Data.
+
+
+
+ hash_init(Type) -> Context
+
+
+ Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512
+
+
+ Initializes the context for streaming hash operations. Type determines
+ which digest to use. The returned context should be used as argument
+ to hash_update.
+
+
+
+ hash_update(Context, Data) -> NewContext
+
+
+ Data = iodata()
+
+
+ Updates the digest represented by Context using the given Data. Context
+ must have been generated using hash_init
+ or a previous call to this function. Data can be any length. NewContext
+ must be passed into the next call to hash_update
+ or hash_final.
+
+
+
+ hash_final(Context) -> Digest
+
+
+ Digest = binary()
+
+
+ Finalizes the hash operation referenced by Context returned
+ from a previous call to hash_update.
+ The size of Digest is determined by the type of hash
+ function used to generate it.
+
+
md5_mac(Key, Data) -> Mac
Compute an MD5 MACmessage authentification code
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index a07e7a30b4..63043888b9 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -22,7 +22,7 @@
-module(crypto).
-export([start/0, stop/0, info/0, info_lib/0, version/0]).
--export([hash/2]).
+-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]).
-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
@@ -194,11 +194,40 @@ version() -> ?CRYPTO_VSN.
hash(md5, Data) -> md5(Data);
hash(md4, Data) -> md4(Data);
hash(sha, Data) -> sha(Data);
-hash(sha1, Data) -> sha(Data);
+hash(sha224, Data) -> sha224(Data);
hash(sha256, Data) -> sha256(Data);
hash(sha384, Data) -> sha384(Data);
hash(sha512, Data) -> sha512(Data).
+-spec hash_init('md5'|'md4'|'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
+
+hash_init(md5) -> {md5, md5_init()};
+hash_init(md4) -> {md4, md4_init()};
+hash_init(sha) -> {sha, sha_init()};
+hash_init(sha224) -> {sha224, sha224_init()};
+hash_init(sha256) -> {sha256, sha256_init()};
+hash_init(sha384) -> {sha384, sha384_init()};
+hash_init(sha512) -> {sha512, sha512_init()}.
+
+-spec hash_update(_, iodata()) -> any().
+
+hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
+hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
+hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
+hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
+hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
+hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
+hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+
+-spec hash_final(_) -> binary().
+
+hash_final({md5,Context}) -> md5_final(Context);
+hash_final({md4,Context}) -> md4_final(Context);
+hash_final({sha,Context}) -> sha_final(Context);
+hash_final({sha224,Context}) -> sha224_final(Context);
+hash_final({sha256,Context}) -> sha256_final(Context);
+hash_final({sha384,Context}) -> sha384_final(Context);
+hash_final({sha512,Context}) -> sha512_final(Context).
%%
%% MD5
--
cgit v1.2.3
From c5541a4c03b89fcbcb0dd1bfab8460b1287cc6cb Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Mon, 20 Aug 2012 12:31:28 +0200
Subject: crypto: Add sha224 for rsa sign/verify
---
lib/crypto/c_src/crypto.c | 13 +++++++++++++
lib/crypto/doc/src/crypto.xml | 4 ++--
lib/crypto/src/crypto.erl | 2 +-
3 files changed, 16 insertions(+), 3 deletions(-)
(limited to 'lib/crypto')
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index d9ae8a87a3..9a1a6f6c55 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -1564,6 +1564,12 @@ static void sha1_digest(unsigned char* in, unsigned int in_len, unsigned char* o
{
SHA1(in, in_len, out);
}
+#ifdef HAVE_SHA224
+static void sha224_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
+{
+ SHA224(in, in_len, out);
+}
+#endif
#ifdef HAVE_SHA256
static void sha256_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
{
@@ -1595,6 +1601,13 @@ struct digest_type_t digest_types[] =
{
{"md5", MD5_DIGEST_LENGTH, NID_md5, md5_digest},
{"sha", SHA_DIGEST_LENGTH, NID_sha1, sha1_digest},
+ {"sha224",
+#ifdef HAVE_SHA224
+ SHA224_LEN, NID_sha224, sha224_digest
+#else
+ 0
+#endif
+ },
{"sha256",
#ifdef HAVE_SHA256
SHA256_LEN, NID_sha256, sha256_digest
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 0d78dbc426..48e35f8093 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -932,7 +932,7 @@ 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 | sha256 | sha384 | sha512
+ DigestType = md5 | sha | sha224 | sha256 | sha384 | sha512
The default DigestType is sha.
Mpint = binary()
Signature = binary()
@@ -957,7 +957,7 @@ Mpint() = >]]>
Key = [E, N]
E, N = Mpint
Where E is the public exponent and N is public modulus.
- DigestType = md5 | sha | sha256 | sha384 | sha512
+ DigestType = md5 | sha | sha224 | sha256 | sha384 | sha512
The default DigestType is sha.
Mpint = binary()
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 63043888b9..0089e79a4f 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -105,7 +105,7 @@
aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt,
info_lib]).
--type rsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'.
+-type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
-type dss_digest_type() :: 'none' | 'sha'.
-type data_or_digest() :: binary() | {digest, binary()}.
-type crypto_integer() :: binary() | integer().
--
cgit v1.2.3