Replace SHA1 library 87/270887/4 accepted/tizen/6.5/unified/20220222.132801 submit/tizen_6.5/20220221.170828
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Fri, 4 Feb 2022 15:09:43 +0000 (16:09 +0100)
committerMateusz Moscicki <m.moscicki2@partner.samsung.com>
Mon, 21 Feb 2022 14:59:47 +0000 (15:59 +0100)
The previous SHA1 implementation was unable to correctly calculate
hashes for images larger than 0x1fffffff bytes.

Change-Id: Ic98f8cb4355e4522bb8154aa3285a60f20c42f4a

ss_engine/SS_ApplyPatch.c
ss_engine/SS_Common.c
ss_engine/SS_PatchDelta.c
ss_engine/SS_PatchDelta.h
ss_engine/sha1.c
ss_engine/sha1.h

index 2057ac3..bc9e86b 100755 (executable)
@@ -44,7 +44,7 @@
 #include <LzmaEnc.h>
 
 
-int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, sha1_ctx_t * ctx1)
+int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, SHA1_CTX * ctx1)
 {
        UInt64 unpackSize = 0;
        CFileSeqInStream inStream;
@@ -103,7 +103,7 @@ int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void
        }
 
        if (ctx1)
-               sha1_update(ctx1, new_data, new_size);
+               SHA1Update(ctx1, new_data, new_size);
 Cleanup:
        if (new_data)
                SS_Free(new_data);
index 6e31854..b0815ea 100755 (executable)
@@ -143,8 +143,8 @@ int SS_CalculateFileSha(char *filename, long int filesize, unsigned char calcula
        }
 
        ssize_t bytes_read = 0;
-       sha1_ctx_t sha_ctx;
-       sha1_init(&sha_ctx);
+       SHA1_CTX sha_ctx;
+       SHA1Init(&sha_ctx);
 
        while (filesize > 0) {
                if (filesize < chunk) {
@@ -154,7 +154,7 @@ int SS_CalculateFileSha(char *filename, long int filesize, unsigned char calcula
                                ulResult = E_SS_FAILURE;
                                goto Cleanup;
                        }
-                       sha1_update(&sha_ctx, buffer, filesize);
+                       SHA1Update(&sha_ctx, buffer, filesize);
                        break;
                } else {
                        bytes_read = fread(buffer, 1, chunk, fp);
@@ -163,12 +163,12 @@ int SS_CalculateFileSha(char *filename, long int filesize, unsigned char calcula
                                ulResult = E_SS_FAILURE;
                                goto Cleanup;
                        }
-                       sha1_update(&sha_ctx, buffer, chunk);
+                       SHA1Update(&sha_ctx, buffer, chunk);
                        filesize -= chunk;
                }
        }
 
-       sha1_final(&sha_ctx, (uint32_t *) &calculated_sha1[0]);
+       SHA1Final(calculated_sha1, &sha_ctx);
 
 Cleanup:
        if (fp)
index f3d6a5f..9f2d94c 100755 (executable)
@@ -146,19 +146,19 @@ int SS_LoadPartition(const char *filename, FileInfo * file)
                return -1;
        }
 
-       sha1_ctx_t sha_ctx;
-       sha1_init(&sha_ctx);
+       SHA1_CTX sha_ctx;
+       SHA1Init(&sha_ctx);
 
        file->data = SS_Malloc(file->size);
        if (file->data) {
                read = fread(file->data, 1, file->size, dev);
                LOGL(LOG_SSENGINE, "Partition size read %d\n", read);
-               sha1_update(&sha_ctx, file->data, read);
+               SHA1Update(&sha_ctx, file->data, read);
                file->size = read;
        }
 
-       const uint8_t sha_final[SHA_DIGEST_SIZE] = { 0, };
-       sha1_final(&sha_ctx, (uint32_t *) & sha_final);
+       unsigned char sha_final[SHA_DIGEST_SIZE] = { 0, };
+       SHA1Final(sha_final, &sha_ctx);
        for (i = 0; i < SHA_DIGEST_SIZE; ++i)
                file->sha1[i] = sha_final[i];
        //LOGL(LOG_SSENGINE, "Final SHA of Source (%s)\n", sha_final);
