1/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10 */
11#include "tomcrypt.h"
12
13/**
14  @file sha1.c
15  SHA1 code by Tom St Denis
16*/
17
18
19#ifdef SHA1
20
21const struct ltc_hash_descriptor sha1_desc =
22{
23    "sha1",
24    2,
25    20,
26    64,
27
28    /* OID */
29   { 1, 3, 14, 3, 2, 26,  },
30   6,
31
32    &sha1_init,
33    &sha1_process,
34    &sha1_done,
35    &sha1_test,
36    NULL
37};
38
39#define F0(x,y,z)  (z ^ (x & (y ^ z)))
40#define F1(x,y,z)  (x ^ y ^ z)
41#define F2(x,y,z)  ((x & y) | (z & (x | y)))
42#define F3(x,y,z)  (x ^ y ^ z)
43
44#ifdef LTC_CLEAN_STACK
45static int _sha1_compress(hash_state *md, unsigned char *buf)
46#else
47static int  sha1_compress(hash_state *md, unsigned char *buf)
48#endif
49{
50    ulong32 a,b,c,d,e,W[80],i;
51#ifdef LTC_SMALL_CODE
52    ulong32 t;
53#endif
54
55    /* copy the state into 512-bits into W[0..15] */
56    for (i = 0; i < 16; i++) {
57        LOAD32H(W[i], buf + (4*i));
58    }
59
60    /* copy state */
61    a = md->sha1.state[0];
62    b = md->sha1.state[1];
63    c = md->sha1.state[2];
64    d = md->sha1.state[3];
65    e = md->sha1.state[4];
66
67    /* expand it */
68    for (i = 16; i < 80; i++) {
69        W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
70    }
71
72    /* compress */
73    /* round one */
74    #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
75    #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
76    #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
77    #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
78
79#ifdef LTC_SMALL_CODE
80
81    for (i = 0; i < 20; ) {
82       FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
83    }
84
85    for (; i < 40; ) {
86       FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
87    }
88
89    for (; i < 60; ) {
90       FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
91    }
92
93    for (; i < 80; ) {
94       FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
95    }
96
97#else
98
99    for (i = 0; i < 20; ) {
100       FF0(a,b,c,d,e,i++);
101       FF0(e,a,b,c,d,i++);
102       FF0(d,e,a,b,c,i++);
103       FF0(c,d,e,a,b,i++);
104       FF0(b,c,d,e,a,i++);
105    }
106
107    /* round two */
108    for (; i < 40; )  {
109       FF1(a,b,c,d,e,i++);
110       FF1(e,a,b,c,d,i++);
111       FF1(d,e,a,b,c,i++);
112       FF1(c,d,e,a,b,i++);
113       FF1(b,c,d,e,a,i++);
114    }
115
116    /* round three */
117    for (; i < 60; )  {
118       FF2(a,b,c,d,e,i++);
119       FF2(e,a,b,c,d,i++);
120       FF2(d,e,a,b,c,i++);
121       FF2(c,d,e,a,b,i++);
122       FF2(b,c,d,e,a,i++);
123    }
124
125    /* round four */
126    for (; i < 80; )  {
127       FF3(a,b,c,d,e,i++);
128       FF3(e,a,b,c,d,i++);
129       FF3(d,e,a,b,c,i++);
130       FF3(c,d,e,a,b,i++);
131       FF3(b,c,d,e,a,i++);
132    }
133#endif
134
135    #undef FF0
136    #undef FF1
137    #undef FF2
138    #undef FF3
139
140    /* store */
141    md->sha1.state[0] = md->sha1.state[0] + a;
142    md->sha1.state[1] = md->sha1.state[1] + b;
143    md->sha1.state[2] = md->sha1.state[2] + c;
144    md->sha1.state[3] = md->sha1.state[3] + d;
145    md->sha1.state[4] = md->sha1.state[4] + e;
146
147    return CRYPT_OK;
148}
149
150#ifdef LTC_CLEAN_STACK
151static int sha1_compress(hash_state *md, unsigned char *buf)
152{
153   int err;
154   err = _sha1_compress(md, buf);
155   burn_stack(sizeof(ulong32) * 87);
156   return err;
157}
158#endif
159
160/**
161   Initialize the hash state
162   @param md   The hash state you wish to initialize
163   @return CRYPT_OK if successful
164*/
165int sha1_init(hash_state * md)
166{
167   LTC_ARGCHK(md != NULL);
168   md->sha1.state[0] = 0x67452301UL;
169   md->sha1.state[1] = 0xefcdab89UL;
170   md->sha1.state[2] = 0x98badcfeUL;
171   md->sha1.state[3] = 0x10325476UL;
172   md->sha1.state[4] = 0xc3d2e1f0UL;
173   md->sha1.curlen = 0;
174   md->sha1.length = 0;
175   return CRYPT_OK;
176}
177
178/**
179   Process a block of memory though the hash
180   @param md     The hash state
181   @param in     The data to hash
182   @param inlen  The length of the data (octets)
183   @return CRYPT_OK if successful
184*/
185HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
186
187/**
188   Terminate the hash to get the digest
189   @param md  The hash state
190   @param out [out] The destination of the hash (20 bytes)
191   @return CRYPT_OK if successful
192*/
193int sha1_done(hash_state * md, unsigned char *out)
194{
195    int i;
196
197    LTC_ARGCHK(md  != NULL);
198    LTC_ARGCHK(out != NULL);
199
200    if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
201       return CRYPT_INVALID_ARG;
202    }
203
204    /* increase the length of the message */
205    md->sha1.length += md->sha1.curlen * 8;
206
207    /* append the '1' bit */
208    md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
209
210    /* if the length is currently above 56 bytes we append zeros
211     * then compress.  Then we can fall back to padding zeros and length
212     * encoding like normal.
213     */
214    if (md->sha1.curlen > 56) {
215        while (md->sha1.curlen < 64) {
216            md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
217        }
218        sha1_compress(md, md->sha1.buf);
219        md->sha1.curlen = 0;
220    }
221
222    /* pad upto 56 bytes of zeroes */
223    while (md->sha1.curlen < 56) {
224        md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
225    }
226
227    /* store length */
228    STORE64H(md->sha1.length, md->sha1.buf+56);
229    sha1_compress(md, md->sha1.buf);
230
231    /* copy output */
232    for (i = 0; i < 5; i++) {
233        STORE32H(md->sha1.state[i], out+(4*i));
234    }
235#ifdef LTC_CLEAN_STACK
236    zeromem(md, sizeof(hash_state));
237#endif
238    return CRYPT_OK;
239}
240
241/**
242  Self-test the hash
243  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
244*/
245int  sha1_test(void)
246{
247 #ifndef LTC_TEST
248    return CRYPT_NOP;
249 #else
250  static const struct {
251      char *msg;
252      unsigned char hash[20];
253  } tests[] = {
254    { "abc",
255      { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
256        0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
257        0x9c, 0xd0, 0xd8, 0x9d }
258    },
259    { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
260      { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
261        0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
262        0xE5, 0x46, 0x70, 0xF1 }
263    }
264  };
265
266  int i;
267  unsigned char tmp[20];
268  hash_state md;
269
270  for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0]));  i++) {
271      sha1_init(&md);
272      sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
273      sha1_done(&md, tmp);
274      if (XMEMCMP(tmp, tests[i].hash, 20) != 0) {
275         return CRYPT_FAIL_TESTVECTOR;
276      }
277  }
278  return CRYPT_OK;
279  #endif
280}
281
282#endif
283
284
285
286/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */
287/* $Revision: 1.8 $ */
288/* $Date: 2006/11/01 09:28:17 $ */
289