From: Daiki Ueno Date: Mon, 11 Mar 2024 00:22:18 +0000 (-0400) Subject: Additional API for SHAKE streaming read. X-Git-Tag: nettle_3.10rc1~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dd9e7cb1f7c1c88cb927eff1ff4092efc2e595f4;p=thirdparty%2Fnettle.git Additional API for SHAKE streaming read. This adds an alternative function sha3_256_shake_output in the SHAKE256 support, which enables to read output multiple times in an incremental manner. Signed-off-by: Daiki Ueno --- diff --git a/sha3.h b/sha3.h index 9220829d..4b7e186c 100644 --- a/sha3.h +++ b/sha3.h @@ -49,6 +49,7 @@ extern "C" { #define sha3_256_update nettle_sha3_256_update #define sha3_256_digest nettle_sha3_256_digest #define sha3_256_shake nettle_sha3_256_shake +#define sha3_256_shake_output nettle_sha3_256_shake_output #define sha3_384_init nettle_sha3_384_init #define sha3_384_update nettle_sha3_384_update #define sha3_384_digest nettle_sha3_384_digest @@ -143,6 +144,13 @@ sha3_256_shake(struct sha3_256_ctx *ctx, size_t length, uint8_t *digest); +/* Unlike sha3_256_shake, this function can be called multiple times + to retrieve output from shake256 in an incremental manner */ +void +sha3_256_shake_output(struct sha3_256_ctx *ctx, + size_t length, + uint8_t *digest); + struct sha3_384_ctx { struct sha3_state state; diff --git a/shake256.c b/shake256.c index f5c77a43..9c418395 100644 --- a/shake256.c +++ b/shake256.c @@ -36,6 +36,8 @@ # include "config.h" #endif +#include +#include #include #include @@ -44,6 +46,8 @@ #include "nettle-write.h" +#define INDEX_HIGH_BIT (~((UINT_MAX) >> 1)) + void sha3_256_shake (struct sha3_256_ctx *ctx, size_t length, @@ -61,3 +65,59 @@ sha3_256_shake (struct sha3_256_ctx *ctx, sha3_256_init (ctx); } + +void +sha3_256_shake_output (struct sha3_256_ctx *ctx, + size_t length, + uint8_t *digest) +{ + unsigned index, left; + + /* We use the leftmost bit as a flag to indicate SHAKE is initialized. */ + if (ctx->index & INDEX_HIGH_BIT) + index = ctx->index & ~INDEX_HIGH_BIT; + else + { + /* This is the first call of _shake_output. */ + _sha3_pad_shake (&ctx->state, sizeof (ctx->block), ctx->block, ctx->index); + /* Point at the end of block to trigger fill in of the buffer. */ + index = sizeof (ctx->block); + } + + assert (index <= sizeof (ctx->block)); + + /* Write remaining data from the buffer. */ + left = sizeof (ctx->block) - index; + if (length <= left) + { + memcpy (digest, ctx->block + index, length); + ctx->index = (index + length) | INDEX_HIGH_BIT; + return; + } + else + { + memcpy (digest, ctx->block + index, left); + length -= left; + digest += left; + } + + /* Write full blocks. */ + while (length > sizeof (ctx->block)) + { + _nettle_write_le64 (sizeof (ctx->block), digest, ctx->state.a); + length -= sizeof (ctx->block); + digest += sizeof (ctx->block); + sha3_permute (&ctx->state); + } + + if (length > 0) + { + /* Fill in the buffer for next call. */ + _nettle_write_le64 (sizeof (ctx->block), ctx->block, ctx->state.a); + sha3_permute (&ctx->state); + memcpy (digest, ctx->block, length); + ctx->index = length | INDEX_HIGH_BIT; + } + else + ctx->index = sizeof (ctx->block) | INDEX_HIGH_BIT; +} diff --git a/testsuite/shake256-test.c b/testsuite/shake256-test.c index b91417cb..016060e8 100644 --- a/testsuite/shake256-test.c +++ b/testsuite/shake256-test.c @@ -34,6 +34,8 @@ #include "sha3.h" +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + const struct nettle_hash nettle_shake256 = { "shake256", @@ -45,9 +47,36 @@ const struct nettle_hash nettle_shake256 = (nettle_hash_digest_func *) sha3_256_shake, }; +static void +test_incremental (const struct tstring *msg, + const struct tstring *digest, + size_t interval) +{ + struct sha3_256_ctx ctx; + size_t offset = 0; + uint8_t *buffer = xalloc (digest->length); + + sha3_256_init (&ctx); + sha3_256_update (&ctx, msg->length, msg->data); + + while (offset < digest->length) + { + size_t to_read = MIN(digest->length - offset, interval); + + sha3_256_shake_output (&ctx, to_read, buffer + offset); + + offset += to_read; + } + + ASSERT (MEMEQ (digest->length, digest->data, buffer)); + free (buffer); +} + void test_main(void) { + const struct tstring *msg, *digest; + /* Extracted from ShortMsgKAT_SHAKE256.txt. */ test_hash (&nettle_shake256, /* 0 octets */ SHEX(""), @@ -5937,4 +5966,33 @@ test_main(void) "805C7B7E2CFD54E0FAD62F0D8CA67A775DC4546AF9096F2EDB2" "21DB42843D65327861282DC946A0BA01A11863AB2D1DFD16E39" "73D4")); + + /* Test incremental API */ + msg = SHEX("3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F5623CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A15358F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0A3D84A2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764B2F83AADC66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43C70088B6183639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D817FC2534A52F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E085172E328807C02D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1"); + digest = SHEX("8A5199B4A7E133E264A86202720655894D48CFF344A928CF834" + "7F48379CEF347DFC5BCFFAB99B27B1F89AA2735E23D30088FFA" + "03B9EDB02B9635470AB9F1038985D55F9CA774572DD006470EA" + "65145469609F9FA0831BF1FFD842DC24ACADE27BD9816E3B5BF" + "2876CB112232A0EB4475F1DFF9F5C713D9FFD4CCB89AE5607FE" + "35731DF06317949EEF646E9591CF3BE53ADD6B7DD2B6096E2B3" + "FB06E662EC8B2D77422DAAD9463CD155204ACDBD38E319613F3" + "9F99B6DFB35CA9365160066DB19835888C2241FF9A731A4ACBB" + "5663727AAC34A401247FBAA7499E7D5EE5B69D31025E63D04C3" + "5C798BCA1262D5673A9CF0930B5AD89BD485599DC184528DA47" + "90F088EBD170B635D9581632D2FF90DB79665CED430089AF13C" + "9F21F6D443A818064F17AEC9E9C5457001FA8DC6AFBADBE3138" + "F388D89D0E6F22F66671255B210754ED63D81DCE75CE8F189B5" + "34E6D6B3539AA51E837C42DF9DF59C71E6171CD4902FE1BDC73" + "FB1775B5C754A1ED4EA7F3105FC543EE0418DAD256F3F6118EA" + "77114A16C15355B42877A1DB2A7DF0E155AE1D8670ABCEC3450" + "F4E2EEC9838F895423EF63D261138BAAF5D9F104CB5A957AEA0" + "6C0B9B8C78B0D441796DC0350DDEABB78A33B6F1F9E68EDE3D1" + "805C7B7E2CFD54E0FAD62F0D8CA67A775DC4546AF9096F2EDB2" + "21DB42843D65327861282DC946A0BA01A11863AB2D1DFD16E39" + "73D4"); + + test_incremental (msg, digest, 16); + test_incremental (msg, digest, SHA3_256_BLOCK_SIZE - 1); + test_incremental (msg, digest, SHA3_256_BLOCK_SIZE); + test_incremental (msg, digest, SHA3_256_BLOCK_SIZE + 1); }