comparison src/hashes/sha1.c @ 192:9cc34777b479 libtomcrypt

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