summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/crypto/c_src/hash.c186
-rw-r--r--lib/crypto/doc/src/crypto.xml8
-rw-r--r--lib/crypto/src/crypto.erl10
-rw-r--r--lib/crypto/test/crypto_SUITE.erl2
4 files changed, 72 insertions, 134 deletions
diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c
index 92f599fc61..ba454f5062 100644
--- a/lib/crypto/c_src/hash.c
+++ b/lib/crypto/c_src/hash.c
@@ -104,39 +104,30 @@ ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
unsigned ret_size;
unsigned char *outp;
- ASSERT(argc == 2);
-
if ((digp = get_digest_type(argv[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad digest type");
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_NOTSUP_N(env, 0, "Bad digest type in FIPS");
+ if ((md = digp->md.p) == NULL)
+ return EXCP_NOTSUP_N(env, 0, "Digest type not supported in this cryptolib");
+
if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 1, "Not iolist");
- if ((md = digp->md.p) == NULL)
- goto err;
ret_size = (unsigned)EVP_MD_size(md);
ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate binary");
+
if (EVP_Digest(data.data, data.size, outp, &ret_size, md, NULL) != 1)
- goto err;
+ return EXCP_ERROR(env, "Low-level call failed");
ASSERT(ret_size == (unsigned)EVP_MD_size(md));
CONSUME_REDS(env, data);
return ret;
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- return atom_notsup;
-
- err:
- return atom_notsup;
}
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
@@ -147,31 +138,22 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
struct evp_md_ctx *ctx = NULL;
ERL_NIF_TERM ret;
- ASSERT(argc == 1);
-
if ((digp = get_digest_type(argv[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad digest type");
+
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_NOTSUP_N(env, 0, "Digest type not supported in FIPS");
if (digp->md.p == NULL)
- goto err;
+ return EXCP_NOTSUP_N(env, 0, "Unsupported digest type");
if ((ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate nif resource");
if ((ctx->ctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_new failed"));
if (EVP_DigestInit(ctx->ctx, digp->md.p) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_DigestInit failed"));
ret = enif_make_resource(env, ctx);
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- err:
- ret = atom_notsup;
done:
if (ctx)
@@ -185,31 +167,23 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
ErlNifBinary data;
ERL_NIF_TERM ret;
- ASSERT(argc == 2);
-
if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+
if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 1, "Not iolist");
if ((new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx))) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate nif resource");
if ((new_ctx->ctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_new failed"));
if (EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_copy failed"));
if (EVP_DigestUpdate(new_ctx->ctx, data.data, data.size) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_DigestUpdate failed"));
ret = enif_make_resource(env, new_ctx);
CONSUME_REDS(env, data);
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- err:
- ret = atom_notsup;
done:
if (new_ctx)
@@ -228,28 +202,21 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ASSERT(argc == 1);
if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
ret_size = (unsigned)EVP_MD_CTX_size(ctx->ctx);
ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
if ((new_ctx = EVP_MD_CTX_new()) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_new failed"));
if (EVP_MD_CTX_copy(new_ctx, ctx->ctx) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_MD_CTX_copy failed"));
if ((outp = enif_make_new_binary(env, ret_size, &ret)) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Can't make a new binary"));
if (EVP_DigestFinal(new_ctx, outp, &ret_size) != 1)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_DigestFinal failed"));
ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx->ctx));
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- err:
- ret = atom_notsup;
done:
if (new_ctx)
@@ -271,11 +238,12 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ASSERT(argc == 1);
if ((digp = get_digest_type(argv[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad digest type");
+
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_NOTSUP_N(env, 0, "Digest type not supported in FIPS");
if (digp->md.p == NULL)
- goto err;
+ return EXCP_NOTSUP_N(env, 0, "Unsupported digest type");
switch (EVP_MD_type(digp->md.p))
{
@@ -326,27 +294,18 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
break;
#endif
default:
- goto err;
+ return EXCP_NOTSUP_N(env, 0, "Unsupported digest type");
}
ASSERT(ctx_size);
ASSERT(ctx_init);
if ((outp = enif_make_new_binary(env, ctx_size, &ctx)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate binary");
if (ctx_init(outp) != 1)
- goto err;
+ return EXCP_ERROR(env, "Can't init ctx");
return enif_make_tuple2(env, argv[0], ctx);
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- return atom_notsup;
-
- err:
- return atom_notsup;
}
ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -361,23 +320,21 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
size_t ctx_size = 0;
update_fun ctx_update = 0;
- ASSERT(argc == 2);
-
if (!enif_get_tuple(env, argv[0], &arity, &tuple))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (arity != 2)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((digp = get_digest_type(tuple[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+ if (digp->md.p == NULL)
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (!enif_inspect_binary(env, tuple[1], &ctx))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+
if (!enif_inspect_iolist_as_binary(env, argv[1], &data))
- goto bad_arg;
-
- if (digp->md.p == NULL)
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad data");
switch (EVP_MD_type(digp->md.p))
{
@@ -428,32 +385,24 @@ ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
break;
#endif
default:
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad state");
}
ASSERT(ctx_size);
ASSERT(ctx_update);
if (ctx.size != ctx_size)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate binary");
+
memcpy(ctx_buff, ctx.data, ctx_size);
if (ctx_update(ctx_buff, data.data, data.size) != 1)
- goto err;
+ return EXCP_ERROR(env, "Can't update");
CONSUME_REDS(env, data);
return enif_make_tuple2(env, tuple[0], new_ctx);
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- return atom_notsup;
-
- err:
- return atom_notsup;
}
ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -470,21 +419,19 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
final_fun ctx_final = 0;
unsigned char *outp;
- ASSERT(argc == 1);
-
if (!enif_get_tuple(env, argv[0], &arity, &tuple))
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (arity != 2)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((digp = get_digest_type(tuple[0])) == NULL)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if (DIGEST_FORBIDDEN_IN_FIPS(digp))
- goto notsup;
- if (!enif_inspect_binary(env, tuple[1], &ctx))
- goto bad_arg;
-
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((md = digp->md.p) == NULL)
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad state");
+
+ if (!enif_inspect_binary(env, tuple[1], &ctx))
+ return EXCP_BADARG_N(env, 0, "Bad data");
switch (EVP_MD_type(md))
{
@@ -535,33 +482,24 @@ ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
break;
#endif
default:
- goto err;
+ return EXCP_BADARG_N(env, 0, "Bad state");
}
ASSERT(ctx_size);
ASSERT(ctx_final);
if (ctx.size != ctx_size)
- goto bad_arg;
+ return EXCP_BADARG_N(env, 0, "Bad state");
if ((new_ctx = enif_alloc(ctx_size)) == NULL)
- goto err;
+ return EXCP_ERROR(env, "Can't allocate");
memcpy(new_ctx, ctx.data, ctx_size);
if ((outp = enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret)) == NULL)
- goto err;
+ assign_goto(ret, done, EXCP_ERROR(env, "Can't allocate binary"));
if (ctx_final(outp, new_ctx) != 1)
- goto err;
-
- goto done;
-
- bad_arg:
- return enif_make_badarg(env);
-
- notsup:
- err:
- ret = atom_notsup;
+ assign_goto(ret, done, EXCP_ERROR(env, "Can't do final"));
done:
if (new_ctx)
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 34abbfa279..d8d26fffb0 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1078,9 +1078,8 @@ end
<name name="hash" arity="2" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Computes a message digest of type <c>Type</c> from <c>Data</c>.</p>
- <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
@@ -1088,11 +1087,10 @@ end
<name name="hash_init" arity="1" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Initializes the context for streaming hash operations. <c>Type</c> determines
which digest to use. The returned context should be used as argument
to <seemfa marker="#hash_update/2">hash_update</seemfa>.</p>
- <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
@@ -1100,6 +1098,7 @@ end
<name name="hash_update" arity="2" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using <seemfa marker="#hash_init/1">hash_init</seemfa>
or a previous call to this function. <c>Data</c> can be any length. <c>NewContext</c>
@@ -1112,6 +1111,7 @@ end
<name name="hash_final" arity="1" since="OTP R15B02"/>
<fsummary></fsummary>
<desc>
+ <p>Uses the <seeerl marker="#error_3tup">3-tuple style</seeerl> for error handling.</p>
<p>Finalizes the hash operation referenced by <c>Context</c> returned
from a previous call to <seemfa marker="#hash_update/2">hash_update</seemfa>.
The size of <c>Digest</c> is determined by the type of hash
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 9d54849ee6..3ecd0777d6 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -614,7 +614,7 @@ hash(Type, Data) ->
-spec hash_init(Type) -> State when Type :: hash_algorithm(),
State :: hash_state().
hash_init(Type) ->
- notsup_to_error(hash_init_nif(Type)).
+ ?nif_call(hash_init_nif(Type)).
-spec hash_update(State, Data) -> NewState when State :: hash_state(),
NewState :: hash_state(),
@@ -627,7 +627,7 @@ hash_update(Context, Data) ->
-spec hash_final(State) -> Digest when State :: hash_state(),
Digest :: binary().
hash_final(Context) ->
- notsup_to_error(hash_final_nif(Context)).
+ ?nif_call(hash_final_nif(Context)).
%%%================================================================
%%%
@@ -2170,17 +2170,17 @@ notsup_to_error(Other) ->
%% HASH --------------------------------------------------------------------
hash(Hash, Data, Size, Max) when Size =< Max ->
- notsup_to_error(hash_nif(Hash, Data));
+ ?nif_call(hash_nif(Hash, Data));
hash(Hash, Data, Size, Max) ->
State0 = hash_init(Hash),
State1 = hash_update(State0, Data, Size, Max),
hash_final(State1).
hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- notsup_to_error(hash_update_nif(State, Data));
+ ?nif_call(hash_update_nif(State, Data), {1,2});
hash_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = notsup_to_error(hash_update_nif(State0, Increment)),
+ State = ?nif_call(hash_update_nif(State0, Increment), {1,2}),
hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
hash_info_nif(_Hash) -> ?nif_stub.
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index fdf3394e5e..0329ed992a 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -4345,7 +4345,7 @@ bad_generate_key_name(_Config) ->
bad_hash_name(_Config) ->
?chk_api_name(crypto:hash_init(foobar),
- error:badarg).
+ error:{badarg,{"hash.c",_},"Bad digest type"}).
bad_mac_name(_Config) ->
?chk_api_name(crypto:mac(foobar, <<1:1024>>, "nothing"),