LCOV - code coverage report
Current view: top level - lib - sha1.c (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 63 0.0 %
Date: 2023-04-18 16:19:03 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*
       2             : SHA-1 in C
       3             : By Steve Reid <steve@edmweb.com>
       4             : 100% Public Domain
       5             : 
       6             : Test Vectors (from FIPS PUB 180-1)
       7             : "abc"
       8             :   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
       9             : "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
      10             :   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
      11             : A million repetitions of "a"
      12             :   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
      13             : */
      14             : 
      15             : #include "sha1.h"
      16             : #include <stdint.h>
      17             : #include <stdio.h>
      18             : #include <string.h>
      19             : #include <endian.h>
      20             : 
      21             : #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
      22             : 
      23             : /* blk0() and blk() perform the initial expand. */
      24             : /* I got the idea of expanding during the round function from SSLeay */
      25             : #define blk0(i) (block[i] = htobe32(block[i]))
      26             : #define blk(i)                                                                 \
      27             :     (block[i & 15] = rol(block[(i + 13) & 15] ^ block[(i + 8) & 15] ^          \
      28             :                              block[(i + 2) & 15] ^ block[i & 15],              \
      29             :                          1))
      30             : 
      31             : /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
      32             : #define R0(v, w, x, y, z, i)                                                   \
      33             :     z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5);               \
      34             :     w = rol(w, 30);
      35             : #define R1(v, w, x, y, z, i)                                                   \
      36             :     z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5);                \
      37             :     w = rol(w, 30);
      38             : #define R2(v, w, x, y, z, i)                                                   \
      39             :     z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5);                        \
      40             :     w = rol(w, 30);
      41             : #define R3(v, w, x, y, z, i)                                                   \
      42             :     z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5);          \
      43             :     w = rol(w, 30);
      44             : #define R4(v, w, x, y, z, i)                                                   \
      45             :     z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5);                        \
      46             :     w = rol(w, 30);
      47             : 
      48             : /* Hash a single 512-bit block. This is the core of the algorithm. */
      49             : 
      50             : #define STATE(i)                state[(index + (i)) % 5]
      51             : 
      52           0 : static void sha1_transform(uint32_t orig_state[5], const unsigned char buffer[64])
      53             : {
      54             :     uint32_t state[5];
      55             :     uint32_t block[16];
      56           0 :     int round = 0;
      57           0 :     int index = 0;
      58             : 
      59           0 :     memcpy(block, buffer, sizeof(block));
      60             : 
      61             :     /* Copy context->state[] to working vars */
      62           0 :     memcpy(state, orig_state, sizeof(state));
      63             : 
      64             :     /* 4 rounds of 20 operations each. */
      65           0 :     for (; round < 16; round++, index += 4) {
      66           0 :         R0(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
      67             :     }
      68           0 :     for (; round < 20; round++, index += 4) {
      69           0 :         R1(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
      70             :     }
      71             : 
      72           0 :     for (; round < 40; round++, index += 4) {
      73           0 :         R2(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
      74             :     }
      75             : 
      76           0 :     for (; round < 60; round++, index += 4) {
      77           0 :         R3(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
      78             :     }
      79             : 
      80           0 :     for (; round < 80; round++, index += 4) {
      81           0 :         R4(STATE(0), STATE(1), STATE(2), STATE(3), STATE(4), round);
      82             :     }
      83             : 
      84             :     /* Add the working vars back into context.state[] */
      85           0 :     for (int i = 0; i < 5; i++)
      86           0 :         orig_state[i] += state[i];
      87             : 
      88             :     /* Wipe transient state */
      89           0 :     memset(state, 0, sizeof(state));
      90           0 :     memset(block, 0, sizeof(block));
      91           0 :     __asm__ volatile("" : : "g"(block), "g"(state) : "memory");
      92           0 : }
      93             : 
      94             : /* sha1_init - Initialize new context */
      95             : 
      96           0 : void sha1_init(sha1_context *context)
      97             : {
      98             :     /* SHA1 initialization constants */
      99           0 :     context->state[0] = 0x67452301;
     100           0 :     context->state[1] = 0xEFCDAB89;
     101           0 :     context->state[2] = 0x98BADCFE;
     102           0 :     context->state[3] = 0x10325476;
     103           0 :     context->state[4] = 0xC3D2E1F0;
     104           0 :     context->count[0] = context->count[1] = 0;
     105           0 : }
     106             : 
     107             : /* Run your data through this. */
     108             : 
     109           0 : void sha1_update(sha1_context *context, const unsigned char *data, size_t len)
     110             : {
     111             :     size_t i;
     112             :     size_t j;
     113             : 
     114           0 :     j = context->count[0];
     115           0 :     if ((context->count[0] += len << 3) < j)
     116           0 :         context->count[1]++;
     117           0 :     context->count[1] += (len >> 29);
     118             : 
     119           0 :     j = (j >> 3) & 63;
     120             : 
     121           0 :     if ((j + len) > 63) {
     122           0 :         i = 64 - j;
     123           0 :         memcpy(&context->buffer[j], data, i);
     124           0 :         sha1_transform(context->state, context->buffer);
     125             : 
     126           0 :         for (; i + 63 < len; i += 64)
     127           0 :             sha1_transform(context->state, &data[i]);
     128             : 
     129           0 :         j = 0;
     130             :     } else {
     131           0 :         i = 0;
     132             :     }
     133             : 
     134           0 :     memcpy(&context->buffer[j], &data[i], len - i);
     135           0 : }
     136             : 
     137             : /* Add padding and return the message digest. */
     138             : 
     139           0 : void sha1_finalize(sha1_context *context, unsigned char digest[20])
     140             : {
     141             :     unsigned i;
     142             :     unsigned char finalcount[8];
     143             :     unsigned char c;
     144             : 
     145           0 :     for (i = 0; i < 8; i++) {
     146           0 :         finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >>
     147           0 :                                          ((3 - (i & 3)) * 8)) &
     148             :                                         255); /* Endian independent */
     149             :     }
     150             : 
     151           0 :     c = 0200;
     152           0 :     sha1_update(context, &c, 1);
     153           0 :     while ((context->count[0] & 504) != 448) {
     154           0 :         c = 0000;
     155           0 :         sha1_update(context, &c, 1);
     156             :     }
     157           0 :     sha1_update(context, finalcount, 8); /* Should cause a sha1_transform() */
     158           0 :     for (i = 0; i < 20; i++) {
     159           0 :         digest[i] =
     160           0 :             (unsigned char)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
     161             :                             255);
     162             :     }
     163             : 
     164             :     /* Wipe variables */
     165           0 :     memset(context, '\0', sizeof(*context));
     166           0 :     __asm__ volatile("" : : "g"(context) : "memory");
     167             : 
     168           0 :     memset(&finalcount, '\0', sizeof(finalcount));
     169           0 :     __asm__ volatile("" : : "g"(finalcount) : "memory");
     170           0 : }
     171             : 
     172             : 
     173             : #ifdef SHA1_TEST
     174             : #include <unistd.h>
     175             : 
     176             : int main(int argc, char *argv)
     177             : {
     178             :     sha1_context ctx;
     179             :     unsigned char buffer[512];
     180             :     unsigned char digest[20];
     181             : 
     182             :     sha1_init(&ctx);
     183             : 
     184             :     for (;;) {
     185             :         ssize_t r = read(fileno(stdin), buffer, sizeof(buffer));
     186             : 
     187             :         if (r < 0) {
     188             :             perror("read");
     189             :             return 1;
     190             :         }
     191             : 
     192             :         sha1_update(&ctx, buffer, (size_t)r);
     193             : 
     194             :         if (r < (ssize_t)sizeof(buffer))
     195             :             break;
     196             :     }
     197             : 
     198             :     sha1_finalize(&ctx, digest);
     199             : 
     200             :     printf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%"
     201             :            "02x%02x%02x%02x\n",
     202             :            digest[0], digest[1], digest[2], digest[3], digest[4], digest[5],
     203             :            digest[6], digest[7], digest[8], digest[9], digest[10], digest[11],
     204             :            digest[12], digest[13], digest[14], digest[15], digest[16],
     205             :            digest[17], digest[18], digest[19]);
     206             : }
     207             : #endif

Generated by: LCOV version 1.15-2-gb9d6727