LCOV - code coverage report
Current view: top level - src - sha1.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 91 93 97.8 %
Date: 2024-02-24 00:00:00 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /** @file
       2             :  *  SHA-1 hash.
       3             :  */
       4             : 
       5             : /*
       6             : SHA-1 in C
       7             : By Steve Reid <sreid@sea-to-sky.net>
       8             : 100% Public Domain
       9             : 
      10             : -----------------
      11             : Modified 7/98
      12             : By James H. Brown <jbrown@burgoyne.com>
      13             : Still 100% Public Domain
      14             : 
      15             : Corrected a problem which generated improper hash values on 16 bit machines
      16             : Routine SHA1Update changed from
      17             :     void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
      18             : len)
      19             : to
      20             :     void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
      21             : long len)
      22             : 
      23             : The 'len' parameter was declared an int which works fine on 32 bit machines.
      24             : However, on 16 bit machines an int is too small for the shifts being done
      25             : against
      26             : it.  This caused the hash function to generate incorrect values if len was
      27             : greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
      28             : 
      29             : Since the file IO in main() reads 16K at a time, any file 8K or larger would
      30             : be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
      31             : "a"s).
      32             : 
      33             : I also changed the declaration of variables i & j in SHA1Update to
      34             : unsigned long from unsigned int for the same reason.
      35             : 
      36             : These changes should make no difference to any 32 bit implementations since
      37             : an
      38             : int and a long are the same size in those environments.
      39             : 
      40             : --
      41             : I also corrected a few compiler warnings generated by Borland C.
      42             : 1. Added #include <process.h> for exit() prototype
      43             : 2. Removed unused variable 'j' in SHA1Final
      44             : 3. Changed exit(0) to return(0) at end of main.
      45             : 
      46             : ALL changes I made can be located by searching for comments containing 'JHB'
      47             : -----------------
      48             : Modified 8/98
      49             : By Steve Reid <sreid@sea-to-sky.net>
      50             : Still 100% public domain
      51             : 
      52             : 1- Removed #include <process.h> and used return() instead of exit()
      53             : 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
      54             : 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
      55             : 
      56             : -----------------
      57             : Modified 4/01
      58             : By Saul Kravitz <Saul.Kravitz@celera.com>
      59             : Still 100% PD
      60             : Modified to run on Compaq Alpha hardware.
      61             : 
      62             : -----------------
      63             : Modified 07/2002
      64             : By Ralph Giles <giles@artofcode.com>
      65             : Still 100% public domain
      66             : modified for use with stdint types, autoconf
      67             : code cleanup, removed attribution comments
      68             : switched SHA1Final() argument order for consistency
      69             : use SHA1_ prefix for public api
      70             : move public api to sha1.h
      71             : */
      72             : 
      73             : #include <string.h>
      74             : 
      75             : #include "ostypes.h"
      76             : #include "sha1.h"
      77             : 
      78             : static uint32_t host_to_be(uint32_t i);
      79             : static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
      80             : 
      81             : #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
      82             : 
      83             : /* blk0() and blk() perform the initial expand. */
      84             : /* I got the idea of expanding during the round function from SSLeay */
      85             : #define blk0(i) (block->l[i] = host_to_be(block->l[i]))
      86             : #define blk(i)                                                                 \
      87             :     (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
      88             :                                 block->l[(i + 2) & 15] ^ block->l[i & 15],     \
      89             :                             1))
      90             : 
      91             : /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
      92             : #define R0(v, w, x, y, z, i)                                     \
      93             :     z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
      94             :     w = rol(w, 30);
      95             : #define R1(v, w, x, y, z, i)                                    \
      96             :     z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
      97             :     w = rol(w, 30);
      98             : #define R2(v, w, x, y, z, i)                            \
      99             :     z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
     100             :     w = rol(w, 30);
     101             : #define R3(v, w, x, y, z, i)                                          \
     102             :     z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
     103             :     w = rol(w, 30);
     104             : #define R4(v, w, x, y, z, i)                            \
     105             :     z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
     106             :     w = rol(w, 30);
     107             : 
     108          16 : static uint32_t host_to_be(uint32_t i)
     109             : {
     110             : #define le_to_be(i) ((rol((i), 24) & 0xFF00FF00) | (rol((i), 8) & 0x00FF00FF))
     111             : #if defined(__BIG_ENDIAN__) ||                                   \
     112             :     (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
     113             :      __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
     114             :     return i;
     115             : #elif defined(__LITTLE_ENDIAN__) ||                                 \
     116             :     (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
     117             :      __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
     118          16 :     return le_to_be(i);
     119             : #else /* fallback to run-time check */
     120             :     static const union {
     121             :         uint32_t u;
     122             :         unsigned char c;
     123             :     } check = {1};
     124             :     return check.c ? le_to_be(i) : i;
     125             : #endif
     126             : #undef le_to_be
     127             : }
     128             : 
     129             : static void *(*volatile SHA1_explicit_memset)(void *, int, size_t) = &memset;
     130             : 
     131         112 : static void SHA1_cleanse(void *p, size_t len)
     132             : {
     133         112 :     SHA1_explicit_memset(p, 0, len);
     134             : }
     135             : 
     136             : /* Hash a single 512-bit block. This is the core of the algorithm. */
     137          16 : static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
     138             : {
     139          16 :     uint32_t a, b, c, d, e;
     140          16 :     typedef union {
     141             :         uint8_t c[64];
     142             :         uint32_t l[16];
     143             :     } CHAR64LONG16;
     144          16 :     CHAR64LONG16 *block;
     145             : 
     146          16 :     static uint8_t workspace[64];
     147          16 :     block = (CHAR64LONG16 *)workspace;
     148          16 :     memcpy(block, buffer, 64);
     149             : 
     150             :     /* Copy context->state[] to working vars */
     151          16 :     a = state[0];
     152          16 :     b = state[1];
     153          16 :     c = state[2];
     154          16 :     d = state[3];
     155          16 :     e = state[4];
     156             : 
     157             :     /* 4 rounds of 20 operations each. Loop unrolled. */
     158             :     /* clang-format off */
     159          16 :     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);
     160          16 :     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);
     161          16 :     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);
     162          16 :     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);
     163          16 :     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);
     164          16 :     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);
     165          16 :     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);
     166          16 :     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);
     167          16 :     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);
     168          16 :     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);
     169          16 :     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);
     170          16 :     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);
     171          16 :     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);
     172          16 :     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);
     173          16 :     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);
     174          16 :     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);
     175          16 :     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);
     176          16 :     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);
     177          16 :     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);
     178          16 :     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);
     179             :     /* clang-format on */
     180             : 
     181             :     /* Add the working vars back into context.state[] */
     182          16 :     state[0] += a;
     183          16 :     state[1] += b;
     184          16 :     state[2] += c;
     185          16 :     state[3] += d;
     186          16 :     state[4] += e;
     187             : 
     188             :     /* Wipe variables */
     189          16 :     SHA1_cleanse(&a, sizeof(a));
     190          16 :     SHA1_cleanse(&b, sizeof(b));
     191          16 :     SHA1_cleanse(&c, sizeof(c));
     192          16 :     SHA1_cleanse(&d, sizeof(d));
     193          16 :     SHA1_cleanse(&e, sizeof(e));
     194          16 : }
     195             : 
     196             : /* SHA1Init - Initialize new context */
     197           8 : void crypto_SHA1_Init(SHA1_CTX *context)
     198             : {
     199             :     /* SHA1 initialization constants */
     200           8 :     context->state[0] = 0x67452301;
     201           8 :     context->state[1] = 0xEFCDAB89;
     202           8 :     context->state[2] = 0x98BADCFE;
     203           8 :     context->state[3] = 0x10325476;
     204           8 :     context->state[4] = 0xC3D2E1F0;
     205           8 :     context->count[0] = context->count[1] = 0;
     206           8 : }
     207             : 
     208             : /* Run your data through this. */
     209         336 : void crypto_SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len)
     210             : {
     211         336 :     size_t i, j;
     212             : 
     213         336 :     j = (context->count[0] >> 3) & 63;
     214         336 :     if ((context->count[0] += (uint32_t)len << 3) < ((uint32_t)len << 3))
     215           0 :         context->count[1]++;
     216         336 :     context->count[1] += (uint32_t)(len >> 29);
     217         336 :     if ((j + len) > 63) {
     218           8 :         memcpy(&context->buffer[j], data, (i = 64 - j));
     219           8 :         SHA1_Transform(context->state, context->buffer);
     220          16 :         for (; i + 63 < len; i += 64) {
     221           0 :             SHA1_Transform(context->state, data + i);
     222             :         }
     223             :         j = 0;
     224             :     } else
     225             :         i = 0;
     226         336 :     memcpy(&context->buffer[j], &data[i], len - i);
     227         336 : }
     228             : 
     229             : /* Add padding and return the message digest. */
     230           8 : void crypto_SHA1_Final(SHA1_CTX *context, uint8_t *digest)
     231             : {
     232           8 :     uint32_t i;
     233           8 :     uint8_t finalcount[8];
     234             : 
     235          72 :     for (i = 0; i < 8; i++) {
     236          64 :         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >>
     237          64 :                                          ((3 - (i & 3)) * 8)) &
     238             :                                         255); /* Endian independent */
     239             :     }
     240           8 :     crypto_SHA1_Update(context, (uint8_t *)"\200", 1);
     241         320 :     while ((context->count[0] & 504) != 448) {
     242         312 :         crypto_SHA1_Update(context, (uint8_t *)"\0", 1);
     243             :     }
     244             :     /* Should cause a SHA1_Transform() */
     245           8 :     crypto_SHA1_Update(context, finalcount, 8);
     246         168 :     for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
     247         160 :         digest[i] =
     248         160 :             (uint8_t)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
     249             :     }
     250             : 
     251             :     /* Wipe variables */
     252           8 :     SHA1_cleanse(context->buffer, 64);
     253           8 :     SHA1_cleanse(context->state, 20);
     254           8 :     SHA1_cleanse(context->count, 8);
     255           8 :     SHA1_cleanse(finalcount, 8); /* SWR */
     256             : 
     257           8 :     SHA1_Transform(context->state, context->buffer);
     258           8 : }
     259             : 
     260           8 : void crypto_SHA1(const uint8_t *data, size_t len, uint8_t *digest)
     261             : {
     262           8 :     SHA1_CTX ctx;
     263           8 :     crypto_SHA1_Init(&ctx);
     264           8 :     crypto_SHA1_Update(&ctx, data, len);
     265           8 :     crypto_SHA1_Final(&ctx, digest);
     266           8 : }

Generated by: LCOV version 1.14