diff options
author | Sverker Eriksson <sverker@erlang.org> | 2012-06-27 20:55:04 +0200 |
---|---|---|
committer | Ingela Anderton Andin <ingela@erlang.org> | 2012-08-22 14:00:42 +0200 |
commit | 7553817a73f8409a789496964a5292627002e785 (patch) | |
tree | dfb0cf698ac20b1cc95fa742068fdc342aa559bc | |
parent | 807fc6ec56e3e7a65d9de5884cf6ac9927e5c1aa (diff) | |
download | otp-7553817a73f8409a789496964a5292627002e785.tar.gz otp-7553817a73f8409a789496964a5292627002e785.tar.bz2 otp-7553817a73f8409a789496964a5292627002e785.zip |
crypto: Add sha384
-rw-r--r-- | lib/crypto/c_src/crypto.c | 143 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 51 |
2 files changed, 193 insertions, 1 deletions
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). @@ -268,6 +272,40 @@ 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 %% -spec sha512(iodata()) -> binary(). @@ -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 |