@@ -212,7 +212,7 @@ int SS_LoadFile(const char *filename, FileInfo * file)
        }
        fclose(f);
        //LOGL(LOG_SSENGINE,"SS_LoadFile --- [bytes_read %d]\n",bytes_read);
-       sha1(file->data, file->size, (uint32_t *) file->sha1);
+       SHA1(file->sha1, file->data, file->size);
        return 0;
 }
 
@@ -241,7 +241,7 @@ int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename,
 {
        uint8_t target_sha1[SHA_DIGEST_SIZE] = { 0, };
        uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, };
-       sha1_ctx_t ctx1;
+       SHA1_CTX ctx1;
        int output;
        int retry = 1;
        int use_backup = 0;
@@ -413,7 +413,7 @@ int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename,
                        sink = ss_fileSink;
                        token = &output;
                }
-               sha1_init(&ctx1);
+               SHA1Init(&ctx1);
                if (use_backup)
                        result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
                else
@@ -439,8 +439,8 @@ int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename,
                }
        } while (retry-- > 0);
 
-       const uint8_t current_target_sha1[SHA_DIGEST_SIZE] = { 0, };
-       sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
+       unsigned char current_target_sha1[SHA_DIGEST_SIZE] = { 0, };
+       SHA1Final(current_target_sha1, &ctx1);
        if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
                LOGE("patch did not produce expected sha1\n");
                SS_SetUpgradeState(E_SS_FSSHA_MISMATCH);
