sha3: code shrink
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 19 Jan 2013 23:38:09 +0000 (00:38 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 19 Jan 2013 23:38:09 +0000 (00:38 +0100)
function                                             old     new   delta
sha3_hash                                            155     101     -54

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/libbb.h
libbb/hash_md5_sha.c

index 606db7d0ddb09f47000018d4d143e33f059ce14b..e5200602068670c1b258defbe718053f374e1d8d 100644 (file)
@@ -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;
index d23d4f6392ea84e07a4b0344b1c3a8ad5eeca35b..b4d955e5a3a887b0296dab1b0d17dec546815925 100644 (file)
@@ -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);
 }