Blake2b: Use OSSL_DIGEST_PARAM_SIZE as settable instead of XOFLEN
authorTomas Mraz <tomas@openssl.org>
Tue, 24 Oct 2023 11:44:26 +0000 (13:44 +0200)
committerMatt Caswell <matt@openssl.org>
Wed, 25 Oct 2023 19:13:39 +0000 (20:13 +0100)
BLAKE2 is not really an extensible output function unlike SHAKE
as the digest size must be set during the context initialization.
Thus it makes no sense to use OSSL_DIGEST_PARAM_XOFLEN.

We also need to adjust EVP_DigestFinal_ex() to query the
OSSL_DIGEST_PARAM_SIZE as gettable ctx param for the size.

Fixes #22488

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22491)

crypto/evp/digest.c
doc/man3/EVP_DigestInit.pod
doc/man7/EVP_MD-BLAKE2.pod
providers/implementations/digests/blake2_prov.c
providers/implementations/digests/blake2b_prov.c
providers/implementations/include/prov/blake2.h
providers/implementations/kdfs/argon2.c
test/evp_test.c
test/recipes/30-test_evp_data/evpmd_blake.txt

index 01f54792f6f377caf208a07d3ba31a9d86a0e539..42331703da3223fda7107f679df23256bb2ab016 100644 (file)
@@ -454,6 +454,15 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
     if (ctx->digest->prov == NULL)
         goto legacy;
 
+    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;
index 9b5fda08ee9f4bd326dc64e092cbd095fef94bbb..409630e5d4db88105241d5c5a91d0e084e556494 100644 (file)
@@ -282,9 +282,11 @@ data.
 Retrieves the digest value from I<ctx> and places it in I<md>. If the I<s>
 parameter is not NULL then the number of bytes of data written (i.e. the
 length of the digest) will be written to the integer at I<s>, at most
-B<EVP_MAX_MD_SIZE> bytes will be written.  After calling EVP_DigestFinal_ex()
-no additional calls to EVP_DigestUpdate() can be made, but
-EVP_DigestInit_ex2() can be called to initialize a new digest operation.
+B<EVP_MAX_MD_SIZE> bytes will be written unless the digest implementation
+allows changing the digest size and it is set to a larger value by the
+application. After calling EVP_DigestFinal_ex() no additional calls to
+EVP_DigestUpdate() can be made, but EVP_DigestInit_ex2() can be called to
+initialize a new digest operation.
 
 =item EVP_DigestFinalXOF()
 
index f72d3da1ce8e13c8c43d9ef26aff030c6f5c909c..205b0c59be6f339ba1d61cf92fcdad86fcfdea0b 100644 (file)
@@ -30,6 +30,21 @@ Known names are "BLAKE2B-512" and "BLAKE2b512".
 This implementation supports the common gettable parameters described
 in L<EVP_MD-common(7)>.
 
+=head2 Settable Context Parameters
+
+The BLAKE2B-512 implementation supports the following L<OSSL_PARAM(3)> entries,
+settable for an B<EVP_MD_CTX> with L<EVP_MD_CTX_set_params(3)>:
+
+=over 4
+
+=item "size" (B<OSSL_DIGEST_PARAM_SIZE>) <unsigned integer>
+
+Sets a different digest length for the L<EVP_DigestFinal(3)> output.
+The value of the "size" parameter should not exceed 255 and it must be set
+during the L<EVP_DigestInit_ex2(3)> call.
+
+=back
+
 =head1 SEE ALSO
 
 L<provider-digest(7)>, L<OSSL_PROVIDER-default(7)>
index 34bbd7ed37d5468d8cda1fef997bb522a344b0f8..d31627b92eefcd80ccb53863d55ac1130a208327 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <openssl/crypto.h>
+#include <openssl/proverr.h>
 #include "prov/blake2.h"
 #include "prov/digestcommon.h"
 #include "prov/implementations.h"
@@ -83,14 +84,23 @@ static int blake2b512_internal_final(void *ctx, unsigned char *out,
                                      size_t *outl, size_t outsz)
 {
     struct blake2b_md_data_st *b_ctx;
-    
+
     b_ctx = (struct blake2b_md_data_st *)ctx;
-    *outl = b_ctx->ctx.outlen;
 
     if (!ossl_prov_is_running())
         return 0;
 
-    return (outsz > 0) ? ossl_blake2b_final(out, ctx) : 1;
+    *outl = b_ctx->ctx.outlen;
+
+    if (outsz == 0)
+       return 1;
+
+    if (outsz < *outl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE);
+        return 0;
+    }
+
+    return ossl_blake2b_final(out, ctx);
 }
 
 static int blake2b512_get_params(OSSL_PARAM params[])
