Coverage Report

Created: 2025-08-29 06:36

/src/libevent/sha1.c
Line
Count
Source (jump to first uncovered line)
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
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
16
/* #define SHA1HANDSOFF * Copies data before messing with it. */
17
18
#define SHA1HANDSOFF
19
20
#if defined(__clang__)
21
#elif defined(__GNUC__)
22
#pragma GCC diagnostic push
23
/* Ignore the case when SHA1Transform() called with 'char *', that code passed
24
 * buffer of 64 bytes anyway (at least now) */
25
#pragma GCC diagnostic ignored "-Wstringop-overread"
26
#endif
27
28
#include <stdio.h>
29
#include <string.h>
30
31
/* for uint32_t */
32
#include <stdint.h>
33
34
#include "sha1.h"
35
36
0
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
37
38
/* blk0() and blk() perform the initial expand. */
39
/* I got the idea of expanding during the round function from SSLeay */
40
#if defined(LITTLE_ENDIAN)
41
#define blk0(i)                                                                \
42
0
    (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) |                       \
43
0
                   (rol(block->l[i], 8) & 0x00FF00FF))
44
#elif defined(BIG_ENDIAN)
45
#define blk0(i) block->l[i]
46
#else
47
#error "Endianness not defined!"
48
#endif
49
#define blk(i)                                                                 \
50
0
    (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
51
0
                                block->l[(i + 2) & 15] ^ block->l[i & 15],     \
52
0
                            1))
53
54
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
55
#define R0(v, w, x, y, z, i)                                                   \
56
0
    z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5);               \
57
0
    w = rol(w, 30);
58
#define R1(v, w, x, y, z, i)                                                   \
59
0
    z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5);                \
60
0
    w = rol(w, 30);
61
#define R2(v, w, x, y, z, i)                                                   \
62
0
    z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5);                        \
63
0
    w = rol(w, 30);
64
#define R3(v, w, x, y, z, i)                                                   \
65
0
    z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5);          \
66
0
    w = rol(w, 30);
67
#define R4(v, w, x, y, z, i)                                                   \
68
0
    z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5);                        \
69
0
    w = rol(w, 30);
