From: slontis Date: Sun, 25 Aug 2024 23:38:56 +0000 (+1000) Subject: XOF / EVP_MD_size() changes. X-Git-Tag: openssl-3.4.0-alpha1~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c48e56874c5c7d3af3d522e4cae7cb9069143667;p=thirdparty%2Fopenssl.git XOF / EVP_MD_size() changes. Added the function EVP_MD_CTX_get_size_ex() which checks for XOF and does a ctx get rather than just returning EVP_MD_size(). SHAKE did not have a get_ctx_params() so that had to be added to return the xoflen. Added a helper function EVP_MD_xof() EVP_MD_CTX_size() was just an aliased macro for EVP_MD_size(), so to keep it the same I added an extra function. EVP_MD_size() always returns 0 for SHAKE now, since it caches the value of md_size at the time of an EVP_MD_fetch(). This is probably better than returning the incorrect initial value it was before e.g (16 for SHAKE128) and returning tht always instead of the set xoflen. Note BLAKE2B uses "size" instead of "xoflen" to do a similar thing. Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/25285) --- diff --git a/CHANGES.md b/CHANGES.md index a762dcb8f6b..c66ec92cd9f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,6 +29,21 @@ OpenSSL 3.4 ### Changes between 3.3 and 3.4 [xx XXX xxxx] + * XOF Digest API changes. + + EVP_MD_CTX_get_size() and EVP_MD_CTX_size are macros that were aliased to + EVP_MD_get_size which returns a constant value. XOF Digests such as SHAKE + have an output size that is not fixed, so calling EVP_MD_get_size() is not + sufficent. The existing macros now point to the new function + EVP_MD_CTX_get_size_ex() which will retrieve the "size" for a XOF digest, + otherwise it falls back to calling EVP_MD_get_size(). Note that the SHAKE + implementation did not have a context getter previously, so the "size" will + only be able to be retrieved with new providers. + + Also added a EVP_xof() helper. + + *Shane Lontis* + * Add FIPS indicators to the FIPS provider. FIPS 140-3 requires indicators to be used if the FIPS provider allows non-approved algorithms. An algorithm is approved if it passes all diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 9003af6d74e..a34b7ced6c2 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -446,24 +446,13 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize) if (ctx->digest == NULL) return 0; - sz = EVP_MD_get_size(ctx->digest); + sz = EVP_MD_CTX_get_size(ctx); if (sz < 0) return 0; mdsize = sz; if (ctx->digest->prov == NULL) goto legacy; - if (sz == 0) /* Assuming a xoflen must have been set. */ - mdsize = SIZE_MAX; - if (ctx->digest->gettable_ctx_params != NULL) { - OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; - - params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, - &mdsize); - if (!EVP_MD_CTX_get_params(ctx, params)) - return 0; - } - if (ctx->digest->dfinal == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); return 0; @@ -544,7 +533,7 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size) return ret; legacy: - if (ctx->digest->flags & EVP_MD_FLAG_XOF + if (EVP_MD_xof(ctx->digest) && size <= INT_MAX && ctx->digest->md_ctrl(ctx, EVP_MD_CTRL_XOF_LEN, (int)size, NULL)) { ret = ctx->digest->final(ctx, md); @@ -983,6 +972,11 @@ static int evp_md_cache_constants(EVP_MD *md) size_t mdsize = 0; OSSL_PARAM params[5]; + /* + * Note that these parameters are 'constants' that are only set up + * during the EVP_MD_fetch(). For this reason the XOF functions set the + * md_size to 0, since the output size is unknown. + */ params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, &blksz); params[1] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &mdsize); params[2] = OSSL_PARAM_construct_int(OSSL_DIGEST_PARAM_XOF, &xof); diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 3c670b8396b..1aebd718f03 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -814,6 +814,11 @@ int EVP_MD_get_size(const EVP_MD *md) return md->md_size; } +int EVP_MD_xof(const EVP_MD *md) +{ + return md != NULL && ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0); +} + unsigned long EVP_MD_get_flags(const EVP_MD *md) { return md->flags; @@ -1028,6 +1033,34 @@ EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx) return md; } +int EVP_MD_CTX_get_size_ex(const EVP_MD_CTX *ctx) +{ + EVP_MD_CTX *c = (EVP_MD_CTX *)ctx; + const OSSL_PARAM *gettables; + + gettables = EVP_MD_CTX_gettable_params(c); + if (gettables != NULL + && OSSL_PARAM_locate_const(gettables, + OSSL_DIGEST_PARAM_SIZE) != NULL) { + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t sz = 0; + + /* + * For XOF's EVP_MD_get_size() returns 0 + * So try to get the xoflen instead. This will return -1 if the + * xof length has not been set. + */ + params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &sz); + if (EVP_MD_CTX_get_params(c, params) != 1 + || sz == SIZE_MAX + || sz == 0) + return -1; + return sz; + } + /* Normal digests have a constant fixed size output */ + return EVP_MD_get_size(EVP_MD_CTX_get0_md(ctx)); +} + EVP_PKEY_CTX *EVP_MD_CTX_get_pkey_ctx(const EVP_MD_CTX *ctx) { return ctx->pctx; diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod index 70d0836ec26..ed327480a1c 100644 --- a/doc/man3/EVP_DigestInit.pod +++ b/doc/man3/EVP_DigestInit.pod @@ -17,14 +17,15 @@ EVP_MD_is_a, EVP_MD_get0_name, EVP_MD_get0_description, EVP_MD_names_do_all, EVP_MD_get0_provider, EVP_MD_get_type, EVP_MD_get_pkey_type, EVP_MD_get_size, EVP_MD_get_block_size, EVP_MD_get_flags, EVP_MD_CTX_get0_name, EVP_MD_CTX_md, EVP_MD_CTX_get0_md, EVP_MD_CTX_get1_md, -EVP_MD_CTX_get_type, EVP_MD_CTX_get_size, EVP_MD_CTX_get_block_size, +EVP_MD_CTX_get_type, EVP_MD_CTX_get_size_ex, EVP_MD_CTX_get_block_size, EVP_MD_CTX_get0_md_data, EVP_MD_CTX_update_fn, EVP_MD_CTX_set_update_fn, EVP_md_null, EVP_get_digestbyname, EVP_get_digestbynid, EVP_get_digestbyobj, EVP_MD_CTX_get_pkey_ctx, EVP_MD_CTX_set_pkey_ctx, EVP_MD_do_all_provided, EVP_MD_type, EVP_MD_nid, EVP_MD_name, EVP_MD_pkey_type, EVP_MD_size, -EVP_MD_block_size, EVP_MD_flags, EVP_MD_CTX_size, EVP_MD_CTX_block_size, +EVP_MD_block_size, EVP_MD_flags, EVP_MD_xof, +EVP_MD_CTX_size, EVP_MD_CTX_get_size, EVP_MD_CTX_block_size, EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data - EVP digest routines @@ -85,11 +86,12 @@ EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data int EVP_MD_get_size(const EVP_MD *md); int EVP_MD_get_block_size(const EVP_MD *md); unsigned long EVP_MD_get_flags(const EVP_MD *md); + int EVP_MD_xof(const EVP_MD *md); const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx); EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx); const char *EVP_MD_CTX_get0_name(const EVP_MD_CTX *ctx); - int EVP_MD_CTX_get_size(const EVP_MD_CTX *ctx); + int EVP_MD_CTX_get_size_ex(const EVP_MD_CTX *ctx); int EVP_MD_CTX_get_block_size(const EVP_MD_CTX *ctx); int EVP_MD_CTX_get_type(const EVP_MD_CTX *ctx); void *EVP_MD_CTX_get0_md_data(const EVP_MD_CTX *ctx); @@ -114,7 +116,8 @@ EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data #define EVP_MD_size EVP_MD_get_size #define EVP_MD_block_size EVP_MD_get_block_size #define EVP_MD_flags EVP_MD_get_flags - #define EVP_MD_CTX_size EVP_MD_CTX_get_size + #define EVP_MD_CTX_get_size EVP_MD_CTX_get_size_ex + #define EVP_MD_CTX_size EVP_MD_CTX_get_size_ex #define EVP_MD_CTX_block_size EVP_MD_CTX_get_block_size #define EVP_MD_CTX_type EVP_MD_CTX_get_type #define EVP_MD_CTX_pkey_ctx EVP_MD_CTX_get_pkey_ctx @@ -135,11 +138,20 @@ see L: =head1 DESCRIPTION -The EVP digest routines are a high-level interface to message digests, -and should be used instead of the digest-specific functions. +The EVP digest routines are a high-level interface to message digests, and +Extendable Output Functions (XOF). The B type is a structure for digest method implementation. +Each Message digest algorithm (such as SHA256) produces a fixed size output +length which is returned when EVP_DigestFinal_ex() is called. +Extendable Output Functions (XOF) such as SHAKE256 have a variable sized output +length I which can be used with either EVP_DigestFinalXOF() or +EVP_DigestSqueeze(). EVP_DigestFinal_ex() may also be used for an XOF, but the +"xoflen" must be set beforehand (See L). +Note that EVP_MD_get_size() and EVP_MD_CTX_get_size_ex() behave differently for +an XOF. + =over 4 =item EVP_MD_fetch() @@ -344,6 +356,12 @@ EVP_sha256() rather than the result of an EVP_MD_fetch()), only cipher names registered with the default library context (see L) will be considered. +=item EVP_MD_xof() + +Returns 1 if I is an Extendable-output Function (XOF) otherwise it returns +0. SHAKE128 and SHAKE256 are XOF functions. +It returns 0 for BLAKE2B algorithms. + =item EVP_MD_get0_name(), EVP_MD_CTX_get0_name() @@ -366,11 +384,16 @@ The description is at the discretion of the digest implementation. Returns an B pointer to the provider that implements the given B. -=item EVP_MD_get_size(), -EVP_MD_CTX_get_size() +=item EVP_MD_get_size() Return the size of the message digest when passed an B or an B structure, i.e. the size of the hash. +For an XOF this returns 0. + +=item EVP_MD_CTX_get_size_ex(), EVP_MD_CTX_get_size() + +For a normal digest this is the same as EVP_MD_get_size(). +For an XOF this returns the "xoflen" if it has been set, otherwise it returns 0. =item EVP_MD_get_block_size(), EVP_MD_CTX_get_block_size() @@ -482,17 +505,31 @@ I as argument. See L for information about passing parameters. -EVP_MD_CTX_set_params() can be used with the following OSSL_PARAM keys: +EVP_MD_CTX_set_params() and EVP_MD_CTX_get_params() can be used with the +following OSSL_PARAM keys: =over 4 =item "xoflen" (B) -Sets the digest length for extendable output functions. +Sets or gets the digest length for extendable output functions. The value should not exceed what can be given using a B. -It may be used by BLAKE2B-512, SHAKE-128 and SHAKE-256 to set the +It may be used by SHAKE-128 and SHAKE-256 to set the output length used by EVP_DigestFinal_ex() and EVP_DigestFinal(). +=item "size" (B) + +Sets or gets a fixed digest length. +The value should not exceed what can be given using a B. +It may be used by BLAKE2B-512 to set the output length used by +EVP_DigestFinal_ex() and EVP_DigestFinal(). + +=back + +EVP_MD_CTX_set_params() can be used with the following OSSL_PARAM keys: + +=over 4 + =item "pad-type" (B) Sets the padding type. @@ -532,7 +569,7 @@ an L item with the key "micalg" (B). This control sets the digest length for extendable output functions to I. Sending this control directly should not be necessary, the use of EVP_DigestFinalXOF() is preferred. -Currently used by SHAKE. +Currently used by SHAKE algorithms. When used with a fetched B, EVP_MD_CTX_get_params() gets called with an L item with the key "xoflen" (B). @@ -815,6 +852,12 @@ The EVP_MD_CTX_dup() function was added in OpenSSL 3.1. The EVP_DigestSqueeze() function was added in OpenSSL 3.3. +The EVP_MD_CTX_get_size_ex() and EVP_xof() functions were added in OpenSSL 3.4. +The macros EVP_MD_CTX_get_size() and EVP_MD_CTX_size were changed in OpenSSL 3.4 +to be aliases for EVP_MD_CTX_get_size_ex(), previously they were aliases for +EVP_MD_get_size which returned a constant value. This is required for XOF +digests since they do not have a fixed size. + =head1 COPYRIGHT Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man7/EVP_MD-BLAKE2.pod b/doc/man7/EVP_MD-BLAKE2.pod index bfcf43e1991..7b4cf2a6c13 100644 --- a/doc/man7/EVP_MD-BLAKE2.pod +++ b/doc/man7/EVP_MD-BLAKE2.pod @@ -28,11 +28,11 @@ Known names are "BLAKE2B-512" and "BLAKE2b512". =head2 Settable Parameters "BLAKE2B-512" supports the following EVP_MD_CTX_set_params() key -described in L. +described in L. =over 4 -=item "xoflen" (B) +=item "size" (B) =back diff --git a/doc/man7/EVP_MD-SHAKE.pod b/doc/man7/EVP_MD-SHAKE.pod index 10aa3de3dc3..42cf5977f4a 100644 --- a/doc/man7/EVP_MD-SHAKE.pod +++ b/doc/man7/EVP_MD-SHAKE.pod @@ -45,21 +45,15 @@ Known names are "SHAKE-256" and "SHAKE256". =back -=head2 Gettable Parameters +=head2 Parameters -This implementation supports the common gettable parameters described -in L. - -=head2 Settable Context Parameters - -These implementations support the following L entries, -settable for an B with L: +This implementation supports the following L entries: =over 4 =item "xoflen" (B) -Sets the digest length for extendable output functions. +Sets or Gets the digest length for extendable output functions. The length of the "xoflen" parameter should not exceed that of a B. The SHAKE-128 and SHAKE-256 implementations do not have any default digest @@ -70,8 +64,14 @@ EVP_DigestFinal(), since these functions were not designed to handle variable length output. It is recommended to either use EVP_DigestSqueeze() or EVP_DigestFinalXOF() instead. +=item "size" (B) + +An alias of "xoflen". + =back +See L for further information related to parameters + =head1 NOTES For SHAKE-128, to ensure the maximum security strength of 128 bits, the output diff --git a/doc/man7/EVP_MD-common.pod b/doc/man7/EVP_MD-common.pod index afbb91ec07b..02cf65e9b67 100644 --- a/doc/man7/EVP_MD-common.pod +++ b/doc/man7/EVP_MD-common.pod @@ -48,7 +48,7 @@ This value can also be retrieved with L. =head1 SEE ALSO -L, L +L, L, L =head1 COPYRIGHT diff --git a/include/openssl/evp.h b/include/openssl/evp.h index ae76d472a74..33c4d825c1b 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -552,6 +552,7 @@ int EVP_MD_get_block_size(const EVP_MD *md); # define EVP_MD_block_size EVP_MD_get_block_size unsigned long EVP_MD_get_flags(const EVP_MD *md); # define EVP_MD_flags EVP_MD_get_flags +int EVP_MD_xof(const EVP_MD *md); const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx); EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx); @@ -566,9 +567,11 @@ void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx, int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count)); # endif +int EVP_MD_CTX_get_size_ex(const EVP_MD_CTX *ctx); + # define EVP_MD_CTX_get0_name(e) EVP_MD_get0_name(EVP_MD_CTX_get0_md(e)) -# define EVP_MD_CTX_get_size(e) EVP_MD_get_size(EVP_MD_CTX_get0_md(e)) -# define EVP_MD_CTX_size EVP_MD_CTX_get_size +# define EVP_MD_CTX_get_size(e) EVP_MD_CTX_get_size_ex(e) +# define EVP_MD_CTX_size EVP_MD_CTX_get_size_ex # define EVP_MD_CTX_get_block_size(e) EVP_MD_get_block_size(EVP_MD_CTX_get0_md(e)) # define EVP_MD_CTX_block_size EVP_MD_CTX_get_block_size # define EVP_MD_CTX_get_type(e) EVP_MD_get_type(EVP_MD_CTX_get0_md(e)) diff --git a/providers/implementations/digests/sha3_prov.c b/providers/implementations/digests/sha3_prov.c index 76431e89296..5d08e32636f 100644 --- a/providers/implementations/digests/sha3_prov.c +++ b/providers/implementations/digests/sha3_prov.c @@ -35,6 +35,8 @@ static OSSL_FUNC_digest_final_fn keccak_final; static OSSL_FUNC_digest_freectx_fn keccak_freectx; static OSSL_FUNC_digest_dupctx_fn keccak_dupctx; static OSSL_FUNC_digest_squeeze_fn shake_squeeze; +static OSSL_FUNC_digest_get_ctx_params_fn shake_get_ctx_params; +static OSSL_FUNC_digest_gettable_ctx_params_fn shake_gettable_ctx_params; static OSSL_FUNC_digest_set_ctx_params_fn shake_set_ctx_params; static OSSL_FUNC_digest_settable_ctx_params_fn shake_settable_ctx_params; static sha3_absorb_fn generic_sha3_absorb; @@ -525,6 +527,9 @@ const OSSL_DISPATCH ossl_##name##_functions[] = { \ { OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))shake_set_ctx_params }, \ { OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \ (void (*)(void))shake_settable_ctx_params }, \ + { OSSL_FUNC_DIGEST_GET_CTX_PARAMS, (void (*)(void))shake_get_ctx_params }, \ + { OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS, \ + (void (*)(void))shake_gettable_ctx_params }, \ PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END static void keccak_freectx(void *vctx) @@ -545,13 +550,50 @@ static void *keccak_dupctx(void *ctx) return ret; } -static const OSSL_PARAM known_shake_settable_ctx_params[] = { - {OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, - OSSL_PARAM_END -}; +static const OSSL_PARAM *shake_gettable_ctx_params(ossl_unused void *ctx, + ossl_unused void *provctx) +{ + static const OSSL_PARAM known_shake_gettable_ctx_params[] = { + {OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, + {OSSL_DIGEST_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, + OSSL_PARAM_END + }; + return known_shake_gettable_ctx_params; +} + +static int shake_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + KECCAK1600_CTX *ctx = (KECCAK1600_CTX *)vctx; + + if (ctx == NULL) + return 0; + if (params == NULL) + return 1; + + p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_XOFLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->md_size)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + /* Size is an alias of xoflen */ + p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->md_size)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + return 1; +} + static const OSSL_PARAM *shake_settable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx) { + static const OSSL_PARAM known_shake_settable_ctx_params[] = { + {OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, + {OSSL_DIGEST_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, + OSSL_PARAM_END + }; + return known_shake_settable_ctx_params; } @@ -566,6 +608,9 @@ static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[]) return 1; p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_XOFLEN); + if (p == NULL) + p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_SIZE); + if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->md_size)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return 0; @@ -589,8 +634,8 @@ static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[]) SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, \ 0 /* no default md length */, '\x1f') \ PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \ - SHA3_BLOCKSIZE(bitlen), 0, \ - SHAKE_FLAGS) + SHA3_BLOCKSIZE(bitlen), 0, \ + SHAKE_FLAGS) #define IMPLEMENT_KMAC_functions(bitlen) \ KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \ diff --git a/test/evp_xof_test.c b/test/evp_xof_test.c index 964005d0c1b..e1740bab0a6 100644 --- a/test/evp_xof_test.c +++ b/test/evp_xof_test.c @@ -246,18 +246,24 @@ static int shake_kat_digestfinal_xoflen_test(void) int ret = 0; unsigned int digest_length = 0; EVP_MD_CTX *ctx = NULL; + const EVP_MD *md; unsigned char out[sizeof(shake256_output)]; OSSL_PARAM params[2]; size_t sz = 12; if (!TEST_ptr(ctx = shake_setup("SHAKE256"))) return 0; + md = EVP_MD_CTX_get0_md(ctx); memset(out, 0, sizeof(out)); params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &sz); params[1] = OSSL_PARAM_construct_end(); - if (!TEST_int_eq(EVP_MD_CTX_set_params(ctx, params), 1) + if (!TEST_int_eq(EVP_MD_CTX_size(ctx), -1) + || !TEST_int_eq(EVP_MD_CTX_set_params(ctx, params), 1) + || !TEST_int_eq(EVP_MD_CTX_size(ctx), sz) + || !TEST_int_eq(EVP_MD_get_size(md), 0) + || !TEST_true(EVP_MD_xof(md)) || !TEST_true(EVP_DigestUpdate(ctx, shake256_input, sizeof(shake256_input))) || !TEST_true(EVP_DigestFinal(ctx, out, &digest_length)) @@ -494,6 +500,17 @@ err: return ret; } +static int xof_fail_test(void) +{ + int ret; + EVP_MD *md = NULL; + + ret = TEST_ptr(md = EVP_MD_fetch(NULL, "SHA256", NULL)) + && TEST_false(EVP_MD_xof(md)); + EVP_MD_free(md); + return ret; +} + int setup_tests(void) { ADD_TEST(shake_kat_test); @@ -503,5 +520,6 @@ int setup_tests(void) ADD_ALL_TESTS(shake_squeeze_kat_test, OSSL_NELEM(stride_tests)); ADD_ALL_TESTS(shake_squeeze_large_test, OSSL_NELEM(stride_tests)); ADD_ALL_TESTS(shake_squeeze_dup_test, OSSL_NELEM(dupoffset_tests)); + ADD_TEST(xof_fail_test); return 1; }