It will work only if OSSL_DIGEST_PARAM_XOFLEN is set.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/24105)
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 };
return 0;
}
-int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
+int ossl_keccak_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen, size_t mdlen)
{
int ret = ossl_sha3_init(ctx, pad, bitlen);
if (ret)
- ctx->md_size *= 2;
+ ctx->md_size = mdlen / 8;
return ret;
}
void ossl_sha3_reset(KECCAK1600_CTX *ctx);
int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);
-int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad,
- size_t bitlen);
+int ossl_keccak_init(KECCAK1600_CTX *ctx, unsigned char pad,
+ size_t typelen, size_t mdlen);
int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
int ossl_sha3_final(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen);
int ossl_sha3_squeeze(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen);
#include <openssl/params.h>
#include <openssl/err.h>
#include <openssl/proverr.h>
+#include "internal/numbers.h"
#include "internal/sha3.h"
#include "prov/digestcommon.h"
#include "prov/implementations.h"
if (!ossl_prov_is_running())
return 0;
+ if (ctx->md_size == SIZE_MAX) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
+ return 0;
+ }
if (outlen > 0)
ret = ctx->meth.final(ctx, out, ctx->md_size);
return ctx; \
}
-#define SHAKE_newctx(typ, uname, name, bitlen, pad) \
+#define SHAKE_newctx(typ, uname, name, bitlen, mdlen, pad) \
static OSSL_FUNC_digest_newctx_fn name##_newctx; \
static void *name##_newctx(void *provctx) \
{ \
\
if (ctx == NULL) \
return NULL; \
- ossl_sha3_init(ctx, pad, bitlen); \
+ ossl_keccak_init(ctx, pad, bitlen, mdlen); \
+ if (mdlen == 0) \
+ ctx->md_size = SIZE_MAX; \
SHAKE_SET_MD(uname, typ) \
return ctx; \
}
\
if (ctx == NULL) \
return NULL; \
- ossl_keccak_kmac_init(ctx, pad, bitlen); \
+ ossl_keccak_init(ctx, pad, bitlen, 2 * bitlen); \
KMAC_SET_MD(bitlen) \
return ctx; \
}
SHA3_FLAGS)
#define IMPLEMENT_SHAKE_functions(bitlen) \
- SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f') \
+ SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, \
+ 0 /* no default md length */, '\x1f') \
PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \
- SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
+ SHA3_BLOCKSIZE(bitlen), 0, \
SHAKE_FLAGS)
+
#define IMPLEMENT_KMAC_functions(bitlen) \
KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \
PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen, \
EVP_MD_CTX *ctx = NULL;
unsigned char out[sizeof(shake256_output)];
+ /* Test that EVP_DigestFinal without setting XOFLEN fails */
if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
return 0;
if (!TEST_true(EVP_DigestUpdate(ctx, shake256_input,
- sizeof(shake256_input)))
- || !TEST_true(EVP_DigestFinal(ctx, out, &digest_length))
- || !TEST_uint_eq(digest_length, 32)
- || !TEST_mem_eq(out, digest_length,
- shake256_output, digest_length)
+ sizeof(shake256_input))))
+ return 0;
+ ERR_set_mark();
+ if (!TEST_false(EVP_DigestFinal(ctx, out, &digest_length))) {
+ ERR_clear_last_mark();
+ return 0;
+ }
+ ERR_pop_to_mark();
+ EVP_MD_CTX_free(ctx);
+
+ /* However EVP_DigestFinalXOF must work */
+ if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
+ return 0;
+ if (!TEST_true(EVP_DigestUpdate(ctx, shake256_input,
+ sizeof(shake256_input))))
+ return 0;
+ if (!TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out)))
+ || !TEST_mem_eq(out, sizeof(out),
+ shake256_output, sizeof(shake256_output))
|| !TEST_false(EVP_DigestFinalXOF(ctx, out, sizeof(out))))
goto err;
ret = 1;
};
subtest "SHAKE digest generation with no xoflen set `dgst` CLI" => sub {
- plan tests => 1;
+ plan tests => 2;
my $testdata = srctop_file('test', 'data.bin');
- my @xofdata = run(app(['openssl', 'dgst', '-shake128', $testdata], stderr => "outerr.txt"), capture => 1);
- chomp(@xofdata);
- my $expected = qr/SHAKE-128\(\Q$testdata\E\)= bb565dac72640109e1c926ef441d3fa6/;
- ok($xofdata[0] =~ $expected, "Check short digest is output");
+ ok(!run(app(['openssl', 'dgst', '-shake128', $testdata])), "SHAKE128 must fail without xoflen");
+ ok(!run(app(['openssl', 'dgst', '-shake256', $testdata])), "SHAKE256 must fail without xoflen");
};
SKIP: {