@@ -98,8 +108,8 @@ static int blake2b512_get_params(OSSL_PARAM params[])
     return ossl_digest_default_get_params(params, BLAKE2B_BLOCKBYTES, 64, 0);
 }
 
-const OSSL_DISPATCH ossl_blake2b512_functions[] =
-    { {OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))blake2b512_newctx},
+const OSSL_DISPATCH ossl_blake2b512_functions[] = {
+    {OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))blake2b512_newctx},
     {OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))ossl_blake2b_update},
     {OSSL_FUNC_DIGEST_FINAL, (void (*)(void))blake2b512_internal_final},
     {OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))blake2b512_freectx},
@@ -108,8 +118,13 @@ const OSSL_DISPATCH ossl_blake2b512_functions[] =
     {OSSL_FUNC_DIGEST_GETTABLE_PARAMS,
      (void (*)(void))ossl_digest_default_gettable_params},
     {OSSL_FUNC_DIGEST_INIT, (void (*)(void))blake2b512_internal_init},
+    {OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS,
+     (void (*)(void))ossl_blake2b_gettable_ctx_params},
     {OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS,
      (void (*)(void))ossl_blake2b_settable_ctx_params},
+    {OSSL_FUNC_DIGEST_GET_CTX_PARAMS,
+     (void (*)(void))ossl_blake2b_get_ctx_params},
     {OSSL_FUNC_DIGEST_SET_CTX_PARAMS,
-     (void (*)(void))ossl_blake2b_set_ctx_params}, {0, NULL} };
-
+     (void (*)(void))ossl_blake2b_set_ctx_params},
+    {0, NULL}
+};
index 0e3e894a43bd44f1eee1e978897e15288de69211..ee61de8a72b501ac9c9a54e124c0358509a15cca 100644 (file)
 #include <openssl/core_names.h>
 #include <openssl/proverr.h>
 #include <openssl/err.h>
+#include "internal/numbers.h"
 #include "blake2_impl.h"
 #include "prov/blake2.h"
 
-static const OSSL_PARAM known_blake2b_settable_ctx_params[] = {
-    {OSSL_DIGEST_PARAM_XOFLEN, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
+static const OSSL_PARAM known_blake2b_ctx_params[] = {
+    {OSSL_DIGEST_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0},
     OSSL_PARAM_END
 };
 
+const OSSL_PARAM *ossl_blake2b_gettable_ctx_params(ossl_unused void *ctx,
+                                                   ossl_unused void *pctx)
+{
+    return known_blake2b_ctx_params;
+}
+
 const OSSL_PARAM *ossl_blake2b_settable_ctx_params(ossl_unused void *ctx,
                                                    ossl_unused void *pctx)
 {
-    return known_blake2b_settable_ctx_params;
+    return known_blake2b_ctx_params;
+}
+
+int ossl_blake2b_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+    struct blake2b_md_data_st *mdctx = vctx;
+    OSSL_PARAM *p;
+
+    BLAKE2B_CTX *ctx = &mdctx->ctx;
+
+    if (ctx == NULL)
+        return 0;
+    if (params == NULL)
+        return 1;
+
+    p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE);
+    if (p != NULL
+        && !OSSL_PARAM_set_uint(p, (unsigned int)mdctx->params.digest_length)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+
+    return 1;
 }
 
 int ossl_blake2b_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
-    size_t xoflen;
+    size_t size;
     struct blake2b_md_data_st *mdctx = vctx;
     const OSSL_PARAM *p;
 
@@ -47,13 +76,17 @@ int ossl_blake2b_set_ctx_params(void *vctx, const OSSL_PARAM params[])
     if (params == NULL)
         return 1;
 
-    p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_XOFLEN);
+    p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_SIZE);
     if (p != NULL) {
-        if (!OSSL_PARAM_get_size_t(p, &xoflen)) {
+        if (!OSSL_PARAM_get_size_t(p, &size)) {
             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
             return 0;
         }
-        ossl_blake2b_param_set_digest_length(&mdctx->params, (uint8_t)xoflen);
+        if (size < 1 || size > UINT8_MAX) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE);
+            return 0;
+        }
+        ossl_blake2b_param_set_digest_length(&mdctx->params, (uint8_t)size);
     }
 
     return 1;
