sha: merge sha1/sha256 handling (they are similar enough for this),
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 15 Mar 2009 02:28:05 +0000 (02:28 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 15 Mar 2009 02:28:05 +0000 (02:28 -0000)
 shrink sha215 code

function                                             old     new   delta
sha1_end                                             129     142     +13
sha1_process_block64                                 486     494      +8
sha256_begin                                          37      44      +7
sha1_begin                                            49      56      +7
sha1_hash                                            108     112      +4
...
sha512_end                                           204     184     -20
sha512_process_block128                             1405    1334     -71
sha256_process_block64                               520     446     -74
sha256_end                                           147       -    -147
sha512_hash                                          297     130    -167
sha256_hash                                          260       -    -260
------------------------------------------------------------------------------
(add/remove: 0/2 grow/shrink: 11/9 up/down: 59/-752)         Total: -693 bytes

include/libbb.h
libbb/sha1.c

index b04488a548c9b0c2bd2b4c8c09e0e781cc1dcf73..b6eab6f24facfaf012c68262b7a69c5e093e3cf0 100644 (file)
@@ -1321,24 +1321,21 @@ extern const char bb_uuenc_tbl_std[];
 void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
 
 typedef struct sha1_ctx_t {
+       uint32_t hash[8];    /* 5, +3 elements for sha256 */
        uint64_t total64;
        uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
-       uint32_t hash[5];
+       void (*process_block)(struct sha1_ctx_t*);
 } sha1_ctx_t;
 void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
 void sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx) FAST_FUNC;
 void sha1_end(void *resbuf, sha1_ctx_t *ctx) FAST_FUNC;
-typedef struct sha256_ctx_t {
-       uint64_t total64;
-       uint32_t hash[8];
-       uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
-} sha256_ctx_t;
+typedef struct sha1_ctx_t sha256_ctx_t;
 void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
-void sha256_hash(const void *buffer, size_t len, sha256_ctx_t *ctx) FAST_FUNC;
-void sha256_end(void *resbuf, sha256_ctx_t *ctx) FAST_FUNC;
+#define sha256_hash sha1_hash
+#define sha256_end sha1_end
 typedef struct sha512_ctx_t {
-       uint64_t total64[2];
        uint64_t hash[8];
+       uint64_t total64[2];
        uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
 } sha512_ctx_t;
 void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
