From 6a5dc8fdf6569e14a42d136baa6ab242719edeba Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 30 Nov 2011 12:20:58 +0100 Subject: crypto: Add sha256 and sha512 No test and doc --- lib/crypto/c_src/crypto.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++ lib/crypto/src/crypto.erl | 75 +++++++++++++++++++++-- 2 files changed, 222 insertions(+), 4 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 802c1991de..76c2b11b82 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -53,6 +53,13 @@ #include #include +#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA256) && defined(NID_sha256) +# define HAVE_SHA256 +#endif +#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA512) && defined(NID_sha512) +# define HAVE_SHA512 +#endif + #ifdef VALGRIND # include @@ -124,6 +131,14 @@ 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 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 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[]); +static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -201,6 +216,14 @@ static ErlNifFunc nif_funcs[] = { {"sha_init", 0, sha_init}, {"sha_update", 2, sha_update}, {"sha_final", 1, sha_final}, + {"sha256_nif", 1, sha256_nif}, + {"sha256_init_nif", 0, sha256_init_nif}, + {"sha256_update_nif", 2, sha256_update_nif}, + {"sha256_final_nif", 1, sha256_final_nif}, + {"sha512_nif", 1, sha512_nif}, + {"sha512_init_nif", 0, sha512_init_nif}, + {"sha512_update_nif", 2, sha512_update_nif}, + {"sha512_final_nif", 1, sha512_final_nif}, {"md4", 1, md4}, {"md4_init", 0, md4_init}, {"md4_update", 2, md4_update}, @@ -260,6 +283,9 @@ 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 SHA256_LEN (256/8) +#define SHA384_LEN (384/8) +#define SHA512_LEN (512/8) #define HMAC_INT_LEN 64 #define HMAC_IPAD 0x36 @@ -286,6 +312,7 @@ static ERL_NIF_TERM atom_not_suitable_generator; 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 int is_ok_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info) @@ -355,6 +382,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_check_failed = enif_make_atom(env,"check_failed"); atom_unknown = enif_make_atom(env,"unknown"); atom_none = enif_make_atom(env,"none"); + atom_notsup = enif_make_atom(env,"notsup"); *priv_data = NULL; library_refc++; @@ -519,6 +547,129 @@ static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ return ret; } +static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Data) */ +#ifdef HAVE_SHA256 + ErlNifBinary ibin; + ERL_NIF_TERM ret; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { + return enif_make_badarg(env); + } + SHA256((unsigned char *) ibin.data, ibin.size, + enif_make_new_binary(env,SHA256_LEN, &ret)); + return ret; +#else + return atom_notsup; +#endif +} +static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* () */ +#ifdef HAVE_SHA256 + ERL_NIF_TERM ret; + SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret)); + return ret; +#else + return atom_notsup; +#endif +} +static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Context, Data) */ +#ifdef HAVE_SHA256 + 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)); + SHA256_Update(new_ctx, data_bin.data, data_bin.size); + return ret; +#else + return atom_notsup; +#endif +} +static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Context) */ +#ifdef HAVE_SHA256 + 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 */ + SHA256_Final(enif_make_new_binary(env, SHA256_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 + ErlNifBinary ibin; + ERL_NIF_TERM ret; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { + return enif_make_badarg(env); + } + SHA512((unsigned char *) ibin.data, ibin.size, + enif_make_new_binary(env,SHA512_LEN, &ret)); + return ret; +#else + return atom_notsup; +#endif +} +static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* () */ +#ifdef HAVE_SHA512 + ERL_NIF_TERM ret; + SHA512_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret)); + return ret; +#else + return atom_notsup; +#endif +} +static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Context, Data) */ +#ifdef HAVE_SHA512 + 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)); + SHA512_Update(new_ctx, data_bin.data, data_bin.size); + return ret; +#else + return atom_notsup; +#endif +} +static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Context) */ +#ifdef HAVE_SHA512 + 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 */ + SHA512_Final(enif_make_new_binary(env, SHA512_LEN, &ret), &ctx_clone); + return ret; +#else + return atom_notsup; +#endif +} + + static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 0714cb686d..522cce2086 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -25,8 +25,8 @@ -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([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([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]). @@ -64,8 +64,8 @@ -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, -%% sha512, sha512_init, sha512_update, sha512_final, + sha256, sha256_init, sha256_update, sha256_final, + sha512, sha512_init, sha512_update, sha512_final, md5_mac, md5_mac_96, sha_mac, sha_mac_96, sha_mac_init, sha_mac_update, sha_mac_final, @@ -219,6 +219,73 @@ sha_init() -> ?nif_stub. sha_update(_Context, _Data) -> ?nif_stub. sha_final(_Context) -> ?nif_stub. +% +%% SHA256 +%% +-spec sha256(iodata()) -> binary(). +-spec sha256_init() -> binary(). +-spec sha256_update(binary(), iodata()) -> binary(). +-spec sha256_final(binary()) -> binary(). + +sha256(Data) -> + case sha256_nif(Data) of + notsup -> erlang:error(notsup); + Bin -> Bin + end. +sha256_init() -> + case sha256_init_nif() of + notsup -> erlang:error(notsup); + Bin -> Bin + end. +sha256_update(Context, Data) -> + case sha256_update_nif(Context, Data) of + notsup -> erlang:error(notsup); + Bin -> Bin + end. +sha256_final(Context) -> + case sha256_final_nif(Context) of + notsup -> erlang:error(notsup); + Bin -> Bin + end. + +sha256_nif(_Data) -> ?nif_stub. +sha256_init_nif() -> ?nif_stub. +sha256_update_nif(_Context, _Data) -> ?nif_stub. +sha256_final_nif(_Context) -> ?nif_stub. + +% +%% SHA512 +%% +-spec sha512(iodata()) -> binary(). +-spec sha512_init() -> binary(). +-spec sha512_update(binary(), iodata()) -> binary(). +-spec sha512_final(binary()) -> binary(). + +sha512(Data) -> + case sha512_nif(Data) of + notsup -> erlang:error(notsup); + Bin -> Bin + end. +sha512_init() -> + case sha512_init_nif() of + notsup -> erlang:error(notsup); + Bin -> Bin + end. +sha512_update(Context, Data) -> + case sha512_update_nif(Context, Data) of + notsup -> erlang:error(notsup); + Bin -> Bin + end. +sha512_final(Context) -> + case sha512_final_nif(Context) of + notsup -> erlang:error(notsup); + Bin -> Bin + end. + +sha512_nif(_Data) -> ?nif_stub. +sha512_init_nif() -> ?nif_stub. +sha512_update_nif(_Context, _Data) -> ?nif_stub. +sha512_final_nif(_Context) -> ?nif_stub. %% %% MESSAGE AUTHENTICATION CODES -- cgit v1.2.3