]> mj.ucw.cz Git - maildups.git/blob - sha1.c
Teach mparse to handle maildirs
[maildups.git] / sha1.c
1 /*
2  * SHA1 Secure Hash Algorithm.
3  *
4  * Derived by Martin Mares from Linux Kernel implementation, which is:
5  *
6  * Copyright (c) Alan Smithee.
7  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
8  * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the Free
12  * Software Foundation; either version 2 of the License, or (at your option)
13  * any later version.
14  *
15  * SHA transform algorithm originally taken from code written by
16  * Peter Gutmann, and placed in the public domain.
17  */
18
19 #include <stdint.h>
20 #include <string.h>
21
22 #include "util.h"
23
24 static inline u32 rol32(u32 x, uns bits)
25 {
26         return (x << bits) | (x >> (32 - bits));
27 }
28
29 #define SHA_WORKSPACE_WORDS 80
30
31 /* The SHA f()-functions.  */
32
33 #define f1(x,y,z)   (z ^ (x & (y ^ z)))         /* x ? y : z */
34 #define f2(x,y,z)   (x ^ y ^ z)                 /* XOR */
35 #define f3(x,y,z)   ((x & y) + (z & (x ^ y)))   /* majority */
36
37 /* The SHA Mysterious Constants */
38
39 #define K1  0x5A827999L                 /* Rounds  0-19: sqrt(2) * 2^30 */
40 #define K2  0x6ED9EBA1L                 /* Rounds 20-39: sqrt(3) * 2^30 */
41 #define K3  0x8F1BBCDCL                 /* Rounds 40-59: sqrt(5) * 2^30 */
42 #define K4  0xCA62C1D6L                 /* Rounds 60-79: sqrt(10) * 2^30 */
43
44 /*
45  * sha_transform: single block SHA1 transform
46  *
47  * @digest: 160 bit digest to update
48  * @data:   512 bits of data to hash
49  * @W:      80 words of workspace (see note)
50  *
51  * This function generates a SHA1 digest for a single 512-bit block.
52  * Be warned, it does not handle padding and message digest, do not
53  * confuse it with the full FIPS 180-1 digest algorithm for variable
54  * length messages.
55  *
56  * Note: If the hash is security sensitive, the caller should be sure
57  * to clear the workspace. This is left to the caller to avoid
58  * unnecessary clears between chained hashing operations.
59  */
60 static void sha_transform(u32 *digest, const u8 *in, u32 *W)
61 {
62         u32 a, b, c, d, e, t, i;
63
64         for (i = 0; i < 16; i++)
65                 W[i] = (in[4*i] << 24) | (in[4*i+1] << 16) | (in[4*i+2] << 8) | in[4*i+3];
66
67         for (i = 0; i < 64; i++)
68                 W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
69
70         a = digest[0];
71         b = digest[1];
72         c = digest[2];
73         d = digest[3];
74         e = digest[4];
75
76         for (i = 0; i < 20; i++) {
77                 t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
78                 e = d; d = c; c = rol32(b, 30); b = a; a = t;
79         }
80
81         for (; i < 40; i ++) {
82                 t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
83                 e = d; d = c; c = rol32(b, 30); b = a; a = t;
84         }
85
86         for (; i < 60; i ++) {
87                 t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
88                 e = d; d = c; c = rol32(b, 30); b = a; a = t;
89         }
90
91         for (; i < 80; i ++) {
92                 t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
93                 e = d; d = c; c = rol32(b, 30); b = a; a = t;
94         }
95
96         digest[0] += a;
97         digest[1] += b;
98         digest[2] += c;
99         digest[3] += d;
100         digest[4] += e;
101 }
102
103 void sha1_init(struct sha1_ctx *sctx)
104 {
105         static const struct sha1_ctx initstate = {
106           0,
107           { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
108           { 0, }
109         };
110
111         *sctx = initstate;
112 }
113
114 void sha1_update(struct sha1_ctx *sctx, const u8 *data, unsigned int len)
115 {
116         unsigned int i, j;
117         u32 temp[SHA_WORKSPACE_WORDS];
118
119         j = (sctx->count >> 3) & 0x3f;
120         sctx->count += len << 3;
121
122         if ((j + len) > 63) {
123                 memcpy(&sctx->buffer[j], data, (i = 64-j));
124                 sha_transform(sctx->state, sctx->buffer, temp);
125                 for ( ; i + 63 < len; i += 64) {
126                         sha_transform(sctx->state, &data[i], temp);
127                 }
128                 j = 0;
129         }
130         else i = 0;
131         memcpy(&sctx->buffer[j], &data[i], len - i);
132 }
133
134
135 /* Add padding and return the message digest. */
136 void sha1_final(struct sha1_ctx *sctx, u8 *out)
137 {
138         u32 i, j, index, padlen;
139         u64 t;
140         u8 bits[8] = { 0, };
141         static const u8 padding[64] = { 0x80, };
142
143         t = sctx->count;
144         bits[7] = 0xff & t; t>>=8;
145         bits[6] = 0xff & t; t>>=8;
146         bits[5] = 0xff & t; t>>=8;
147         bits[4] = 0xff & t; t>>=8;
148         bits[3] = 0xff & t; t>>=8;
149         bits[2] = 0xff & t; t>>=8;
150         bits[1] = 0xff & t; t>>=8;
151         bits[0] = 0xff & t;
152
153         /* Pad out to 56 mod 64 */
154         index = (sctx->count >> 3) & 0x3f;
155         padlen = (index < 56) ? (56 - index) : ((64+56) - index);
156         sha1_update(sctx, padding, padlen);
157
158         /* Append length */
159         sha1_update(sctx, bits, sizeof bits); 
160
161         /* Store state in digest */
162         for (i = j = 0; i < 5; i++, j += 4) {
163                 u32 t2 = sctx->state[i];
164                 out[j+3] = t2 & 0xff; t2>>=8;
165                 out[j+2] = t2 & 0xff; t2>>=8;
166                 out[j+1] = t2 & 0xff; t2>>=8;
167                 out[j  ] = t2 & 0xff;
168         }
169 }