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;
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()
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)>
*/
#include <openssl/crypto.h>
+#include <openssl/proverr.h>
#include "prov/blake2.h"
#include "prov/digestcommon.h"
#include "prov/implementations.h"
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[])
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},
{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}
+};
#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;
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;
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;
/*
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;
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;
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)
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;
}
*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);
Digest = BLAKE2b512
Input =
-XOF = 1
+OutputSize = 32
Output = 0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8
Digest = BLAKE2b512
Input = 61
-XOF = 1
+OutputSize = 32
Output = 8928aae63c84d87ea098564d1e03ad813f107add474e56aedd286349c0c03ea4