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

            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 2.0-1