index efdb0f58e3c85233e0f38adeb32f65754e8c1e38..8ecf71a9df3f6cf50224503cad406d52c9ce7972 100644 (file)
@@ -203,9 +203,10 @@ static const uint32_t K512_lo[80] = {
 
 /* Process LEN bytes of BUFFER, accumulating context into CTX.
    LEN is rounded _down_ to 64.  */
-static void sha256_process_block64(const void *buffer, size_t len, sha256_ctx_t *ctx)
+static void sha256_process_block64(sha256_ctx_t *ctx)
 {
-       const uint32_t *words = buffer;
+       unsigned t;
+       uint32_t W[64];
        uint32_t a = ctx->hash[0];
        uint32_t b = ctx->hash[1];
        uint32_t c = ctx->hash[2];
@@ -214,15 +215,9 @@ static void sha256_process_block64(const void *buffer, size_t len, sha256_ctx_t
        uint32_t f = ctx->hash[5];
        uint32_t g = ctx->hash[6];
        uint32_t h = ctx->hash[7];
+       const uint32_t *words = (uint32_t*) ctx->wbuffer;
 
-       /* Process all bytes in the buffer with 64 bytes in each round of
-          the loop.  */
-       len /= (sizeof(uint32_t) * 16);
-       while (len) {
-               unsigned t;
-               uint32_t W[64];
-
-               /* Operators defined in FIPS 180-2:4.1.2.  */
+       /* Operators defined in FIPS 180-2:4.1.2.  */
 #define Ch(x, y, z) ((x & y) ^ (~x & z))
 #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
 #define S0(x) (rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22))
@@ -230,54 +225,51 @@ static void sha256_process_block64(const void *buffer, size_t len, sha256_ctx_t
 #define R0(x) (rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3))
 #define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10))
 
-               /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2.  */
-               for (t = 0; t < 16; ++t) {
-                       W[t] = ntohl(*words);
-                       words++;
-               }
+       /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2.  */
+       for (t = 0; t < 16; ++t) {
+               W[t] = ntohl(*words);
+               words++;
+       }
 
-               for (/*t = 16*/; t < 64; ++t)
-                       W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
-
-               /* The actual computation according to FIPS 180-2:6.2.2 step 3.  */
-               for (t = 0; t < 64; ++t) {
-                       uint32_t T1 = h + S1(e) + Ch(e, f, g) + K256[t] + W[t];
-                       uint32_t T2 = S0(a) + Maj(a, b, c);
-                       h = g;
-                       g = f;
-                       f = e;
-                       e = d + T1;
-                       d = c;
-                       c = b;
-                       b = a;
-                       a = T1 + T2;
-               }
+       for (/*t = 16*/; t < 64; ++t)
+               W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
+
+       /* The actual computation according to FIPS 180-2:6.2.2 step 3.  */
+       for (t = 0; t < 64; ++t) {
+               uint32_t T1 = h + S1(e) + Ch(e, f, g) + K256[t] + W[t];
+               uint32_t T2 = S0(a) + Maj(a, b, c);
+               h = g;
+               g = f;
+               f = e;
+               e = d + T1;
+               d = c;
+               c = b;
+               b = a;
+               a = T1 + T2;
+       }
 #undef Ch
 #undef Maj
 #undef S0
 #undef S1
 #undef R0
 #undef R1
-               /* Add the starting values of the context according to FIPS 180-2:6.2.2
-                  step 4.  */
-               ctx->hash[0] = a += ctx->hash[0];
-               ctx->hash[1] = b += ctx->hash[1];
-               ctx->hash[2] = c += ctx->hash[2];
-               ctx->hash[3] = d += ctx->hash[3];
-               ctx->hash[4] = e += ctx->hash[4];
-               ctx->hash[5] = f += ctx->hash[5];
-               ctx->hash[6] = g += ctx->hash[6];
-               ctx->hash[7] = h += ctx->hash[7];
-
-               /* Prepare for the next round.  */
-               len--;
-       }
+       /* Add the starting values of the context according to FIPS 180-2:6.2.2
+          step 4.  */
+       ctx->hash[0] += a;
+       ctx->hash[1] += b;
+       ctx->hash[2] += c;
+       ctx->hash[3] += d;
+       ctx->hash[4] += e;
+       ctx->hash[5] += f;
+       ctx->hash[6] += g;
+       ctx->hash[7] += h;
 }
 /* Process LEN bytes of BUFFER, accumulating context into CTX.
    LEN is rounded _down_ to 128.  */
-static void sha512_process_block128(const void *buffer, size_t len, sha512_ctx_t *ctx)
+static void sha512_process_block128(sha512_ctx_t *ctx)
 {
-       const uint64_t *words = buffer;
+       unsigned t;
+       uint64_t W[80];
        uint64_t a = ctx->hash[0];
        uint64_t b = ctx->hash[1];
        uint64_t c = ctx->hash[2];
@@ -286,13 +278,9 @@ static void sha512_process_block128(const void *buffer, size_t len, sha512_ctx_t
        uint64_t f = ctx->hash[5];
        uint64_t g = ctx->hash[6];
        uint64_t h = ctx->hash[7];
+       const uint32_t *words = (uint32_t*) ctx->wbuffer;
 
-       len /= (sizeof(uint64_t) * 16);
-       while (len) {
-               unsigned t;
-               uint64_t W[80];
-
-               /* Operators defined in FIPS 180-2:4.1.2.  */
+       /* Operators defined in FIPS 180-2:4.1.2.  */
 #define Ch(x, y, z) ((x & y) ^ (~x & z))
 #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
 #define S0(x) (rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39))
@@ -300,58 +288,56 @@ static void sha512_process_block128(const void *buffer, size_t len, sha512_ctx_t
 #define R0(x) (rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7))
 #define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6))
 
-               /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2.  */
-               for (t = 0; t < 16; ++t) {
-                       W[t] = ntoh64(*words);
-                       words++;
-               }
-               for (/*t = 16*/; t < 80; ++t)
-                       W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
-
-               /* The actual computation according to FIPS 180-2:6.3.2 step 3.  */
-               for (t = 0; t < 80; ++t) {
-                       uint64_t K512_t = ((uint64_t)(K256[t]) << 32) + K512_lo[t];
-                       uint64_t T1 = h + S1(e) + Ch(e, f, g) + K512_t + W[t];
-                       uint64_t T2 = S0(a) + Maj(a, b, c);
-                       h = g;
-                       g = f;
-                       f = e;
-                       e = d + T1;
-                       d = c;
-                       c = b;
-                       b = a;
-                       a = T1 + T2;
-               }
+       /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2.  */
+       for (t = 0; t < 16; ++t) {
+               W[t] = ntoh64(*words);
+               words++;
+       }
+       for (/*t = 16*/; t < 80; ++t)
+               W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
+
+       /* The actual computation according to FIPS 180-2:6.3.2 step 3.  */
+       for (t = 0; t < 80; ++t) {
+               uint64_t K512_t = ((uint64_t)(K256[t]) << 32) + K512_lo[t];
+               uint64_t T1 = h + S1(e) + Ch(e, f, g) + K512_t + W[t];
+               uint64_t T2 = S0(a) + Maj(a, b, c);
+               h = g;
+               g = f;
+               f = e;
+               e = d + T1;
+               d = c;
+               c = b;
+               b = a;
+               a = T1 + T2;
+       }
 #undef Ch
 #undef Maj
 #undef S0
 #undef S1
 #undef R0
 #undef R1
-               /* Add the starting values of the context according to FIPS 180-2:6.3.2
-                  step 4.  */
-               ctx->hash[0] = a += ctx->hash[0];
-               ctx->hash[1] = b += ctx->hash[1];
-               ctx->hash[2] = c += ctx->hash[2];
-               ctx->hash[3] = d += ctx->hash[3];
-               ctx->hash[4] = e += ctx->hash[4];
-               ctx->hash[5] = f += ctx->hash[5];
-               ctx->hash[6] = g += ctx->hash[6];
-               ctx->hash[7] = h += ctx->hash[7];
-
-               len--;
-       }
+       /* Add the starting values of the context according to FIPS 180-2:6.3.2
+          step 4.  */
+       ctx->hash[0] += a;
+       ctx->hash[1] += b;
+       ctx->hash[2] += c;
+       ctx->hash[3] += d;
+       ctx->hash[4] += e;
+       ctx->hash[5] += f;
+       ctx->hash[6] += g;
+       ctx->hash[7] += h;
 }
 
 
 void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
 {
-       ctx->total64 = 0;
        ctx->hash[0] = 0x67452301;
        ctx->hash[1] = 0xefcdab89;
        ctx->hash[2] = 0x98badcfe;
        ctx->hash[3] = 0x10325476;
        ctx->hash[4] = 0xc3d2e1f0;
+       ctx->total64 = 0;
+       ctx->process_block = sha1_process_block64;
 }
 
 static const uint32_t init256[] = {
@@ -380,6 +366,7 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
 {
        memcpy(ctx->hash, init256, sizeof(init256));
        ctx->total64 = 0;
+       ctx->process_block = sha256_process_block64;
 }
 /* Initialize structure containing state of computation.
    (FIPS 180-2:5.3.3)  */
@@ -405,64 +392,16 @@ void FAST_FUNC sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx)
                len -= add;
                add = SHA1_BLOCK_SIZE;
                in_buf = 0;
-               sha1_process_block64(ctx);
+               ctx->process_block(ctx);
        }
 
        memcpy(ctx->wbuffer + in_buf, buffer, len);
 }
 
-void FAST_FUNC sha256_hash(const void *buffer, size_t len, sha256_ctx_t *ctx)
-{
-       unsigned in_buf = ctx->total64 & 63;
-
-       /* First increment the byte count.  FIPS 180-2 specifies the possible
-          length of the file up to 2^64 _bits_.
-          We compute the number of _bytes_ and convert to bits later.  */
-       ctx->total64 += len;
-
-       /* When we already have some bits in our internal buffer concatenate
-          both inputs first.  */
-       if (in_buf != 0) {
-               unsigned add;
-
-               add = sizeof(ctx->wbuffer) - in_buf;
-               if (add > len)
-                       add = len;
-               memcpy(ctx->wbuffer + in_buf, buffer, add);
-               in_buf += add;
-
-               /* If we still didn't collect full wbuffer, bail out */
-               if (in_buf < sizeof(ctx->wbuffer))
-                       return;
-
-               sha256_process_block64(ctx->wbuffer, 64, ctx);
-               buffer = (const char *)buffer + add;
-               len -= add;
-       }
-
-       /* Process available complete blocks.  */
-       if (len >= 64) {
-               if (UNALIGNED_P(buffer, uint32_t)) {
-                       while (len >= 64) {
-                               sha256_process_block64(memcpy(ctx->wbuffer, buffer, 64), 64, ctx);
-                               buffer = (const char *)buffer + 64;
-                               len -= 64;
-                       }
-               } else {
-                       sha256_process_block64(buffer, len /*& ~63*/, ctx);
-                       buffer = (const char *)buffer + (len & ~63);
-                       len &= 63;
-               }
-       }
-
-       /* Move remaining bytes into internal buffer.  */
-       if (len > 0)
-               memcpy(ctx->wbuffer, buffer, len);
-}
-
 void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx)
 {
        unsigned in_buf = ctx->total64[0] & 127;
+       unsigned add = 128 - in_buf;
 
        /* First increment the byte count.  FIPS 180-2 specifies the possible
           length of the file up to 2^128 _bits_.
@@ -471,39 +410,16 @@ void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx)
        if (ctx->total64[0] < len)
                ctx->total64[1]++;
 
-       if (in_buf != 0) {
-               unsigned add;
-
-               add = sizeof(ctx->wbuffer) - in_buf;
-               if (add > len)
-                       add = len;
+       while (len >= add) {    /* transfer whole blocks while possible  */
                memcpy(ctx->wbuffer + in_buf, buffer, add);
-               in_buf += add;
-
-               if (in_buf < sizeof(ctx->wbuffer))
-                       return;
-
-               sha512_process_block128(ctx->wbuffer, 128, ctx);
                buffer = (const char *)buffer + add;
                len -= add;
+               add = 128;
+               in_buf = 0;
+               sha512_process_block128(ctx);
        }
 
-       if (len >= 128) {
-               if (UNALIGNED_P(buffer, uint64_t)) {
-                       while (len >= 128) {
-                               sha512_process_block128(memcpy(ctx->wbuffer, buffer, 128), 128, ctx);
-                               buffer = (const char *)buffer + 128;
-                               len -= 128;
-                       }
-               } else {
-                       sha512_process_block128(buffer, len /*& ~127*/, ctx);
-                       buffer = (const char *)buffer + (len & ~127);
-                       len &= 127;
-               }
-       }
-
-       if (len > 0)
-               memcpy(ctx->wbuffer, buffer, len);
+       memcpy(ctx->wbuffer + in_buf, buffer, len);
 }
 
 
@@ -528,48 +444,18 @@ void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx)
                        /* wbuffer is suitably aligned for this */
                        *(uint64_t *) (&ctx->wbuffer[SHA1_BLOCK_SIZE - 8]) = t;
                }