@@ -842,9 +842,9 @@ int SS_UpdateDeltaIMG(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, i
 {
        uint8_t target_sha1[SHA_DIGEST_SIZE];
        uint8_t source_sha1[SHA_DIGEST_SIZE];
-       const uint8_t current_target_sha1[SHA_DIGEST_SIZE];
+       unsigned char current_target_sha1[SHA_DIGEST_SIZE];
        FileInfo source_file;
-       sha1_ctx_t ctx1;
+       SHA1_CTX ctx1;
        MemorySinkInfo msi;
        int result = S_SS_SUCCESS;
        int blk_cnt;
@@ -918,7 +918,7 @@ int SS_UpdateDeltaIMG(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, i
        sink = ss_memorySink;
        token = &msi;
 
-       sha1_init(&ctx1);
+       SHA1Init(&ctx1);
        //if souce was corrupted, use backup to apply diff
        if (use_backup_img == -1)
                result =
@@ -931,7 +931,7 @@ int SS_UpdateDeltaIMG(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, i
                goto Cleanup;
        }
 
-       sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
+       SHA1Final(current_target_sha1, &ctx1);
        result = memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE);
        if (result != S_SS_SUCCESS) {
                LOGE("patch did not produce expected sha1 \n");
@@ -983,6 +983,7 @@ Cleanup:
 
 }
 
+
 int SS_UpdateDeltaIMGAB(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
 {
        int result = S_SS_SUCCESS;
index d789419..edbe182 100755 (executable)
@@ -29,7 +29,7 @@
 //#define ENHANCED_BSDIFF
 #define SS_UPDATE_FS 0
 #define SS_UPDATE_IMG 1
-//#define SHA_DIGEST_SIZE 20
+#define SHA_DIGEST_SIZE 20
 typedef struct {
        int type;
        ssize_t size;
@@ -53,7 +53,7 @@ int ParseSha1(const char *str, uint8_t * digest);
 
 void ShowBSDiffLicense();
 int ApplyBSDiffPatch(const unsigned char *old_data, ssize_t old_size,
-               const Value * patch, ssize_t patch_offset, SinkFn sink, void *token, sha1_ctx_t * ctx1);
+               const Value * patch, ssize_t patch_offset, SinkFn sink, void *token, SHA1_CTX * ctx1);
 int ApplyBSDiffPatchMem(const unsigned char *old_data, ssize_t old_size,
                const Value * patch, ssize_t patch_offset, unsigned char **new_data, ssize_t * new_size);
 //int ApplyOptimizedBSDiffPatch(const unsigned char* old_data,void* token,
@@ -64,7 +64,7 @@ int SS_LoadFile(const char *filename, FileInfo * file);
 extern void SS_SetUpgradeState(int Val);
 extern long SS_GetAvailableFreeSpace(const char *partition_name, SS_UINT32 * available_flash_size);
 extern int SS_BackupSource(const char *source_filename);
-extern int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, sha1_ctx_t * ctx1);
+extern int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, SHA1_CTX * ctx1);
 extern int SS_BackupSourceClear();
 extern int SS_PatchSourceClear();
 extern long SS_WriteFile(long wHandle, SS_UINT32 dwPosition, unsigned char *pbBuffer, SS_UINT32 dwSize);
index 54d75a2..fe8da83 100755 (executable)
 /*
- * sha1.c
- *
- * an implementation of the Secure Hash Algorithm v.1 (SHA-1),
- * specified in FIPS 180-1
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
 
-/*
- *
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- *   Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- *   Neither the name of the Cisco Systems, Inc. nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include "sha1.h"
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
 
+/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
 
+#define SHA1HANDSOFF
 
-/* SN == Rotate left N bits */
-#define S1(X)  ((X << 1)  | (X >> 31))
-#define S5(X)  ((X << 5)  | (X >> 27))
-#define S30(X) ((X << 30) | (X >> 2))
+#include <stdio.h>
+#include <string.h>
 
-#define f0(B,C,D) ((B & C) | (~B & D))
-#define f1(B,C,D) (B ^ C ^ D)
-#define f2(B,C,D) ((B & C) | (B & D) | (C & D))
-#define f3(B,C,D) (B ^ C ^ D)
+/* for uint32_t */
+#include <stdint.h>
 
+#include "sha1.h"
 
 
-/*
- * nota bene: the variable K0 appears in the curses library, so we
- * give longer names to these variables to avoid spurious warnings
- * on systems that uses curses
- */
-
-uint32_t SHA_K0 = 0x5A827999;   /* Kt for 0  <= t <= 19 */
-uint32_t SHA_K1 = 0x6ED9EBA1;   /* Kt for 20 <= t <= 39 */
-uint32_t SHA_K2 = 0x8F1BBCDC;   /* Kt for 40 <= t <= 59 */
-uint32_t SHA_K3 = 0xCA62C1D6;   /* Kt for 60 <= t <= 79 */
-
-void
-sha1(const uint8_t *msg,  int octets_in_msg, uint32_t hash_value[5]) {
-  sha1_ctx_t ctx;
-
-  sha1_init(&ctx);
-  sha1_update(&ctx, msg, octets_in_msg);
-  sha1_final(&ctx, hash_value);
-
-}
-
-/*
- *  sha1_core(M, H) computes the core compression function, where M is
- *  the next part of the message (in network byte order) and H is the
- *  intermediate state { H0, H1, ...} (in host byte order)
- *
- *  this function does not do any of the padding required in the
- *  complete SHA1 function
- *
- *  this function is used in the SEAL 3.0 key setup routines
- *  (crypto/cipher/seal.c)
- */
-
-void
-sha1_core(const uint32_t M[16], uint32_t hash_value[5]) {
-  uint32_t H0;
-  uint32_t H1;
-  uint32_t H2;
-  uint32_t H3;
-  uint32_t H4;
-  uint32_t W[80];
-  uint32_t A, B, C, D, E, TEMP;
-  int t;
-
-  /* copy hash_value into H0, H1, H2, H3, H4 */
-  H0 = hash_value[0];
-  H1 = hash_value[1];
-  H2 = hash_value[2];
-  H3 = hash_value[3];
-  H4 = hash_value[4];
-
-  /* copy/xor message into array */
-
-  W[0]  = be32_to_cpu(M[0]);
-  W[1]  = be32_to_cpu(M[1]);
-  W[2]  = be32_to_cpu(M[2]);
-  W[3]  = be32_to_cpu(M[3]);
-  W[4]  = be32_to_cpu(M[4]);
-  W[5]  = be32_to_cpu(M[5]);
-  W[6]  = be32_to_cpu(M[6]);
-  W[7]  = be32_to_cpu(M[7]);
-  W[8]  = be32_to_cpu(M[8]);
-  W[9]  = be32_to_cpu(M[9]);
-  W[10] = be32_to_cpu(M[10]);
-  W[11] = be32_to_cpu(M[11]);
-  W[12] = be32_to_cpu(M[12]);
-  W[13] = be32_to_cpu(M[13]);
-  W[14] = be32_to_cpu(M[14]);
-  W[15] = be32_to_cpu(M[15]);
-  TEMP = W[13] ^ W[8]  ^ W[2]  ^ W[0];  W[16] = S1(TEMP);
-  TEMP = W[14] ^ W[9]  ^ W[3]  ^ W[1];  W[17] = S1(TEMP);
-  TEMP = W[15] ^ W[10] ^ W[4]  ^ W[2];  W[18] = S1(TEMP);
-  TEMP = W[16] ^ W[11] ^ W[5]  ^ W[3];  W[19] = S1(TEMP);
-  TEMP = W[17] ^ W[12] ^ W[6]  ^ W[4];  W[20] = S1(TEMP);
-  TEMP = W[18] ^ W[13] ^ W[7]  ^ W[5];  W[21] = S1(TEMP);
-  TEMP = W[19] ^ W[14] ^ W[8]  ^ W[6];  W[22] = S1(TEMP);
-  TEMP = W[20] ^ W[15] ^ W[9]  ^ W[7];  W[23] = S1(TEMP);
-  TEMP = W[21] ^ W[16] ^ W[10] ^ W[8];  W[24] = S1(TEMP);
-  TEMP = W[22] ^ W[17] ^ W[11] ^ W[9];  W[25] = S1(TEMP);
-  TEMP = W[23] ^ W[18] ^ W[12] ^ W[10]; W[26] = S1(TEMP);
-  TEMP = W[24] ^ W[19] ^ W[13] ^ W[11]; W[27] = S1(TEMP);
-  TEMP = W[25] ^ W[20] ^ W[14] ^ W[12]; W[28] = S1(TEMP);
-  TEMP = W[26] ^ W[21] ^ W[15] ^ W[13]; W[29] = S1(TEMP);
-  TEMP = W[27] ^ W[22] ^ W[16] ^ W[14]; W[30] = S1(TEMP);
-  TEMP = W[28] ^ W[23] ^ W[17] ^ W[15]; W[31] = S1(TEMP);
-
-  /* process the remainder of the array */
-  for (t=32; t < 80; t++) {
-    TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
-    W[t] = S1(TEMP);
-  }
-
-  A = H0; B = H1; C = H2; D = H3; E = H4;
-
-  for (t=0; t < 20; t++) {
-    TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
-    E = D; D = C; C = S30(B); B = A; A = TEMP;
-  }
-  for (   ; t < 40; t++) {
-    TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
-    E = D; D = C; C = S30(B); B = A; A = TEMP;
-  }
-  for (   ; t < 60; t++) {
-    TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
-    E = D; D = C; C = S30(B); B = A; A = TEMP;
-  }
-  for (   ; t < 80; t++) {
-    TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
-    E = D; D = C; C = S30(B); B = A; A = TEMP;
-  }
-
-  hash_value[0] = H0 + A;
-  hash_value[1] = H1 + B;
-  hash_value[2] = H2 + C;
-  hash_value[3] = H3 + D;
-  hash_value[4] = H4 + E;
-
-  return;
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+    |(rol(block->l[i],8)&0x00FF00FF))
+#elif BYTE_ORDER == BIG_ENDIAN
+#define blk0(i) block->l[i]
+#else
+#error "Endianness not defined!"
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+    ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(
+    uint32_t state[5],
+    const unsigned char buffer[64]
+)
+{
+    uint32_t a, b, c, d, e;
+
+    typedef union
+    {
+        unsigned char c[64];
+        uint32_t l[16];
+    } CHAR64LONG16;
+
+#ifdef SHA1HANDSOFF
+    CHAR64LONG16 block[1];      /* use array to appear as a pointer */
+
+    memcpy(block, buffer, 64);
+#else
+    /* The following had better never be used because it causes the
+     * pointer-to-const buffer to be cast into a pointer to non-const.
+     * And the result is written through.  I threw a "const" in, hoping
+     * this will cause a diagnostic.
+     */
+    CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
+#endif
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a, b, c, d, e, 0);
+    R0(e, a, b, c, d, 1);
+    R0(d, e, a, b, c, 2);
+    R0(c, d, e, a, b, 3);
+    R0(b, c, d, e, a, 4);
+    R0(a, b, c, d, e, 5);
+    R0(e, a, b, c, d, 6);
+    R0(d, e, a, b, c, 7);
+    R0(c, d, e, a, b, 8);
+    R0(b, c, d, e, a, 9);
+    R0(a, b, c, d, e, 10);
+    R0(e, a, b, c, d, 11);
+    R0(d, e, a, b, c, 12);
+    R0(c, d, e, a, b, 13);
+    R0(b, c, d, e, a, 14);
+    R0(a, b, c, d, e, 15);
+    R1(e, a, b, c, d, 16);
+    R1(d, e, a, b, c, 17);
+    R1(c, d, e, a, b, 18);
+    R1(b, c, d, e, a, 19);
+    R2(a, b, c, d, e, 20);
+    R2(e, a, b, c, d, 21);
+    R2(d, e, a, b, c, 22);
+    R2(c, d, e, a, b, 23);
+    R2(b, c, d, e, a, 24);
+    R2(a, b, c, d, e, 25);
+    R2(e, a, b, c, d, 26);
+    R2(d, e, a, b, c, 27);
+    R2(c, d, e, a, b, 28);
+    R2(b, c, d, e, a, 29);
+    R2(a, b, c, d, e, 30);
+    R2(e, a, b, c, d, 31);
+    R2(d, e, a, b, c, 32);
+    R2(c, d, e, a, b, 33);
+    R2(b, c, d, e, a, 34);
+    R2(a, b, c, d, e, 35);
+    R2(e, a, b, c, d, 36);
+    R2(d, e, a, b, c, 37);
+    R2(c, d, e, a, b, 38);
+    R2(b, c, d, e, a, 39);
+    R3(a, b, c, d, e, 40);
+    R3(e, a, b, c, d, 41);
+    R3(d, e, a, b, c, 42);
+    R3(c, d, e, a, b, 43);
+    R3(b, c, d, e, a, 44);
+    R3(a, b, c, d, e, 45);
+    R3(e, a, b, c, d, 46);
+    R3(d, e, a, b, c, 47);
+    R3(c, d, e, a, b, 48);
+    R3(b, c, d, e, a, 49);
+    R3(a, b, c, d, e, 50);
+    R3(e, a, b, c, d, 51);
+    R3(d, e, a, b, c, 52);
+    R3(c, d, e, a, b, 53);
+    R3(b, c, d, e, a, 54);
+    R3(a, b, c, d, e, 55);
+    R3(e, a, b, c, d, 56);
+    R3(d, e, a, b, c, 57);
+    R3(c, d, e, a, b, 58);
+    R3(b, c, d, e, a, 59);
+    R4(a, b, c, d, e, 60);
+    R4(e, a, b, c, d, 61);
+    R4(d, e, a, b, c, 62);
+    R4(c, d, e, a, b, 63);
+    R4(b, c, d, e, a, 64);
+    R4(a, b, c, d, e, 65);
+    R4(e, a, b, c, d, 66);
+    R4(d, e, a, b, c, 67);
+    R4(c, d, e, a, b, 68);
+    R4(b, c, d, e, a, 69);
+    R4(a, b, c, d, e, 70);
+    R4(e, a, b, c, d, 71);
+    R4(d, e, a, b, c, 72);
+    R4(c, d, e, a, b, 73);
+    R4(b, c, d, e, a, 74);
+    R4(a, b, c, d, e, 75);
+    R4(e, a, b, c, d, 76);
+    R4(d, e, a, b, c, 77);
+    R4(c, d, e, a, b, 78);
+    R4(b, c, d, e, a, 79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+    memset(block, '\0', sizeof(block));
+#endif
 }
 
-void
-sha1_init(sha1_ctx_t *ctx) {
-  int i;
-
-  /* initialize state vector */
-  ctx->H[0] = 0x67452301;
-  ctx->H[1] = 0xefcdab89;
-  ctx->H[2] = 0x98badcfe;
-  ctx->H[3] = 0x10325476;
-  ctx->H[4] = 0xc3d2e1f0;
-
-  for(i = 0; i < 16; i++) {
-    ctx->M[i] = 0;
-  }
-
-  /* indicate that message buffer is empty */
-  ctx->octets_in_buffer = 0;
 
-  /* reset message bit-count to zero */
-  ctx->num_bits_in_msg = 0;
+/* SHA1Init - Initialize new context */
 
+void SHA1Init(
+    SHA1_CTX * context
+)
+{
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
 }
 
-void
-sha1_update(sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_msg) {
-  int i;
-  uint8_t *buf = (uint8_t *)ctx->M;
-
-  /* update message bit-count */
-  ctx->num_bits_in_msg += octets_in_msg * 8;
-
-  /* loop over 16-word blocks of M */
-  while (octets_in_msg > 0) {
-
-    if (octets_in_msg + ctx->octets_in_buffer >= 64) {
-
-      /*
-       * copy words of M into msg buffer until that buffer is full,
-       * converting them into host byte order as needed
-       */
-      octets_in_msg -= (64 - ctx->octets_in_buffer);
-      for (i=ctx->octets_in_buffer; i < 64; i++)
-       buf[i] = *msg++;
-      ctx->octets_in_buffer = 0;
-
-      /* process a whole block */
-
-      //debug_print(mod_sha1, "(update) running sha1_core()", NULL);
-
-      sha1_core(ctx->M, ctx->H);
-
-    } else {
-
-      //debug_print(mod_sha1, "(update) not running sha1_core()", NULL);
 
-      for (i=ctx->octets_in_buffer;
-          i < (ctx->octets_in_buffer + octets_in_msg); i++)
-       buf[i] = *msg++;
-      ctx->octets_in_buffer += octets_in_msg;
-      octets_in_msg = 0;
+/* Run your data through this. */
+
+void SHA1Update(
+    SHA1_CTX * context,
+    const unsigned char *data,
+    uint32_t len
+)
+{
+    uint32_t i;
+
+    uint32_t j;
+
+    j = context->count[0];
+    if ((context->count[0] += len << 3) < j)
+        context->count[1]++;
+    context->count[1] += (len >> 29);
+    j = (j >> 3) & 63;
+    if ((j + len) > 63)
+    {
+        memcpy(&context->buffer[j], data, (i = 64 - j));
+        SHA1Transform(context->state, context->buffer);
+        for (; i + 63 < len; i += 64)
+        {
+            SHA1Transform(context->state, &data[i]);
+        }
+        j = 0;
     }
-
-  }
-
+    else
+        i = 0;
+    memcpy(&context->buffer[j], &data[i], len - i);
 }
 
-/*
- * sha1_final(ctx, output) computes the result for ctx and copies it
- * into the twenty octets located at *output
- */
-
-void
-sha1_final(sha1_ctx_t *ctx, uint32_t *output) {
-  uint32_t A, B, C, D, E, TEMP;
-  uint32_t W[80];
-  int i, t;
-
-  /*
-   * process the remaining octets_in_buffer, padding and terminating as
-   * necessary
-   */
-  {
-    int tail = ctx->octets_in_buffer % 4;
-
-    /* copy/xor message into array */
-    for (i=0; i < (ctx->octets_in_buffer+3)/4; i++)
-      W[i]  = be32_to_cpu(ctx->M[i]);
-
-    /* set the high bit of the octet immediately following the message */
-    switch (tail) {
-    case (3):
-      W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xffffff00) | 0x80;
-      W[i] = 0x0;
-      break;
-    case (2):
-      W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xffff0000) | 0x8000;
-      W[i] = 0x0;
-      break;
-    case (1):
-      W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xff000000) | 0x800000;
-      W[i] = 0x0;
-      break;
-    case (0):
-      W[i] = 0x80000000;
-      break;
-    }
-
-    /* zeroize remaining words */
-    for (i++   ; i < 15; i++)
-      W[i] = 0x0;
-
-    /*
-     * if there is room at the end of the word array, then set the
-     * last word to the bit-length of the message; otherwise, set that
-     * word to zero and then we need to do one more run of the
-     * compression algo.
-     */
-    if (ctx->octets_in_buffer < 56)
-      W[15] = ctx->num_bits_in_msg;
-    else if (ctx->octets_in_buffer < 60)
-      W[15] = 0x0;
-
-    /* process the word array */
-    for (t=16; t < 80; t++) {
-      TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
-      W[t] = S1(TEMP);
-    }
-
-    A = ctx->H[0];
-    B = ctx->H[1];
-    C = ctx->H[2];
-    D = ctx->H[3];
-    E = ctx->H[4];
-
-    for (t=0; t < 20; t++) {
-      TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
-    }
-    for (   ; t < 40; t++) {
-      TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
-    }
-    for (   ; t < 60; t++) {
-      TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
-    }
-    for (   ; t < 80; t++) {
-      TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
-    }
-
-    ctx->H[0] += A;
-    ctx->H[1] += B;
-    ctx->H[2] += C;
-    ctx->H[3] += D;
-    ctx->H[4] += E;
-
-  }
-
-  //debug_print(mod_sha1, "(final) running sha1_core()", NULL);
 
-  if (ctx->octets_in_buffer >= 56) {
+/* Add padding and return the message digest. */
 
+void SHA1Final(
+    unsigned char digest[20],
+    SHA1_CTX * context
+)
+{
+    unsigned i;
 
-    //debug_print(mod_sha1, "(final) running sha1_core() again", NULL);
+    unsigned char finalcount[8];
 
-    /* we need to do one final run of the compression algo */
+    unsigned char c;
 
-    /*
-     * set initial part of word array to zeros, and set the
-     * final part to the number of bits in the message
+#if 0    /* untested "improvement" by DHR */
+    /* Convert context->count to a sequence of bytes
+     * in finalcount.  Second element first, but
+     * big-endian order within element.
+     * But we do it all backwards.
      */
-    for (i=0; i < 15; i++)
-      W[i] = 0x0;
-    W[15] = ctx->num_bits_in_msg;
-
-    /* process the word array */
-    for (t=16; t < 80; t++) {
-      TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
-      W[t] = S1(TEMP);
-    }
+    unsigned char *fcp = &finalcount[8];
 
-    A = ctx->H[0];
-    B = ctx->H[1];
-    C = ctx->H[2];
-    D = ctx->H[3];
-    E = ctx->H[4];
+    for (i = 0; i < 2; i++)
+    {
+        uint32_t t = context->count[i];
 
-    for (t=0; t < 20; t++) {
-      TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
-    }
-    for (   ; t < 40; t++) {
-      TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
+        int j;
+
+        for (j = 0; j < 4; t >>= 8, j++)
+            *--fcp = (unsigned char) t}
+#else
+    for (i = 0; i < 8; i++)
+    {
+        finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255);      /* Endian independent */
     }
-    for (   ; t < 60; t++) {
-      TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
+#endif
+    c = 0200;
+    SHA1Update(context, &c, 1);
+    while ((context->count[0] & 504) != 448)
+    {
+        c = 0000;
+        SHA1Update(context, &c, 1);
     }
-    for (   ; t < 80; t++) {
-      TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
-      E = D; D = C; C = S30(B); B = A; A = TEMP;
+    SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+    for (i = 0; i < 20; i++)
+    {
+        digest[i] = (unsigned char)
+            ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
     }
-
-    ctx->H[0] += A;
-    ctx->H[1] += B;
-    ctx->H[2] += C;
-    ctx->H[3] += D;
-    ctx->H[4] += E;
-  }
-
-  /* copy result into output buffer */
-  output[0] = be32_to_cpu(ctx->H[0]);
-  output[1] = be32_to_cpu(ctx->H[1]);
-  output[2] = be32_to_cpu(ctx->H[2]);
-  output[3] = be32_to_cpu(ctx->H[3]);
-  output[4] = be32_to_cpu(ctx->H[4]);
-
-  /* indicate that message buffer in context is empty */
-  ctx->octets_in_buffer = 0;
-
-  return;
+    /* Wipe variables */
+    memset(context, '\0', sizeof(*context));
+    memset(&finalcount, '\0', sizeof(finalcount));
 }
 
-
+void SHA1(
+    char *hash_out,
+    const char *str,
+    int len)
+{
+    SHA1_CTX ctx;
+    unsigned int ii;
+
+    SHA1Init(&ctx);
+    for (ii=0; ii<len; ii+=1)
+        SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
+    SHA1Final((unsigned char *)hash_out, &ctx);
+}
 
index 755628a..96bb008 100755 (executable)
-/*
- * sha1.h
- *
- * interface to the Secure Hash Algorithm v.1 (SHA-1), specified in
- * FIPS 180-1
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
-
-/*
- *
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *   Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- *   Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- *   Neither the name of the Cisco Systems, Inc. nor the names of its
- *   contributors may be used to endorse or promote products derived
- *   from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
 #ifndef SHA1_H
 #define SHA1_H
-#define SHA_DIGEST_SIZE 20
-#define be32_to_cpu(x) (uint32_t)      ( \
-                               (((uint32_t)(x) & 0xff000000u) >> 24) | \
-                       (((uint32_t)(x) & 0x00ff0000u) >>  8) | \
-                       (((uint32_t)(x) & 0x0000ff00u) <<  8) | \
-                       (((uint32_t)(x) & 0x000000ffu) << 24))
-
-
-typedef unsigned int uint32_t;
-typedef unsigned char uint8_t;
-typedef struct {
-  uint32_t H[5];             /* state vector                    */
-  uint32_t M[16];            /* message buffer                  */
-  int octets_in_buffer;      /* octets of message in buffer     */
-  uint32_t num_bits_in_msg;  /* total number of bits in message */
-} sha1_ctx_t;
-
-/*
- * sha1(&ctx, msg, len, output) hashes the len octets starting at msg
- * into the SHA1 context, then writes the result to the 20 octets at
- * output
- *
- */
-
-void
-sha1(const uint8_t *message,  int octets_in_msg, uint32_t output[5]);
-
-/*
- * sha1_init(&ctx) initializes the SHA1 context ctx
- *
- * sha1_update(&ctx, msg, len) hashes the len octets starting at msg
- * into the SHA1 context
- *
- * sha1_final(&ctx, output) performs the final processing of the SHA1
- * context and writes the result to the 20 octets at output
- *
- */
-
-void
-sha1_init(sha1_ctx_t *ctx);
-
-void
-sha1_update(sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg);
-
-void
-sha1_final(sha1_ctx_t *ctx, uint32_t output[5]);
-
-/*
- * The sha1_core function is INTERNAL to SHA-1, but it is declared
- * here because it is also used by the cipher SEAL 3.0 in its key
- * setup algorithm.
- */
 
 /*
- *  sha1_core(M, H) computes the core sha1 compression function, where M is
- *  the next part of the message and H is the intermediate state {H0,
- *  H1, ...}
- *
- *  this function does not do any of the padding required in the
- *  complete sha1 function
+   SHA-1 in C
+   By Steve Reid <steve@edmweb.com>
+   100% Public Domain
  */
 
-void
-sha1_core(const uint32_t M[16], uint32_t hash_value[5]);
+#include "stdint.h"
+
+typedef struct
+{
+    uint32_t state[5];
+    uint32_t count[2];
+    unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(
+    uint32_t state[5],
+    const unsigned char buffer[64]
+    );
+
+void SHA1Init(
+    SHA1_CTX * context
+    );
+
+void SHA1Update(
+    SHA1_CTX * context,
+    const unsigned char *data,
+    uint32_t len
+    );
+
+void SHA1Final(
+    unsigned char digest[20],
+    SHA1_CTX * context
+    );
+
+void SHA1(
+    char *hash_out,
+    const char *str,
+    int len);
 
 #endif /* SHA1_H */