]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
XOF / EVP_MD_size() changes.
authorslontis <shane.lontis@oracle.com>
Sun, 25 Aug 2024 23:38:56 +0000 (09:38 +1000)
committerTomas Mraz <tomas@openssl.org>
Thu, 29 Aug 2024 08:29:53 +0000 (10:29 +0200)
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 <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25285)

CHANGES.md
crypto/evp/digest.c
crypto/evp/evp_lib.c
doc/man3/EVP_DigestInit.pod
doc/man7/EVP_MD-BLAKE2.pod
doc/man7/EVP_MD-SHAKE.pod
doc/man7/EVP_MD-common.pod
include/openssl/evp.h
providers/implementations/digests/sha3_prov.c
test/evp_xof_test.c

index a762dcb8f6b86eff9f27cc1c3da3d79914167d3d..c66ec92cd9f99ce690f6ae18b67d924a33d9c3a5 100644 (file)
@@ -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
index 9003af6d74ea60ea2afac7e23927a4ec0ae10f5a..a34b7ced6c2d88e5faec384076e4f3f570a02698 100644 (file)
@@ -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);
index 3c670b8396b6e490f60ca7e93c35d5c585ea88ff..1aebd718f03678f34cc6b25c809c9a7a3fea27b3 100644 (file)
@@ -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;
index 70d0836ec26a9fdb130591b51e51c031ad05b294..ed327480a1ca10004a7fdf055f8d4d881894c88d 100644 (file)
@@ -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<openssl_user_macros(7)>:
 
 =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<EVP_MD> 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<outlen> 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</PARAMETERS>).
+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<OSSL_LIB_CTX(3)>) will be considered.
 
+=item EVP_MD_xof()
+
+Returns 1 if I<md> 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<OSSL_PROVIDER> pointer to the provider that implements the given
 B<EVP_MD>.
 
-=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<EVP_MD> or an
 B<EVP_MD_CTX> 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<arg> as argument.
 
 See L<OSSL_PARAM(3)> 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<OSSL_DIGEST_PARAM_XOFLEN>) <unsigned integer>
 
-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<size_t>.
-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<OSSL_DIGEST_PARAM_SIZE>) <unsigned integer>
+
+Sets or gets a fixed digest length.
+The value should not exceed what can be given using a B<size_t>.
+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<OSSL_DIGEST_PARAM_PAD_TYPE>) <unsigned integer>
 
 Sets the padding type.
@@ -532,7 +569,7 @@ an L<OSSL_PARAM(3)> item with the key "micalg" (B<OSSL_DIGEST_PARAM_MICALG>).
 This control sets the digest length for extendable output functions to I<p1>.
 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>, EVP_MD_CTX_get_params() gets called with
 an L<OSSL_PARAM(3)> item with the key "xoflen" (B<OSSL_DIGEST_PARAM_XOFLEN>).
@@ -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.
index bfcf43e199117a3b2c1f9250e66e134b55c4bd83..7b4cf2a6c13b8198e77e4cbbc253b6460d15f375 100644 (file)
@@ -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<EVP_DigestInit(3)/PARAMETERS>.
+described in L<EVP_DigestInit(3)/PARAMETERS>.
 
 =over 4
 
-=item "xoflen" (B<OSSL_DIGEST_PARAM_XOFLEN>) <unsigned integer>
+=item "size" (B<OSSL_DIGEST_PARAM_SIZE>) <unsigned integer>
 
 =back
 
index 10aa3de3dc36e5e17d924d8f8d36c926a6cb7fd6..42cf5977f4a6799b57ba12f4a493984592b5044e 100644 (file)
@@ -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<EVP_MD-common(7)>.
-
-=head2 Settable Context Parameters
-
-These implementations support the following L<OSSL_PARAM(3)> entries,
-settable for an B<EVP_MD_CTX> with L<EVP_MD_CTX_set_params(3)>:
+This implementation supports the following L<OSSL_PARAM(3)> entries:
 
 =over 4
 
 =item "xoflen" (B<OSSL_DIGEST_PARAM_XOFLEN>) <unsigned integer>
 
-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<size_t>.
 
 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<OSSL_DIGEST_PARAM_SIZE>) <unsigned integer>
+
+An alias of "xoflen".
+
 =back
 
+See L<EVP_DigestInit(3)/PARAMETERS> for further information related to parameters
+
 =head1 NOTES
 
 For SHAKE-128, to ensure the maximum security strength of 128 bits, the output
index afbb91ec07b2442f548e54f5945faeeadb9dcb60..02cf65e9b6764186f7d238385e640c13f10e52d7 100644 (file)
@@ -48,7 +48,7 @@ This value can also be retrieved with L<EVP_MD_get_flags(3)>.
 
 =head1 SEE ALSO
 
-L<EVP_MD_get_params(3)>, L<provider-digest(7)>
+L<EVP_DigestInit(3)/PARAMETERS>, L<EVP_MD_get_params(3)>, L<provider-digest(7)>
 
 =head1 COPYRIGHT
 
index ae76d472a749a6a763faaa78bec9893a077f2ac1..33c4d825c1bf869194e33cdfd842dd0ecaf0e4e9 100644 (file)
@@ -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))
index 76431e89296cc2e2f4fabdcb8bae218565134225..5d08e32636f8bd25c9b0867b8b98584f9c2357c0 100644 (file)
@@ -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')                          \
index 964005d0c1b95088b7201ac7d9d4fcaf79401bfb..e1740bab0a6e0c2d95c14baa9bd68794cb47e585 100644 (file)
@@ -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;
 }