File Coverage

ulib/sha1.c
Criterion Covered Total %
statement 136 145 93.7
branch 19 26 73.0
condition n/a
subroutine n/a
pod n/a
total 155 171 90.6


line stmt bran cond sub pod time code
1             #ifdef __cplusplus
2             extern "C" {
3             #endif
4              
5             #include "ulib/sha1.h"
6             #include "ulib/pack.h"
7             #include "ulib/parse.h"
8              
9             #ifdef __cplusplus
10             }
11             #endif
12              
13             /* borrowed from Digest::SHA1 */
14             /*----------------------------------------------------------------*/
15             /* NIST Secure Hash Algorithm */
16             /* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
17             /* from Peter C. Gutmann's implementation as found in */
18             /* Applied Cryptography by Bruce Schneier */
19             /* Further modifications to include the "UNRAVEL" stuff, below */
20              
21             /* This code is in the public domain */
22              
23             /* Useful defines & typedefs */
24              
25             #if defined(U64TYPE) && (defined(USE_64_BIT_INT) || ((BYTEORDER != 0x1234) && (BYTEORDER != 0x4321)))
26             typedef U64TYPE ULONGx;
27             # if BYTEORDER == 0x1234
28             # undef BYTEORDER
29             # define BYTEORDER 0x12345678
30             # elif BYTEORDER == 0x4321
31             # undef BYTEORDER
32             # define BYTEORDER 0x87654321
33             # endif
34             #else
35             typedef unsigned long ULONGx; /* 32-or-more-bit quantity */
36             #endif
37              
38             #define SHA_BLOCKSIZE 64
39             #define SHA_DIGESTSIZE 20
40              
41             typedef struct {
42             ULONGx digest[5]; /* message digest */
43             ULONGx count_lo, count_hi; /* 64-bit bit count */
44             U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */
45             int local; /* unprocessed amount in data */
46             } SHA_INFO;
47              
48              
49             /* UNRAVEL should be fastest & biggest */
50             /* UNROLL_LOOPS should be just as big, but slightly slower */
51             /* both undefined should be smallest and slowest */
52              
53             #define SHA_VERSION 1
54             #define UNRAVEL
55             /* #define UNROLL_LOOPS */
56             /* SHA f()-functions */
57             #define f1(x,y,z) ((x & y) | (~x & z))
58             #define f2(x,y,z) (x ^ y ^ z)
59             #define f3(x,y,z) ((x & y) | (x & z) | (y & z))
60             #define f4(x,y,z) (x ^ y ^ z)
61              
62             /* SHA constants */
63             #define CONST1 0x5a827999L
64             #define CONST2 0x6ed9eba1L
65             #define CONST3 0x8f1bbcdcL
66             #define CONST4 0xca62c1d6L
67              
68             /* truncate to 32 bits -- should be a null op on 32-bit machines */
69             #define T32(x) ((x) & 0xffffffffL)
70              
71             /* 32-bit rotate */
72             #define R32(x,n) T32(((x << n) | (x >> (32 - n))))
73              
74             /* the generic case, for when the overall rotation is not unraveled */
75             #define FG(n) \
76             T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \
77             E = D; D = C; C = R32(B,30); B = A; A = T
78              
79             /* specific cases, for when the overall rotation is unraveled */
80             #define FA(n) \
81             T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30)
82              
83             #define FB(n) \
84             E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30)
85              
86             #define FC(n) \
87             D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30)
88              
89             #define FD(n) \
90             C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30)
91              
92             #define FE(n) \
93             B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30)
94              
95             #define FT(n) \
96             A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30)
97              
98 146           static void sha_transform(SHA_INFO *sha_info)
99             {
100             int i;
101             U8 *dp;
102             ULONGx T, A, B, C, D, E, W[80], *WP;
103              
104 146           dp = sha_info->data;
105              
106             /*
107             the following makes sure that at least one code block below is
108             traversed or an error is reported, without the necessity for nested
109             preprocessor if/else/endif blocks, which are a great pain in the
110             nether regions of the anatomy...
111             */
112             #undef SWAP_DONE
113              
114             #if BYTEORDER == 0x1234
115             #define SWAP_DONE
116             /* assert(sizeof(ULONGx) == 4); */
117             for (i = 0; i < 16; ++i) {
118             T = *((ULONGx *) dp);
119             dp += 4;
120             W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
121             ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
122             }
123             #endif
124              
125             #if BYTEORDER == 0x4321
126             #define SWAP_DONE
127             /* assert(sizeof(ULONGx) == 4); */
128             for (i = 0; i < 16; ++i) {
129             T = *((ULONGx *) dp);
130             dp += 4;
131             W[i] = T32(T);
132             }
133             #endif
134              
135             #if BYTEORDER == 0x12345678
136             #define SWAP_DONE
137             /* assert(sizeof(ULONGx) == 8); */
138 1314 100         for (i = 0; i < 16; i += 2) {
139 1168           T = *((ULONGx *) dp);
140 1168           dp += 8;
141 1168           W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
142 1168           ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
143 1168           T >>= 32;
144 1168           W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) |
145 1168           ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff);
146             }
147             #endif
148              
149             #if BYTEORDER == 0x87654321
150             #define SWAP_DONE
151             /* assert(sizeof(ULONGx) == 8); */
152             for (i = 0; i < 16; i += 2) {
153             T = *((ULONGx *) dp);
154             dp += 8;
155             W[i] = T32(T >> 32);
156             W[i+1] = T32(T);
157             }
158             #endif
159              
160             #ifndef SWAP_DONE
161             #error Unknown byte order -- you need to add code here
162             #endif /* SWAP_DONE */
163              
164 9490 100         for (i = 16; i < 80; ++i) {
165 9344           W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
166             #if (SHA_VERSION == 1)
167 9344           W[i] = R32(W[i], 1);
168             #endif /* SHA_VERSION */
169             }
170 146           A = sha_info->digest[0];
171 146           B = sha_info->digest[1];
172 146           C = sha_info->digest[2];
173 146           D = sha_info->digest[3];
174 146           E = sha_info->digest[4];
175 146           WP = W;
176             #ifdef UNRAVEL
177 146           FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
178 146           FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
179 146           FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
180 146           FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
181 146           FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
182 146           FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
183 146           FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
184 146           FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
185 146           sha_info->digest[0] = T32(sha_info->digest[0] + E);
186 146           sha_info->digest[1] = T32(sha_info->digest[1] + T);
187 146           sha_info->digest[2] = T32(sha_info->digest[2] + A);
188 146           sha_info->digest[3] = T32(sha_info->digest[3] + B);
189 146           sha_info->digest[4] = T32(sha_info->digest[4] + C);
190             #else /* !UNRAVEL */
191             #ifdef UNROLL_LOOPS
192             FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
193             FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
194             FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
195             FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
196             FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
197             FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
198             FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
199             FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
200             #else /* !UNROLL_LOOPS */
201             for (i = 0; i < 20; ++i) { FG(1); }
202             for (i = 20; i < 40; ++i) { FG(2); }
203             for (i = 40; i < 60; ++i) { FG(3); }
204             for (i = 60; i < 80; ++i) { FG(4); }
205             #endif /* !UNROLL_LOOPS */
206             sha_info->digest[0] = T32(sha_info->digest[0] + A);
207             sha_info->digest[1] = T32(sha_info->digest[1] + B);
208             sha_info->digest[2] = T32(sha_info->digest[2] + C);
209             sha_info->digest[3] = T32(sha_info->digest[3] + D);
210             sha_info->digest[4] = T32(sha_info->digest[4] + E);
211             #endif /* !UNRAVEL */
212 146           }
213              
214             /* initialize the SHA digest */
215              
216 146           static void sha_init(SHA_INFO *sha_info)
217             {
218 146           sha_info->digest[0] = 0x67452301L;
219 146           sha_info->digest[1] = 0xefcdab89L;
220 146           sha_info->digest[2] = 0x98badcfeL;
221 146           sha_info->digest[3] = 0x10325476L;
222 146           sha_info->digest[4] = 0xc3d2e1f0L;
223 146           sha_info->count_lo = 0L;
224 146           sha_info->count_hi = 0L;
225 146           sha_info->local = 0;
226 146           }
227              
228             /* update the SHA digest */
229              
230 292           static void sha_update(SHA_INFO *sha_info, U8 *buffer, int count)
231             {
232             int i;
233             ULONGx clo;
234              
235 292           clo = T32(sha_info->count_lo + ((ULONGx) count << 3));
236 292 50         if (clo < sha_info->count_lo) {
237 0           ++sha_info->count_hi;
238             }
239 292           sha_info->count_lo = clo;
240 292           sha_info->count_hi += (ULONGx) count >> 29;
241 292 100         if (sha_info->local) {
242 146           i = SHA_BLOCKSIZE - sha_info->local;
243 146 50         if (i > count) {
244 146           i = count;
245             }
246 146           memcpy(((U8 *) sha_info->data) + sha_info->local, buffer, i);
247 146           count -= i;
248 146           buffer += i;
249 146           sha_info->local += i;
250 146 50         if (sha_info->local == SHA_BLOCKSIZE) {
251 0           sha_transform(sha_info);
252             } else {
253 146           return;
254             }
255             }
256 146 50         while (count >= SHA_BLOCKSIZE) {
257 0           memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
258 0           buffer += SHA_BLOCKSIZE;
259 0           count -= SHA_BLOCKSIZE;
260 0           sha_transform(sha_info);
261             }
262 146           memcpy(sha_info->data, buffer, count);
263 146           sha_info->local = count;
264             }
265              
266              
267 146           static void sha_transform_and_copy(unsigned char digest[20], SHA_INFO *sha_info)
268             {
269 146           sha_transform(sha_info);
270 146           digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
271 146           digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
272 146           digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
273 146           digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
274 146           digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
275 146           digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
276 146           digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
277 146           digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
278 146           digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
279 146           digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
280 146           digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
281 146           digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
282 146           digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
283 146           digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
284 146           digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
285 146           digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
286 146           digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
287 146           digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
288 146           digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
289 146           digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
290 146           }
291              
292             /* finish computing the SHA digest */
293 146           static void sha_final(unsigned char digest[20], SHA_INFO *sha_info)
294             {
295             int count;
296             ULONGx lo_bit_count, hi_bit_count;
297              
298 146           lo_bit_count = sha_info->count_lo;
299 146           hi_bit_count = sha_info->count_hi;
300 146           count = (int) ((lo_bit_count >> 3) & 0x3f);
301 146           ((U8 *) sha_info->data)[count++] = 0x80;
302 146 50         if (count > SHA_BLOCKSIZE - 8) {
303 0           memset(((U8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
304 0           sha_transform(sha_info);
305 0           memset((U8 *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
306             } else {
307 146           memset(((U8 *) sha_info->data) + count, 0,
308 146           SHA_BLOCKSIZE - 8 - count);
309             }
310 146           sha_info->data[56] = (U8)((hi_bit_count >> 24) & 0xff);
311 146           sha_info->data[57] = (U8)((hi_bit_count >> 16) & 0xff);
312 146           sha_info->data[58] = (U8)((hi_bit_count >> 8) & 0xff);
313 146           sha_info->data[59] = (U8)((hi_bit_count >> 0) & 0xff);
314 146           sha_info->data[60] = (U8)((lo_bit_count >> 24) & 0xff);
315 146           sha_info->data[61] = (U8)((lo_bit_count >> 16) & 0xff);
316 146           sha_info->data[62] = (U8)((lo_bit_count >> 8) & 0xff);
317 146           sha_info->data[63] = (U8)((lo_bit_count >> 0) & 0xff);
318 146           sha_transform_and_copy(digest, sha_info);
319 146           }
320             /*----------------------------------------------------------------*/
321              
322             static const char *hexdigits = "0123456789abcdef";
323              
324 146           static void hex_20(const unsigned char* from, char* to) {
325 146           const unsigned char *end = from + 20;
326 146           char *d = to;
327              
328 3066 100         while (from < end) {
329 2920           *d++ = hexdigits[(*from >> 4)];
330 2920           *d++ = hexdigits[(*from & 0x0F)];
331 2920           from++;
332             }
333 146           *d = '\0';
334 146           }
335              
336 146           void uu_sha_hash(pUCXT, struct_uu_t *io, char *name) {
337             /* io is assumed to be a v1 namespace uuid coming in. */
338             /* do hton*() here. */
339             /* name is... a name. */
340             SHA_INFO context;
341             struct_uu_t ns;
342             char tmp[41];
343             char vardig;
344             unsigned char digeststr[21];
345             uu_t packed;
346              
347 146           uu_pack1(io, (U8*)&packed);
348              
349 146           sha_init(&context);
350              
351 146           sha_update(&context, (U8*)&packed, sizeof(packed));
352 146 50         if (name)
353 146           sha_update(&context, (U8*)name, strlen(name));
354              
355 146           sha_final((U8*)&digeststr, &context);
356 146           digeststr[20] = '\0';
357              
358 146           hex_20(digeststr, tmp);
359 146           tmp[32] = '\0';
360              
361             /* hyphenate */
362 146           Move(&tmp[20], &tmp[21], 12, char); tmp[20] = '-';
363 146           Move(&tmp[16], &tmp[17], 17, char); tmp[16] = '-';
364 146           Move(&tmp[12], &tmp[13], 22, char); tmp[12] = '-';
365 146           Move(&tmp[ 8], &tmp[ 9], 27, char); tmp[ 8] = '-';
366 146           tmp[36] = '\0';
367              
368             /* version */
369 146           tmp[14] = '5';
370              
371             /* variant */
372 146           vardig = tmp[19] - 48;
373 146 100         if (vardig > 9) vardig -= 7;
374 146 100         if (vardig > 15) vardig -= 32;
375 146           vardig = vardig & 0x3 | 0x8;
376 146 50         if (vardig > 9) vardig += 87;
377 146           else vardig += 48;
378 146           tmp[19] = vardig;
379              
380 146           uu_parse(tmp, io);
381 146           }
382              
383             /* ex:set ts=2 sw=2 itab=spaces: */