Coverage Report

Created: 2025-06-22 06:56

/src/util-linux/lib/sha1.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * No copyright is claimed.  This code is in the public domain; do with
3
 * it what you wish.
4
 *
5
 * SHA-1 in C by Steve Reid <steve@edmweb.com>
6
 * 100% Public Domain
7
 *
8
 * Test Vectors (from FIPS PUB 180-1)
9
 * 1) "abc": A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
10
 * 2) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq":  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
11
 * 3) A million repetitions of "a":  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
12
 */
13
14
#define UL_SHA1HANDSOFF
15
16
#include <stdio.h>
17
#include <string.h>
18
#include <stdint.h>
19
20
#include "sha1.h"
21
22
0
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
23
24
/* blk0() and blk() perform the initial expand. */
25
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
26
# define blk0(i) block->l[i]
27
#else
28
0
# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
29
0
    |(rol(block->l[i],8)&0x00FF00FF))
30
#endif
31
32
0
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
33
0
    ^block->l[(i+2)&15]^block->l[i&15],1))
34
35
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
36
0
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
37
0
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
38
0
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
39
0
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
40
0
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
41
42
/* Hash a single 512-bit block. This is the core of the algorithm. */
43
44
void ul_SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
45
0
{
46
0
  uint32_t a, b, c, d, e;
47
48
0
  typedef union {
49
0
    unsigned char c[64];
50
0
    uint32_t l[16];
51
0
  } CHAR64LONG16;
52
53
0
#ifdef UL_SHA1HANDSOFF
54
0
  CHAR64LONG16 block[1];  /* use array to appear as a pointer */
55
56
0
  memcpy(block, buffer, 64);
57
#else
58
  /* The following had better never be used because it causes the
59
   * pointer-to-const buffer to be cast into a pointer to non-const.
60
   * And the result is written through.  I threw a "const" in, hoping
61
   * this will cause a diagnostic.
62
   */
63
  CHAR64LONG16 *block = (const CHAR64LONG16 *)buffer;
64
#endif
65
  /* Copy context->state[] to working vars */
66
0
  a = state[0];
67
0
  b = state[1];
68
0
  c = state[2];
69
0
  d = state[3];
70
0
  e = state[4];
71
  /* 4 rounds of 20 operations each. Loop unrolled. */
72
0
  R0(a, b, c, d, e, 0);
73
0
  R0(e, a, b, c, d, 1);
74
0
  R0(d, e, a, b, c, 2);
75
0
  R0(c, d, e, a, b, 3);
76
0
  R0(b, c, d, e, a, 4);
77
0
  R0(a, b, c, d, e, 5);
78
0
  R0(e, a, b, c, d, 6);
79
0
  R0(d, e, a, b, c, 7);
80
0
  R0(c, d, e, a, b, 8);
81
0
  R0(b, c, d, e, a, 9);
82
0
  R0(a, b, c, d, e, 10);
83
0
  R0(e, a, b, c, d, 11);
84
0
  R0(d, e, a, b, c, 12);
85
0
  R0(c, d, e, a, b, 13);
86
0
  R0(b, c, d, e, a, 14);
87
0
  R0(a, b, c, d, e, 15);
88
0
  R1(e, a, b, c, d, 16);
89
0
  R1(d, e, a, b, c, 17);
90
0
  R1(c, d, e, a, b, 18);
91
0
  R1(b, c, d, e, a, 19);
92
0
  R2(a, b, c, d, e, 20);
93
0
  R2(e, a, b, c, d, 21);
94
0
  R2(d, e, a, b, c, 22);
95
0
  R2(c, d, e, a, b, 23);
96
0
  R2(b, c, d, e, a, 24);
97
0
  R2(a, b, c, d, e, 25);
98
0
  R2(e, a, b, c, d, 26);
99
0
  R2(d, e, a, b, c, 27);
100
0
  R2(c, d, e, a, b, 28);
101
0
  R2(b, c, d, e, a, 29);
102
0
  R2(a, b, c, d, e, 30);
103
0
  R2(e, a, b, c, d, 31);
104
0
  R2(d, e, a, b, c, 32);
105
0
  R2(c, d, e, a, b, 33);
106
0
  R2(b, c, d, e, a, 34);
107
0
  R2(a, b, c, d, e, 35);
108
0
  R2(e, a, b, c, d, 36);
109
0
  R2(d, e, a, b, c, 37);
110
0
  R2(c, d, e, a, b, 38);
111
0
  R2(b, c, d, e, a, 39);
112
0
  R3(a, b, c, d, e, 40);
113
0
  R3(e, a, b, c, d, 41);
114
0
  R3(d, e, a, b, c, 42);
115
0
  R3(c, d, e, a, b, 43);
116
0
  R3(b, c, d, e, a, 44);
117
0
  R3(a, b, c, d, e, 45);
118
0
  R3(e, a, b, c, d, 46);
119
0
  R3(d, e, a, b, c, 47);
120
0
  R3(c, d, e, a, b, 48);
121
0
  R3(b, c, d, e, a, 49);
122
0
  R3(a, b, c, d, e, 50);
123
0
  R3(e, a, b, c, d, 51);
124
0
  R3(d, e, a, b, c, 52);
125
0
  R3(c, d, e, a, b, 53);
126
0
  R3(b, c, d, e, a, 54);
127
0
  R3(a, b, c, d, e, 55);
128
0
  R3(e, a, b, c, d, 56);
129
0
  R3(d, e, a, b, c, 57);
130
0
  R3(c, d, e, a, b, 58);
131
0
  R3(b, c, d, e, a, 59);
132
0
  R4(a, b, c, d, e, 60);
133
0
  R4(e, a, b, c, d, 61);
134
0
  R4(d, e, a, b, c, 62);
135
0
  R4(c, d, e, a, b, 63);
136
0
  R4(b, c, d, e, a, 64);
137
0
  R4(a, b, c, d, e, 65);
138
0
  R4(e, a, b, c, d, 66);
139
0
  R4(d, e, a, b, c, 67);
140
0
  R4(c, d, e, a, b, 68);
141
0
  R4(b, c, d, e, a, 69);
142
0
  R4(a, b, c, d, e, 70);
143
0
  R4(e, a, b, c, d, 71);
144
0
  R4(d, e, a, b, c, 72);
145
0
  R4(c, d, e, a, b, 73);
146
0
  R4(b, c, d, e, a, 74);
147
0
  R4(a, b, c, d, e, 75);
148
0
  R4(e, a, b, c, d, 76);
149
0
  R4(d, e, a, b, c, 77);
150
0
  R4(c, d, e, a, b, 78);
151
0
  R4(b, c, d, e, a, 79);
152
  /* Add the working vars back into context.state[] */
153
0
  state[0] += a;
154
0
  state[1] += b;
155
0
  state[2] += c;
156
0
  state[3] += d;
157
0
  state[4] += e;
158
  /* Wipe variables */
159
0
#ifdef HAVE_EXPLICIT_BZERO
160
0
  explicit_bzero(&a, sizeof(a));
161
0
  explicit_bzero(&b, sizeof(b));
162
0
  explicit_bzero(&c, sizeof(c));
163
0
  explicit_bzero(&d, sizeof(d));
164
0
  explicit_bzero(&e, sizeof(e));
165
#else
166
  a = b = c = d = e = 0;
167
#endif
168
0
#ifdef UL_SHA1HANDSOFF
169
0
  memset(block, '\0', sizeof(block));
170
0
#endif
171
0
}
172
173
/* SHA1Init - Initialize new context */
174
175
void ul_SHA1Init(UL_SHA1_CTX *context)
176
0
{
177
  /* SHA1 initialization constants */
178
0
  context->state[0] = 0x67452301;
179
0
  context->state[1] = 0xEFCDAB89;
180
0
  context->state[2] = 0x98BADCFE;
181
0
  context->state[3] = 0x10325476;
182
0
  context->state[4] = 0xC3D2E1F0;
183
0
  context->count[0] = context->count[1] = 0;
184
0
}
185
186
/* Run your data through this. */
187
188
void ul_SHA1Update(UL_SHA1_CTX *context, const unsigned char *data, uint32_t len)
189
0
{
190
0
  uint32_t i;
191
192
0
  uint32_t j;
193
194
0
  j = context->count[0];
195
0
  if ((context->count[0] += len << 3) < j)
196
0
    context->count[1]++;
197
0
  context->count[1] += (len >> 29);
198
0
  j = (j >> 3) & 63;
199
0
  if ((j + len) > 63) {
200
0
    memcpy(&context->buffer[j], data, (i = 64 - j));
201
0
    ul_SHA1Transform(context->state, context->buffer);
202
0
    for (; i + 63 < len; i += 64) {
203
0
      ul_SHA1Transform(context->state, &data[i]);
204
0
    }
205
0
    j = 0;
206
0
  } else
207
0
    i = 0;
208
0
  memcpy(&context->buffer[j], &data[i], len - i);
209
0
}
210
211
/* Add padding and return the message digest. */
212
213
void ul_SHA1Final(unsigned char digest[20], UL_SHA1_CTX *context)
214
0
{
215
0
  unsigned i;
216
217
0
  unsigned char finalcount[8];
218
219
0
  unsigned char c;
220
221
#if 0       /* untested "improvement" by DHR */
222
  /* Convert context->count to a sequence of bytes
223
   * in finalcount.  Second element first, but
224
   * big-endian order within element.
225
   * But we do it all backwards.
226
   */
227
  unsigned char *fcp = &finalcount[8];
228
229
  for (i = 0; i < 2; i++) {
230
    uint32_t t = context->count[i];
231
232
    int j;
233
234
    for (j = 0; j < 4; t >>= 8, j++)
235
      *--fcp = (unsigned char)t}
236
#else
237
0
  for (i = 0; i < 8; i++) {
238
0
    finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255);  /* Endian independent */
239
0
  }
240
0
#endif
241
0
  c = 0200;
242
0
  ul_SHA1Update(context, &c, 1);
243
0
  while ((context->count[0] & 504) != 448) {
244
0
    c = 0000;
245
0
    ul_SHA1Update(context, &c, 1);
246
0
  }
247
0
  ul_SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
248
0
  for (i = 0; i < 20; i++) {
249
0
    digest[i] = (unsigned char)
250
0
        ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
251
0
  }
252
  /* Wipe variables */
253
0
  memset(context, '\0', sizeof(*context));
254
0
  memset(&finalcount, '\0', sizeof(finalcount));
255
0
}
256
257
void ul_SHA1(char *hash_out, const char *str, unsigned len)
258
0
{
259
0
  UL_SHA1_CTX ctx;
260
0
  unsigned int ii;
261
262
0
  ul_SHA1Init(&ctx);
263
0
  for (ii = 0; ii < len; ii += 1)
264
0
    ul_SHA1Update(&ctx, (const unsigned char *)str + ii, 1);
265
0
  ul_SHA1Final((unsigned char *)hash_out, &ctx);
266
0
  hash_out[20] = '\0';
267
0
}