From 2cfcc9e9d74447cb770255d1d8cb6f3722df22ba Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 20 Jan 2013 00:38:09 +0100 Subject: sha3: code shrink function old new delta sha3_hash 155 101 -54 Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 +-- libbb/hash_md5_sha.c | 91 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 606db7d..e520060 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1641,7 +1641,7 @@ typedef struct sha3_ctx_t { unsigned bytes_queued; } sha3_ctx_t; void md5_begin(md5_ctx_t *ctx) FAST_FUNC; -void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; +void md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; #define sha1_hash md5_hash @@ -1654,7 +1654,7 @@ void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; void sha3_begin(sha3_ctx_t *ctx) FAST_FUNC; void sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; -void sha3_end(sha3_ctx_t *ctx, uint8_t *resbuf) FAST_FUNC; +void sha3_end(sha3_ctx_t *ctx, void *resbuf) FAST_FUNC; extern uint32_t *global_crc32_table; uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index d23d4f6..b4d955e 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -56,7 +56,7 @@ static void FAST_FUNC common64_hash(md5_ctx_t *ctx, const void *buffer, size_t l len -= remaining; buffer = (const char *)buffer + remaining; bufpos += remaining; - /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ + /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */ bufpos -= 64; if (bufpos != 0) break; @@ -839,7 +839,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) len -= remaining; buffer = (const char *)buffer + remaining; bufpos += remaining; - /* clever way to do "if (bufpos != 128) break; ... ; bufpos = 0;" */ + /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */ bufpos -= 128; if (bufpos != 0) break; @@ -1079,63 +1079,90 @@ void FAST_FUNC sha3_begin(sha3_ctx_t *ctx) memset(ctx, 0, sizeof(*ctx)); } -void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buf, size_t bytes) +void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) { - const uint8_t *data = buf; - unsigned bytes_queued = ctx->bytes_queued; +#if SHA3_SMALL + const uint8_t *data = buffer; + unsigned bufpos = ctx->bytes_queued; + + while (1) { + unsigned remaining = SHA3_IBLK_BYTES - bufpos; + if (remaining > len) + remaining = len; + len -= remaining; + /* XOR data into buffer */ + while (remaining != 0) { + uint8_t *buf = (uint8_t*)ctx->state; + buf[bufpos] ^= *data++; + bufpos++; + remaining--; + } + /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */ + bufpos -= SHA3_IBLK_BYTES; + if (bufpos != 0) + break; + /* Buffer is filled up, process it */ + sha3_process_block72(ctx->state); + /*bufpos = 0; - already is */ + } + ctx->bytes_queued = bufpos + SHA3_IBLK_BYTES; +#else + /* +50 bytes code size, but a bit faster because of long-sized XORs */ + const uint8_t *data = buffer; + unsigned bufpos = ctx->bytes_queued; /* If already data in queue, continue queuing first */ - while (bytes != 0 && bytes_queued != 0) { - uint8_t *buffer = (uint8_t*)ctx->state; - buffer[bytes_queued] ^= *data++; - bytes--; - bytes_queued++; - if (bytes_queued == SHA3_IBLK_BYTES) { - sha3_process_block72(ctx->state); - bytes_queued = 0; + while (len != 0 && bufpos != 0) { + uint8_t *buf = (uint8_t*)ctx->state; + buf[bufpos] ^= *data++; + len--; + bufpos++; + if (bufpos == SHA3_IBLK_BYTES) { + bufpos = 0; + goto do_block; } } /* Absorb complete blocks */ - while (bytes >= SHA3_IBLK_BYTES) { + while (len >= SHA3_IBLK_BYTES) { /* XOR data onto beginning of state[]. - * We try to be efficient - operate on word at a time, not byte. - * Yet safe wrt unaligned access: can't just use "*(long*)data"... + * We try to be efficient - operate one word at a time, not byte. + * Careful wrt unaligned access: can't just use "*(long*)data"! */ unsigned count = SHA3_IBLK_BYTES / sizeof(long); - long *buffer = (long*)ctx->state; + long *buf = (long*)ctx->state; do { long v; move_from_unaligned_long(v, (long*)data); - *buffer++ ^= v; + *buf++ ^= v; data += sizeof(long); } while (--count); - + len -= SHA3_IBLK_BYTES; + do_block: sha3_process_block72(ctx->state); - - bytes -= SHA3_IBLK_BYTES; } /* Queue remaining data bytes */ - while (bytes != 0) { - uint8_t *buffer = (uint8_t*)ctx->state; - buffer[bytes_queued] ^= *data++; - bytes_queued++; - bytes--; + while (len != 0) { + uint8_t *buf = (uint8_t*)ctx->state; + buf[bufpos] ^= *data++; + bufpos++; + len--; } - ctx->bytes_queued = bytes_queued; + ctx->bytes_queued = bufpos; +#endif } -void FAST_FUNC sha3_end(sha3_ctx_t *ctx, uint8_t *hashval) +void FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf) { /* Padding */ - uint8_t *buffer = (uint8_t*)ctx->state; - buffer[ctx->bytes_queued] ^= 1; - buffer[SHA3_IBLK_BYTES - 1] ^= 0x80; + uint8_t *buf = (uint8_t*)ctx->state; + buf[ctx->bytes_queued] ^= 1; + buf[SHA3_IBLK_BYTES - 1] ^= 0x80; sha3_process_block72(ctx->state); /* Output */ - memcpy(hashval, ctx->state, 64); + memcpy(resbuf, ctx->state, 64); } -- cgit v1.1