Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLAKE2 refactoring of common code bringing variable length support to BLAKE2s #22444

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ OpenSSL 3.3

### Changes between 3.2 and 3.3 [xx XXX xxxx]

* none yet
* The BLAKE2s hash algorithm matches BLAKE2b's support
for configurable output length.

*Ahelenia Ziemiańska*

OpenSSL 3.2
-----------
Expand Down
5 changes: 2 additions & 3 deletions doc/man3/EVP_blake2b512.pod
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ calling these functions multiple times and should consider using
L<EVP_MD_fetch(3)> with L<EVP_MD-BLAKE2(7)> instead.
See L<crypto(7)/Performance> for further information.

While the BLAKE2b and BLAKE2s algorithms supports a variable length digest,
this implementation outputs a digest of a fixed length (the maximum length
supported), which is 512-bits for BLAKE2b and 256-bits for BLAKE2s.
Both algorithms support a variable-length digest,
but this is only available through L<EVP_MD-BLAKE2(7)>.

=head1 RETURN VALUES

Expand Down
286 changes: 172 additions & 114 deletions providers/implementations/digests/blake2_prov.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,123 +8,181 @@
*/

#include <openssl/crypto.h>
#include <openssl/core_names.h>
#include <openssl/proverr.h>
#include <openssl/err.h>
#include "prov/blake2.h"
#include "prov/digestcommon.h"
#include "prov/implementations.h"

static int ossl_blake2s256_init(void *ctx)
{
BLAKE2S_PARAM P;

ossl_blake2s_param_init(&P);
return ossl_blake2s_init((BLAKE2S_CTX *)ctx, &P);
}

static int ossl_blake2b512_init(void *ctx)
{
struct blake2b_md_data_st *mdctx = ctx;
uint8_t digest_length = mdctx->params.digest_length;

ossl_blake2b_param_init(&mdctx->params);
if (digest_length != 0)
mdctx->params.digest_length = digest_length;
return ossl_blake2b_init(&mdctx->ctx, &mdctx->params);
}

/* ossl_blake2s256_functions */
IMPLEMENT_digest_functions(blake2s256, BLAKE2S_CTX,
BLAKE2S_BLOCKBYTES, BLAKE2S_DIGEST_LENGTH, 0,
ossl_blake2s256_init, ossl_blake2s_update,
ossl_blake2s_final)

/* ossl_blake2b512_functions */

static OSSL_FUNC_digest_init_fn blake2b512_internal_init;
static OSSL_FUNC_digest_newctx_fn blake2b512_newctx;
static OSSL_FUNC_digest_freectx_fn blake2b512_freectx;
static OSSL_FUNC_digest_dupctx_fn blake2b512_dupctx;
static OSSL_FUNC_digest_final_fn blake2b512_internal_final;
static OSSL_FUNC_digest_get_params_fn blake2b512_get_params;

static int blake2b512_internal_init(void *ctx, const OSSL_PARAM params[])
{
return ossl_prov_is_running() && ossl_blake2b_set_ctx_params(ctx, params)
&& ossl_blake2b512_init(ctx);
}

static void *blake2b512_newctx(void *prov_ctx)
{
struct blake2b_md_data_st *ctx;

ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) : NULL;
return ctx;
}

