From 6a5d9faa29e5ccf9467d25388dfaabaf0794e7bd Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 12 Mar 2009 15:39:11 +0000 Subject: shrink sha hashing function old new delta sha512_hash 262 281 +19 sha512_end 204 221 +17 sha1_hash 128 113 -15 static.mask 16 - -16 static.bits 16 - -16 sha1_end 160 136 -24 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 2/2 up/down: 36/-71) Total: -35 bytes --- libbb/pw_encrypt_sha.c | 2 +- libbb/sha1.c | 81 ++++++++++++++++++++------------------------------ 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/libbb/pw_encrypt_sha.c b/libbb/pw_encrypt_sha.c index e71f96fdc..070e0d442 100644 --- a/libbb/pw_encrypt_sha.c +++ b/libbb/pw_encrypt_sha.c @@ -20,7 +20,7 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) { void (*sha_begin)(void *ctx) FAST_FUNC; void (*sha_hash)(const void *buffer, size_t len, void *ctx) FAST_FUNC; - void* (*sha_end)(void *resbuf, void *ctx) FAST_FUNC; + void (*sha_end)(void *resbuf, void *ctx) FAST_FUNC; int _32or64; char *result, *resptr; diff --git a/libbb/sha1.c b/libbb/sha1.c index 5fc312393..38be575a6 100644 --- a/libbb/sha1.c +++ b/libbb/sha1.c @@ -406,22 +406,21 @@ void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) /* hash_compile function as required. */ void FAST_FUNC sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) { - uint32_t pos = (uint32_t) (ctx->total64 & SHA1_MASK); - uint32_t freeb = SHA1_BLOCK_SIZE - pos; - const unsigned char *sp = buffer; + unsigned wbuflen = ctx->total64 & SHA1_MASK; + unsigned add = SHA1_BLOCK_SIZE - wbuflen; ctx->total64 += len; - while (len >= freeb) { /* transfer whole blocks while possible */ - memcpy(((unsigned char *) ctx->wbuffer) + pos, sp, freeb); - sp += freeb; - len -= freeb; - freeb = SHA1_BLOCK_SIZE; - pos = 0; + while (len >= add) { /* transfer whole blocks while possible */ + memcpy(((unsigned char *) ctx->wbuffer) + wbuflen, buffer, add); + buffer = (const char *)buffer + add; + len -= add; + add = SHA1_BLOCK_SIZE; + wbuflen = 0; sha1_process_block64(ctx); } - memcpy(((unsigned char *) ctx->wbuffer) + pos, sp, len); + memcpy(((unsigned char *) ctx->wbuffer) + wbuflen, buffer, len); } void FAST_FUNC sha256_hash(const void *buffer, size_t len, sha256_ctx_t *ctx) @@ -517,42 +516,24 @@ void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx) { - /* SHA1 Final padding and digest calculation */ -#if BB_BIG_ENDIAN - static const uint32_t mask[4] = { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 }; - static const uint32_t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 }; -#else - static const uint32_t mask[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; - static const uint32_t bits[4] = { 0x00000080, 0x00008000, 0x00800000, 0x80000000 }; -#endif - - uint8_t *hval = resbuf; - uint32_t i, cnt = (uint32_t) (ctx->total64 & SHA1_MASK); - - /* mask out the rest of any partial 32-bit word and then set */ - /* the next byte to 0x80. On big-endian machines any bytes in */ - /* the buffer will be at the top end of 32 bit words, on little */ - /* endian machines they will be at the bottom. Hence the AND */ - /* and OR masks above are reversed for little endian systems */ - ctx->wbuffer[cnt >> 2] = - (ctx->wbuffer[cnt >> 2] & mask[cnt & 3]) | bits[cnt & 3]; - - /* we need 9 or more empty positions, one for the padding byte */ - /* (above) and eight for the length count. If there is not */ - /* enough space pad and empty the buffer */ - if (cnt > SHA1_BLOCK_SIZE - 9) { - if (cnt < 60) - ctx->wbuffer[15] = 0; + unsigned i, wbuflen, pad; + + /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ + wbuflen = ctx->total64 & SHA1_MASK; + ((uint8_t *)ctx->wbuffer)[wbuflen++] = 0x80; + pad = SHA1_BLOCK_SIZE - wbuflen; + memset(((uint8_t *)ctx->wbuffer) + wbuflen, 0, pad); + + /* We need 1+8 or more empty positions, one for the padding byte + * (above) and eight for the length count. + * If there is not enough space, empty the buffer. */ + if (pad < 8) { sha1_process_block64(ctx); - cnt = 0; - } else /* compute a word index for the empty buffer positions */ - cnt = (cnt >> 2) + 1; - - while (cnt < 14) /* and zero pad all but last two positions */ - ctx->wbuffer[cnt++] = 0; + memset(ctx->wbuffer, 0, SHA1_BLOCK_SIZE - 8); + ((uint8_t *)ctx->wbuffer)[0] = 0x80; + } - /* assemble the 64-bit counter of bits in the buffer in BE */ - /* format */ + /* Store the 64-bit counter of bits in the buffer in BE format */ { uint64_t t = ctx->total64 << 3; t = hton64(t); @@ -562,10 +543,14 @@ void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx) sha1_process_block64(ctx); - /* extract the hash value as bytes in case the hash buffer is */ - /* misaligned for 32-bit words */ - for (i = 0; i < SHA1_DIGEST_SIZE; ++i) - hval[i] = (unsigned char) (ctx->hash[i >> 2] >> 8 * (~i & 3)); + /* Extract the hash value as bytes in case resbuf is + * misaligned for 32-bit words */ + for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i) { + uint32_t t = ctx->hash[i]; + t = ntohl(t); /* paranoia. this can be a macro */ + move_to_unaligned32(resbuf, t); /* ditto */ + resbuf = (char*)resbuf + 4; + } } -- cgit v1.2.3