70
71
typedef struct {
72
    uint32_t state[5];
73
    uint32_t count[2];
74
    unsigned char buffer[64];
75
} SHA1_CTX;
76
77
static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]);
78
79
static void SHA1Init(SHA1_CTX *context);
80
81
static void SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len);
82
83
static void SHA1Final(unsigned char digest[20], SHA1_CTX *context);
84
85
86
/* Hash a single 512-bit block. This is the core of the algorithm. */
87
88
0
static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) {
89
0
    uint32_t a, b, c, d, e;
90
91
0
    typedef union {
92
0
        unsigned char c[64];
93
0
        uint32_t l[16];
94
0
    } CHAR64LONG16;
95
96
0
#ifdef SHA1HANDSOFF
97
0
    CHAR64LONG16 block[1]; /* use array to appear as a pointer */
98
99
0
    memcpy(block, buffer, 64);
100
#else
101
    /* The following had better never be used because it causes the
102
     * pointer-to-const buffer to be cast into a pointer to non-const.
103
     * And the result is written through.  I threw a "const" in, hoping
104
     * this will cause a diagnostic.
105
     */
106
    CHAR64LONG16 *block = (const CHAR64LONG16 *)buffer;
107
#endif
108
    /* Copy context->state[] to working vars */
109
0
    a = state[0];
110
0
    b = state[1];
111
0
    c = state[2];
112
0
    d = state[3];
113
0
    e = state[4];
114
    /* 4 rounds of 20 operations each. Loop unrolled. */
115
0
    R0(a, b, c, d, e, 0);
116
0
    R0(e, a, b, c, d, 1);
117
0
    R0(d, e, a, b, c, 2);
118
0
    R0(c, d, e, a, b, 3);
119
0
    R0(b, c, d, e, a, 4);
120
0
    R0(a, b, c, d, e, 5);
121
0
    R0(e, a, b, c, d, 6);
122
0
    R0(d, e, a, b, c, 7);
123
0
    R0(c, d, e, a, b, 8);
124
0
    R0(b, c, d, e, a, 9);
125
0
    R0(a, b, c, d, e, 10);
126
0
    R0(e, a, b, c, d, 11);
127
0
    R0(d, e, a, b, c, 12);
128
0
    R0(c, d, e, a, b, 13);
129
0
    R0(b, c, d, e, a, 14);
130
0
    R0(a, b, c, d, e, 15);
131
0
    R1(e, a, b, c, d, 16);
132
0
    R1(d, e, a, b, c, 17);
133
0
    R1(c, d, e, a, b, 18);
134
0
    R1(b, c, d, e, a, 19);
135
0
    R2(a, b, c, d, e, 20);
136
0
    R2(e, a, b, c, d, 21);
137
0
    R2(d, e, a, b, c, 22);
138
0
    R2(c, d, e, a, b, 23);
139
0
    R2(b, c, d, e, a, 24);
140
0
    R2(a, b, c, d, e, 25);
141
0
    R2(e, a, b, c, d, 26);
142
0
    R2(d, e, a, b, c, 27);
143
0
    R2(c, d, e, a, b, 28);
144
0
    R2(b, c, d, e, a, 29);
145
0
    R2(a, b, c, d, e, 30);
146
0
    R2(e, a, b, c, d, 31);
147
0
    R2(d, e, a, b, c, 32);
148
0
    R2(c, d, e, a, b, 33);
149
0
    R2(b, c, d, e, a, 34);
150
0
    R2(a, b, c, d, e, 35);
151
0
    R2(e, a, b, c, d, 36);
152
0
    R2(d, e, a, b, c, 37);
153
0
    R2(c, d, e, a, b, 38);
154
0
    R2(b, c, d, e, a, 39);
155
0
    R3(a, b, c, d, e, 40);
156
0
    R3(e, a, b, c, d, 41);
157
0
    R3(d, e, a, b, c, 42);
158
0
    R3(c, d, e, a, b, 43);
159
0
    R3(b, c, d, e, a, 44);
160
0
    R3(a, b, c, d, e, 45);
161
0
    R3(e, a, b, c, d, 46);
162
0
    R3(d, e, a, b, c, 47);
163
0
    R3(c, d, e, a, b, 48);
164
0
    R3(b, c, d, e, a, 49);
165
0
    R3(a, b, c, d, e, 50);
166
0
    R3(e, a, b, c, d, 51);
167
0
    R3(d, e, a, b, c, 52);
168
0
    R3(c, d, e, a, b, 53);
169
0
    R3(b, c, d, e, a, 54);
170
0
    R3(a, b, c, d, e, 55);
171
0
    R3(e, a, b, c, d, 56);
172
0
    R3(d, e, a, b, c, 57);
173
0
    R3(c, d, e, a, b, 58);
174
0
    R3(b, c, d, e, a, 59);
175
0
    R4(a, b, c, d, e, 60);
176
0
    R4(e, a, b, c, d, 61);
177
0
    R4(d, e, a, b, c, 62);
178
0
    R4(c, d, e, a, b, 63);
179
0
    R4(b, c, d, e, a, 64);
180
0
    R4(a, b, c, d, e, 65);
181
0
    R4(e, a, b, c, d, 66);
182
0
    R4(d, e, a, b, c, 67);
183
0
    R4(c, d, e, a, b, 68);
184
0
    R4(b, c, d, e, a, 69);
185
0
    R4(a, b, c, d, e, 70);
186
0
    R4(e, a, b, c, d, 71);
187
0
    R4(d, e, a, b, c, 72);
188
0
    R4(c, d, e, a, b, 73);
189
0
    R4(b, c, d, e, a, 74);
190
0
    R4(a, b, c, d, e, 75);
191
0
    R4(e, a, b, c, d, 76);
192
0
    R4(d, e, a, b, c, 77);
193
0
    R4(c, d, e, a, b, 78);
194
0
    R4(b, c, d, e, a, 79);
195
    /* Add the working vars back into context.state[] */
196
0
    state[0] += a;
197
0
    state[1] += b;
198
0
    state[2] += c;
199
0
    state[3] += d;
200
0
    state[4] += e;
201
0
#ifdef SHA1HANDSOFF
202
0
    memset(block, '\0', sizeof(block));
203
0
#endif
204
0
}
205
206
/* SHA1Init - Initialize new context */
207
208
0
static void SHA1Init(SHA1_CTX *context) {
209
    /* SHA1 initialization constants */
210
0
    context->state[0] = 0x67452301;
211
0
    context->state[1] = 0xEFCDAB89;
212
0
    context->state[2] = 0x98BADCFE;
213
0
    context->state[3] = 0x10325476;
214
0
    context->state[4] = 0xC3D2E1F0;
215
0
    context->count[0] = context->count[1] = 0;
216
0
}
217
218
/* Run your data through this. */
219
220
0
static void SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len) {
221
0
    uint32_t i;
222
223
0
    uint32_t j;
224
225
0
    j = context->count[0];
226
0
    if ((context->count[0] += len << 3) < j)
227
0
        context->count[1]++;
228
0
    context->count[1] += (len >> 29);
229
0
    j = (j >> 3) & 63;
230
0
    if ((j + len) > 63) {
231
0
        memcpy(&context->buffer[j], data, (i = 64 - j));
232
0
        SHA1Transform(context->state, context->buffer);
233
0
        for (; i + 63 < len; i += 64) {
234
0
            SHA1Transform(context->state, &data[i]);
235
0
        }
236
0
        j = 0;
237
0
    } else
238
0
        i = 0;
239
0
    memcpy(&context->buffer[j], &data[i], len - i);
240
0
}
241
242
/* Add padding and return the message digest. */
243
244
0
static void SHA1Final(unsigned char digest[20], SHA1_CTX *context) {
245
0
    unsigned i;
246
247
0
    unsigned char finalcount[8];
248
249
0
    unsigned char c;
250
251
#if 0 /* untested "improvement" by DHR */
252
    /* Convert context->count to a sequence of bytes
253
     * in finalcount.  Second element first, but
254
     * big-endian order within element.
255
     * But we do it all backwards.
256
     */
257
    unsigned char *fcp = &finalcount[8];
258
259
    for (i = 0; i < 2; i++)
260
    {
261
        uint32_t t = context->count[i];
262
263
        int j;
264
265
        for (j = 0; j < 4; t >>= 8, j++)
266
            *--fcp = (unsigned char) t}
267
#else
268
0
    for (i = 0; i < 8; i++) {
269
0
        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >>
270
0
                                         ((3 - (i & 3)) * 8)) &
271
0
                                        255); /* Endian independent */
272
0
    }
273
0
#endif
274
0
    c = 0200;
275
0
    SHA1Update(context, &c, 1);
276
0
    while ((context->count[0] & 504) != 448) {
277
0
        c = 0000;
278
0
        SHA1Update(context, &c, 1);
279
0
    }
280
0
    SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
281
0
    for (i = 0; i < 20; i++) {
282
0
        digest[i] =
283
0
            (unsigned char)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
284
0
                            255);
285
0
    }
286
    /* Wipe variables */
287
0
    memset(context, '\0', sizeof(*context));
288
0
    memset(&finalcount, '\0', sizeof(finalcount));
289
0
}
290
291
0
void builtin_SHA1(char *hash_out, const char *str, int len) {
292
0
    SHA1_CTX ctx;
293
0
    int ii;
294
295
0
    SHA1Init(&ctx);
296
0
    for (ii = 0; ii < len; ii += 1)
297
0
        SHA1Update(&ctx, (const unsigned char *)str + ii, 1);
298
0
    SHA1Final((unsigned char *)hash_out, &ctx);
299
0
}