static void blake2b512_freectx(void *vctx)
{
struct blake2b_md_data_st *ctx;

ctx = (struct blake2b_md_data_st *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}

static void *blake2b512_dupctx(void *ctx)
{
struct blake2b_md_data_st *in, *ret;

in = (struct blake2b_md_data_st *)ctx;
ret = ossl_prov_is_running()? OPENSSL_malloc(sizeof(*ret)) : NULL;
if (ret != NULL)
*ret = *in;
return ret;
}

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;

if (!ossl_prov_is_running())
return 0;

*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},
{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_DUPCTX, (void (*)(void))blake2b512_dupctx},
{OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))blake2b512_get_params},
{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}
#define IMPLEMENT_BLAKE_functions(variant, VARIANT, variantsize) \
static const OSSL_PARAM known_blake##variant##_ctx_params[] = { \
{OSSL_DIGEST_PARAM_SIZE, OSSL_PARAM_UNSIGNED_INTEGER, NULL, 0, 0}, \
OSSL_PARAM_END \
}; \
\
const OSSL_PARAM *ossl_blake##variant##_gettable_ctx_params(ossl_unused void *ctx, \
ossl_unused void *pctx) \
{ \
return known_blake##variant##_ctx_params; \
} \
\
const OSSL_PARAM *ossl_blake##variant##_settable_ctx_params(ossl_unused void *ctx, \
ossl_unused void *pctx) \
{ \
return known_blake##variant##_ctx_params; \
} \
\
int ossl_blake##variant##_get_ctx_params(void *vctx, OSSL_PARAM params[]) \
{ \
struct blake##variant##_md_data_st *mdctx = vctx; \
OSSL_PARAM *p; \
\
BLAKE##VARIANT##_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_blake##variant##_set_ctx_params(void *vctx, const OSSL_PARAM params[]) \
{ \
size_t size; \
struct blake##variant##_md_data_st *mdctx = vctx; \
const OSSL_PARAM *p; \
\
BLAKE##VARIANT##_CTX *ctx = &mdctx->ctx; \
\
if (ctx == NULL) \
return 0; \
if (params == NULL) \
return 1; \
\
p = OSSL_PARAM_locate_const(params, OSSL_DIGEST_PARAM_SIZE); \
if (p != NULL) { \
if (!OSSL_PARAM_get_size_t(p, &size)) { \
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); \
return 0; \
} \
if (size < 1 || size > UINT8_MAX) { \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this upper constraint correct.. RFC 7693 seems to have 1 <= outlen <=64

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libb2 also refuses lengths longer than the hash, but the paper says "put 0xFFFFFFFF in there if you don't know" () – I daren't have a take on this, I'm just adding backslashes.

ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_SIZE); \
return 0; \
} \
ossl_blake##variant##_param_set_digest_length(&mdctx->params, (uint8_t)size); \
} \
\
return 1; \
} \
\
static int ossl_blake##variantsize##_init(void *ctx) \
{ \
struct blake##variant##_md_data_st *mdctx = ctx; \
uint8_t digest_length = mdctx->params.digest_length; \
\
ossl_blake##variant##_param_init(&mdctx->params); \
if (digest_length != 0) \
mdctx->params.digest_length = digest_length; \
return ossl_blake##variant##_init(&mdctx->ctx, &mdctx->params); \
} \
\
static OSSL_FUNC_digest_init_fn blake##variantsize##_internal_init; \
static OSSL_FUNC_digest_newctx_fn blake##variantsize##_newctx; \
static OSSL_FUNC_digest_freectx_fn blake##variantsize##_freectx; \
static OSSL_FUNC_digest_dupctx_fn blake##variantsize##_dupctx; \
static OSSL_FUNC_digest_final_fn blake##variantsize##_internal_final; \
static OSSL_FUNC_digest_get_params_fn blake##variantsize##_get_params; \
\
static int blake##variantsize##_internal_init(void *ctx, const OSSL_PARAM params[]) \
{ \
return ossl_prov_is_running() && ossl_blake##variant##_set_ctx_params(ctx, params) \
&& ossl_blake##variantsize##_init(ctx); \
} \
\
static void *blake##variantsize##_newctx(void *prov_ctx) \
{ \
struct blake##variant##_md_data_st *ctx; \
\
ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx)) : NULL; \
return ctx; \
} \
\
static void blake##variantsize##_freectx(void *vctx) \
{ \
struct blake##variant##_md_data_st *ctx; \
\
ctx = (struct blake##variant##_md_data_st *)vctx; \
OPENSSL_clear_free(ctx, sizeof(*ctx)); \
} \
\
static void *blake##variantsize##_dupctx(void *ctx) \
{ \
struct blake##variant##_md_data_st *in, *ret; \
\
in = (struct blake##variant##_md_data_st *)ctx; \
ret = ossl_prov_is_running()? OPENSSL_malloc(sizeof(*ret)) : NULL; \
if (ret != NULL) \
*ret = *in; \
return ret; \
} \
\
static int blake##variantsize##_internal_final(void *ctx, unsigned char *out, \
size_t *outl, size_t outsz) \
{ \
struct blake##variant##_md_data_st *b_ctx; \
\
b_ctx = (struct blake##variant##_md_data_st *)ctx; \
\
if (!ossl_prov_is_running()) \
return 0; \
\
*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_blake##variant##_final(out, ctx); \
} \
\
static int blake##variantsize##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_digest_default_get_params(params, BLAKE##VARIANT##_BLOCKBYTES, 64, 0); \
} \
\
const OSSL_DISPATCH ossl_blake##variantsize##_functions[] = { \
{OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))blake##variantsize##_newctx}, \
{OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))ossl_blake##variant##_update}, \
{OSSL_FUNC_DIGEST_FINAL, (void (*)(void))blake##variantsize##_internal_final}, \
{OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))blake##variantsize##_freectx}, \
{OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))blake##variantsize##_dupctx}, \
{OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))blake##variantsize##_get_params}, \
{OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \
(void (*)(void))ossl_digest_default_gettable_params}, \
{OSSL_FUNC_DIGEST_INIT, (void (*)(void))blake##variantsize##_internal_init}, \
{OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS, \
(void (*)(void))ossl_blake##variant##_gettable_ctx_params}, \
{OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \
(void (*)(void))ossl_blake##variant##_settable_ctx_params}, \
{OSSL_FUNC_DIGEST_GET_CTX_PARAMS, \
(void (*)(void))ossl_blake##variant##_get_ctx_params}, \
{OSSL_FUNC_DIGEST_SET_CTX_PARAMS, \
(void (*)(void))ossl_blake##variant##_set_ctx_params}, \
{0, NULL} \
};

IMPLEMENT_BLAKE_functions(2s, 2S, 2s256)
IMPLEMENT_BLAKE_functions(2b, 2B, 2b512)