-               sha1_process_block64(ctx);
+               ctx->process_block(ctx);
                if (pad >= 8)
                        break;
        }
 
+       in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8;
        /* This way we do not impose alignment constraints on resbuf: */
 #if BB_LITTLE_ENDIAN
-       for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i)
-               ctx->hash[i] = htonl(ctx->hash[i]);
-#endif
-       memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
-}
-
-void FAST_FUNC sha256_end(void *resbuf, sha256_ctx_t *ctx)
-{
-       unsigned i, pad, in_buf;
-
-       in_buf = ctx->total64 & 63;
-       /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0...
-        * (FIPS 180-2:5.1.1)
-        */
-       ctx->wbuffer[in_buf++] = 0x80;
-
-       while (1) {
-               pad = 64 - in_buf;
-               memset(ctx->wbuffer + in_buf, 0, pad);
-               in_buf = 0;
-               if (pad >= 8) {
-                       uint64_t t = ctx->total64 << 3;
-                       t = hton64(t);
-                       *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
-               }
-               sha256_process_block64(ctx->wbuffer, 64, ctx);
-               if (pad >= 8)
-                       break;
-       }
-
-#if BB_LITTLE_ENDIAN
-       for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i)
+       for (i = 0; i < in_buf; ++i)
                ctx->hash[i] = htonl(ctx->hash[i]);
 #endif
-       memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
+       memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf);
 }
 
 void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx)
@@ -596,7 +482,7 @@ void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx)
                        t = hton64(t);
                        *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
                }
-               sha512_process_block128(ctx->wbuffer, 128, ctx);
+               sha512_process_block128(ctx);
                if (pad >= 16)
                        break;
        }