#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
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;
# include "config.h"
#endif
+#include <assert.h>
+#include <limits.h>
#include <stddef.h>
#include <string.h>
#include "nettle-write.h"
+#define INDEX_HIGH_BIT (~((UINT_MAX) >> 1))
+
void
sha3_256_shake (struct sha3_256_ctx *ctx,
size_t length,
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;
+}
#include "sha3.h"
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
const struct nettle_hash nettle_shake256 =
{
"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(""),
"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);
}