Adding the READ method for SHAKE
Jussi Kivilinna
jussi.kivilinna at iki.fi
Thu Jun 22 08:00:37 CEST 2023
Hello,
On 20.6.2023 3.43, NIIBE Yutaka wrote:
> Hello,
>
> I'd like to propose a change for the SHAKE implementation.
>
> This comes in the context of a bug in gcry_pk_hash_sign:
>
> https://dev.gnupg.org/T6539
>
> I learned that there is a use case of SHAKE in CMS, specified in RFC
> 8802.
>
> Use of the SHAKE One-Way Hash Functions in the Cryptographic Message
> Syntax (CMS): https://www.rfc-editor.org/rfc/rfc8702.html
>
> In RFC 8802, SHAKE128 is used with 32-byte output, and SHAKE256 is used
> with 64-byte output.
>
> I think that: when a digest function is used for signing, fixed size
> makes sense, as the matter is the strength of the hash function.
>
> Considering this use case for signing, I'd like to add the READ method
> and the definition of length to the SHAKE digest functions. Attached is
> the change.
>
> How do you think?
I think this is good change. For example, Crypto++ uses same digest lengths
as this change... 32B for SHAKE128 and 64B for SHAKE256.
One thing to notice is that `keccak_final()` prepares `keccak_read()` output
only for SHA3 functions (see `if (suffix == SHA3_DELIMITED_SUFFIX)`). Not
sure how `keccak_read()` should work for SHAKE.
Simultaneous use of `md_extract` and `md_read` on same SHAKE digest object
probably does not make much sense and maybe those should block another
after either one is used first time. So could add some new flags to
KECCAK_CONTEXT... `shake_in_read_mode` and `skake_in_extract_mode` etc.
So, in `keccak_read()` we'd have something like:
static byte *
keccak_read (void *context)
{
KECCAK_CONTEXT *ctx = (KECCAK_CONTEXT *) context;
KECCAK_STATE *hd = &ctx->state;
if (ctx->suffix == SHAKE_DELIMITED_SUFFIX)
{
if (ctx->skake_in_extract_mode)
{
/* Already in extract mode? Invalid use... should/can return NULL? */
return NULL;
}
if (!ctx->skake_in_read_mode)
{
ctx->skake_in_read_mode = 1;
#ifdef USE_S390X_CRYPTO
if (ctx->kimd_func)
{
/* TODO: need to check if 'hd' can be direct output here: */
keccak_extract_s390x (context, (void *)hd, <digestlen>);
return (byte *)&hd->u;
}
#endif
/* Switch to the squeezing phase. */
burn = ctx->ops->permute(hd);
/* Squeeze out the SHAKE digest. */
nburn = ctx->ops->extract(hd, 0, (void *)hd, <digestlen>);
burn = nburn > burn ? nburn : burn;
if (burn)
_gcry_burn_stack (burn);
}
}
return (byte *)&hd->u;
}
`keccak_extract` would have new checks:
if (ctx->skake_in_read_mode)
return <error>; /* Need to add return type for keccak_extract. */
if (!ctx->shake_in_extract_mode)
ctx->shake_in_extract_mode = 1;
I can take deeper look into this in few days.
-Jussi
>
> ==========================
> diff --git a/cipher/keccak.c b/cipher/keccak.c
> index 22c40302..76e08cb5 100644
> --- a/cipher/keccak.c
> +++ b/cipher/keccak.c
> @@ -1630,8 +1630,8 @@ const gcry_md_spec_t _gcry_digest_spec_sha3_512 =
> const gcry_md_spec_t _gcry_digest_spec_shake128 =
> {
> GCRY_MD_SHAKE128, {0, 1},
> - "SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 0,
> - shake128_init, keccak_write, keccak_final, NULL, keccak_extract,
> + "SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 32,
> + shake128_init, keccak_write, keccak_final, keccak_read, keccak_extract,
> _gcry_shake128_hash_buffers,
> sizeof (KECCAK_CONTEXT),
> run_selftests
> @@ -1639,8 +1639,8 @@ const gcry_md_spec_t _gcry_digest_spec_shake128 =
> const gcry_md_spec_t _gcry_digest_spec_shake256 =
> {
> GCRY_MD_SHAKE256, {0, 1},
> - "SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 0,
> - shake256_init, keccak_write, keccak_final, NULL, keccak_extract,
> + "SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 64,
> + shake256_init, keccak_write, keccak_final, keccak_read, keccak_extract,
> _gcry_shake256_hash_buffers,
> sizeof (KECCAK_CONTEXT),
> run_selftests
More information about the Gcrypt-devel
mailing list