From: Tomas Mraz Date: Tue, 24 Oct 2023 11:44:26 +0000 (+0200) Subject: Blake2b: Use OSSL_DIGEST_PARAM_SIZE as settable instead of XOFLEN X-Git-Tag: openssl-3.2.0-beta1~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6a0ae393dd554eb718e5148696e8f437d4faae5b;p=thirdparty%2Fopenssl.git Blake2b: Use OSSL_DIGEST_PARAM_SIZE as settable instead of XOFLEN 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 Reviewed-by: Paul Dale Reviewed-by: Tim Hudson Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22491) --- diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 01f54792f6f..42331703da3 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -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; diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod index 9b5fda08ee9..409630e5d4d 100644 --- a/doc/man3/EVP_DigestInit.pod +++ b/doc/man3/EVP_DigestInit.pod @@ -282,9 +282,11 @@ data. Retrieves the digest value from I and places it in I. If the I 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, at most -B 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 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() diff --git a/doc/man7/EVP_MD-BLAKE2.pod b/doc/man7/EVP_MD-BLAKE2.pod index f72d3da1ce8..205b0c59be6 100644 --- a/doc/man7/EVP_MD-BLAKE2.pod +++ b/doc/man7/EVP_MD-BLAKE2.pod @@ -30,6 +30,21 @@ Known names are "BLAKE2B-512" and "BLAKE2b512". This implementation supports the common gettable parameters described in L. +=head2 Settable Context Parameters + +The BLAKE2B-512 implementation supports the following L entries, +settable for an B with L: + +=over 4 + +=item "size" (B) + +Sets a different digest length for the L output. +The value of the "size" parameter should not exceed 255 and it must be set +during the L call. + +=back + =head1 SEE ALSO L, L diff --git a/providers/implementations/digests/blake2_prov.c b/providers/implementations/digests/blake2_prov.c index 34bbd7ed37d..d31627b92ee 100644 --- a/providers/implementations/digests/blake2_prov.c +++ b/providers/implementations/digests/blake2_prov.c @@ -8,6 +8,7 @@ */ #include +#include #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} +}; diff --git a/providers/implementations/digests/blake2b_prov.c b/providers/implementations/digests/blake2b_prov.c index 0e3e894a43b..ee61de8a72b 100644 --- a/providers/implementations/digests/blake2b_prov.c +++ b/providers/implementations/digests/blake2b_prov.c @@ -20,23 +20,52 @@ #include #include #include +#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; diff --git a/providers/implementations/include/prov/blake2.h b/providers/implementations/include/prov/blake2.h index bcd0bb9bcd4..445fd89aa21 100644 --- a/providers/implementations/include/prov/blake2.h +++ b/providers/implementations/include/prov/blake2.h @@ -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; /* diff --git a/providers/implementations/kdfs/argon2.c b/providers/implementations/kdfs/argon2.c index d93381c4104..fe84ab54cad 100644 --- a/providers/implementations/kdfs/argon2.c +++ b/providers/implementations/kdfs/argon2.c @@ -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; diff --git a/test/evp_test.c b/test/evp_test.c index bd1a7cc122f..487d6a1ad2e 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -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); diff --git a/test/recipes/30-test_evp_data/evpmd_blake.txt b/test/recipes/30-test_evp_data/evpmd_blake.txt index 02b3df9e9c6..474e6591429 100644 --- a/test/recipes/30-test_evp_data/evpmd_blake.txt +++ b/test/recipes/30-test_evp_data/evpmd_blake.txt @@ -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