diff --git a/lib/crypto/c_src/digest.c b/lib/crypto/c_src/digest.c index 01b6cbe751f8..9902a20692ec 100644 --- a/lib/crypto/c_src/digest.c +++ b/lib/crypto/c_src/digest.c @@ -116,7 +116,8 @@ static struct digest_type_t digest_types[] = {"shake128", "SHAKE-128", 0, 0, #ifdef HAVE_SHAKE128 - {&EVP_shake128, NULL} + {&EVP_shake128, NULL}, + 16, /* xof_default_length */ #else {NULL,NULL} #endif @@ -124,7 +125,8 @@ static struct digest_type_t digest_types[] = {"shake256", "SHAKE-256", 0, 0, #ifdef HAVE_SHAKE256 - {&EVP_shake256, NULL} + {&EVP_shake256, NULL}, + 32, /* xof_default_length */ #else {NULL,NULL} #endif diff --git a/lib/crypto/c_src/digest.h b/lib/crypto/c_src/digest.h index de02ef36003f..d78f345f908b 100644 --- a/lib/crypto/c_src/digest.h +++ b/lib/crypto/c_src/digest.h @@ -32,6 +32,7 @@ struct digest_type_t { const EVP_MD* (*funcp)(void); /* before init, NULL if notsup */ const EVP_MD* p; /* after init, NULL if notsup */ }md; + unsigned int xof_default_length; /* 0 or default digest length for XOF digests */ }; /* masks in the flags field if digest_type_t */ diff --git a/lib/crypto/c_src/hash.c b/lib/crypto/c_src/hash.c index 4d1c4dfdd8a8..132c9aaed828 100644 --- a/lib/crypto/c_src/hash.c +++ b/lib/crypto/c_src/hash.c @@ -154,6 +154,21 @@ ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) if (EVP_DigestInit(ctx->ctx, digp->md.p) != 1) assign_goto(ret, done, EXCP_ERROR(env, "Low-level call EVP_DigestInit failed")); +#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(3,4,0) + /* + * The default digest length for shake128 and shake256 was removed + * in OpenSSL 3.4, so we set them to be backward compatible with ourself. + */ + if (digp->xof_default_length) { + OSSL_PARAM params[2]; + params[0] = OSSL_PARAM_construct_uint("xoflen", &digp->xof_default_length); + params[1] = OSSL_PARAM_construct_end(); + if (!EVP_MD_CTX_set_params(ctx->ctx, params)) { + assign_goto(ret, done, EXCP_ERROR(env, "Can't set param xoflen")); + } + } +#endif + ret = enif_make_resource(env, ctx); done: diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index bcb3490487ad..89c6343e8575 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -806,9 +806,9 @@ hash(Config) when is_list(Config) -> hash_xof() -> [{doc, "Test all different hash_xof functions"}]. hash_xof(Config) when is_list(Config) -> - {Type, MsgsLE, Digests, Lengths} = proplists:get_value(hash_xof, Config), + {Type, DefaultLen, MsgsLE, Digests, Lengths} = proplists:get_value(hash_xof, Config), Msgs = lazy_eval(MsgsLE), - hash_xof(Type, Msgs, Digests, Lengths). + hash_xof(Type, DefaultLen, Msgs, Digests, Lengths). %%-------------------------------------------------------------------- no_hash() -> @@ -1569,15 +1569,29 @@ hash(Type, [Msg | RestMsg], [Digest| RestDigest]) -> ct:fail({{crypto, hash, [Type, Msg]}, {expected, Digest}, {got, Other}}) end. -hash_xof(_, [], [], []) -> +hash_xof(_, _, [], [], []) -> ok; -hash_xof(Type, [Msg | RestMsg], [Digest | RestDigest], [Length | RestLength]) -> - case crypto:hash_xof(Type, Msg, Length) of - Digest -> - hash_xof(Type, RestMsg, RestDigest, RestLength); - Other -> - ct:fail({{crypto, hash_xof, [Type, Msg, Length]}, {expected, Digest}, {got, Other}}) - end. +hash_xof(Type, DefaultLen, [Msg | RestMsg], [Digest | RestDigest], [Length | RestLength]) -> + case crypto:hash_xof(Type, Msg, Length) of + Digest -> + ok; + Other1 -> + ct:fail({{crypto, hash_xof, [Type, Msg, Length]}, {expected, Digest}, {got, Other1}}) + end, + case Length of + DefaultLen -> + State1 = crypto:hash_init(Type), + State2 = crypto:hash_update(State1, Msg), + case crypto:hash_final(State2) of + Digest -> + ok; + Other2 -> + ct:fail({{crypto, hash_xof, [Type, Msg, Length]}, {expected, Digest}, {got, Other2}}) + end; + _ -> + ok % No crypto:hash_init({Type,Length}) support yet + end, + hash_xof(Type, DefaultLen, RestMsg, RestDigest, RestLength). hash_increment(Type, Increments, Digest) -> State = crypto:hash_init(Type), @@ -2215,10 +2229,10 @@ group_config(sm3 = Type, Config) -> [{hash, {Type, Msgs, Digests}} | Config]; group_config(shake128 = Type, Config) -> {Msgs,Digests,Lengths} = sha3_shake128_test_vectors(Type), - [{hash_xof, {Type, Msgs, Digests, Lengths}} | Config]; + [{hash_xof, {Type, 128, Msgs, Digests, Lengths}} | Config]; group_config(shake256 = Type, Config) -> {Msgs,Digests,Lengths} = sha3_shake256_test_vectors(Type), - [{hash_xof, {Type, Msgs, Digests, Lengths}} | Config]; + [{hash_xof, {Type, 256, Msgs, Digests, Lengths}} | Config]; group_config(blake2b = Type, Config) -> {Msgs, Digests} = blake2_test_vectors(Type), [{hash, {Type, Msgs, Digests}} | Config];