index bcd0bb9bcd4a4fca00de471cebbb19f27aa4cec9..445fd89aa21b5f958ac33a8934bebab9739741a8 100644 (file)
@@ -94,7 +94,9 @@ int ossl_blake2b_init_key(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P,
 int ossl_blake2b_update(BLAKE2B_CTX *c, const void *data, size_t datalen);
 int ossl_blake2b_final(unsigned char *md, BLAKE2B_CTX *c);
 
+OSSL_FUNC_digest_get_ctx_params_fn ossl_blake2b_get_ctx_params;
 OSSL_FUNC_digest_set_ctx_params_fn ossl_blake2b_set_ctx_params;
+OSSL_FUNC_digest_gettable_ctx_params_fn ossl_blake2b_gettable_ctx_params;
 OSSL_FUNC_digest_settable_ctx_params_fn ossl_blake2b_settable_ctx_params;
 
 /*
index d93381c410440cdee906d8a41d1b8fdcdb2b38a4..fe84ab54cad7c399b75010867ae537d30dfc243a 100644 (file)
@@ -823,12 +823,12 @@ static int blake2b_md(EVP_MD *md, void *out, size_t outlen, const void *in,
     if ((ctx = EVP_MD_CTX_create()) == NULL)
         return 0;
 
-    par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &outlen);
+    par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen);
     par[1] = OSSL_PARAM_construct_end();
 
     ret = EVP_DigestInit_ex2(ctx, md, par) == 1
         && EVP_DigestUpdate(ctx, in, inlen) == 1
-        && EVP_DigestFinalXOF(ctx, out, outlen) == 1;
+        && EVP_DigestFinal_ex(ctx, out, NULL) == 1;
 
     EVP_MD_CTX_free(ctx);
     return ret;
@@ -868,14 +868,14 @@ static int blake2b_long(EVP_MD *md, EVP_MAC *mac, unsigned char *out,
         return 0;
 
     outlen_md = (outlen <= BLAKE2B_OUTBYTES) ? outlen : BLAKE2B_OUTBYTES;
-    par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &outlen_md);
+    par[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &outlen_md);
     par[1] = OSSL_PARAM_construct_end();
 
     ret = EVP_DigestInit_ex2(ctx, md, par) == 1
         && EVP_DigestUpdate(ctx, outlen_bytes, sizeof(outlen_bytes)) == 1
         && EVP_DigestUpdate(ctx, in, inlen) == 1
-        && EVP_DigestFinalXOF(ctx, (outlen > BLAKE2B_OUTBYTES) ? outbuf : out,
-                outlen_md) == 1;
+        && EVP_DigestFinal_ex(ctx, (outlen > BLAKE2B_OUTBYTES) ? outbuf : out,
+                              NULL) == 1;
 
     if (ret == 0)
         goto fail;
index bd1a7cc122f370e811000e36d538ff44ee8f9016..487d6a1ad2e06e9c8c5e980a39f7a69c0fd0f6fc 100644 (file)
@@ -355,6 +355,8 @@ typedef struct digest_data_st {
     int pad_type;
     /* XOF mode? */
     int xof;
+    /* Size for variable output length but non-XOF */
+    size_t digest_size;
 } DIGEST_DATA;
 
 static int digest_test_init(EVP_TEST *t, const char *alg)
@@ -410,6 +412,15 @@ static int digest_test_parse(EVP_TEST *t,
         return (mdata->pad_type = atoi(value)) > 0;
     if (strcmp(keyword, "XOF") == 0)
         return (mdata->xof = atoi(value)) > 0;
+    if (strcmp(keyword, "OutputSize") == 0) {
+        int sz;
+
+        sz = atoi(value);
+        if (sz < 0)
+            return -1;
+        mdata->digest_size = sz;
+        return 1;
+    }
     return 0;
 }
 
@@ -463,6 +474,10 @@ static int digest_test_run(EVP_TEST *t)
         *p++ = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN,
                                            &expected->output_len);
     }
+    if (expected->digest_size > 0) {
+        *p++ = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE,
+                                           &expected->digest_size);
+    }
     if (expected->pad_type > 0)
         *p++ = OSSL_PARAM_construct_int(OSSL_DIGEST_PARAM_PAD_TYPE,
                                         &expected->pad_type);
index 02b3df9e9c6d14bdc35af39c5979d752aafe1d79..474e659142981bae07ca455e3cdc03671ed11766 100644 (file)
@@ -92,10 +92,10 @@ Output = DF0A9D0C212843A6A934E3902B2DD30D17FBA5F969D2030B12A546D8A6A45E80CF5635F
 
 Digest = BLAKE2b512
 Input =
-XOF = 1
+OutputSize = 32
 Output = 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8
 
 Digest = BLAKE2b512
 Input = 61
-XOF = 1
+OutputSize = 32
 Output = 8928aae63c84d87ea098564d1e03ad813f107add474e56aedd286349c0c03ea4