diff options
Diffstat (limited to 'lib/crypto')
-rw-r--r-- | lib/crypto/c_src/hash.c | 186 | ||||
-rw-r--r-- | lib/crypto/doc/src/crypto.xml | 8 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 10 | ||||
-rw-r--r-- | lib/crypto/test/crypto_SUITE.erl | 2 |
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"), |