Made link flags variable depending on selected protocols, eliminated some
[centerim.git] / libyahoo2 / sha.c
blobd87de38822d9eddc3c5197a0f37d6abfd2cf61fd
1 /*-
2 * Copyright (c) 2001-2003 Allan Saddi <allan@saddi.com>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
26 * $Id: sha.c,v 1.4 2004/12/21 14:13:27 konst Exp $
30 * Define WORDS_BIGENDIAN if compiling on a big-endian architecture.
32 * Define SHA1_TEST to test the implementation using the NIST's
33 * sample messages. The output should be:
35 * a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d
36 * 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1
37 * 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif /* HAVE_CONFIG_H */
44 #if HAVE_INTTYPES_H
45 # include <inttypes.h>
46 #else
47 # if HAVE_STDINT_H
48 # include <stdint.h>
49 # endif
50 #endif
52 #include <string.h>
54 #include "sha.h"
56 #ifndef lint
57 static const char rcsid[] =
58 "$Id: sha.c,v 1.4 2004/12/21 14:13:27 konst Exp $";
59 #endif /* !lint */
61 #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
62 #define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
64 #define F_0_19(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
65 #define F_20_39(x, y, z) ((x) ^ (y) ^ (z))
66 #define F_40_59(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
67 #define F_60_79(x, y, z) ((x) ^ (y) ^ (z))
69 #define DO_ROUND(F, K) { \
70 temp = ROTL(a, 5) + F(b, c, d) + e + *(W++) + K; \
71 e = d; \
72 d = c; \
73 c = ROTL(b, 30); \
74 b = a; \
75 a = temp; \
78 #define K_0_19 0x5a827999L
79 #define K_20_39 0x6ed9eba1L
80 #define K_40_59 0x8f1bbcdcL
81 #define K_60_79 0xca62c1d6L
83 #ifndef RUNTIME_ENDIAN
85 #ifdef WORDS_BIGENDIAN
87 #define BYTESWAP(x) (x)
88 #define BYTESWAP64(x) (x)
90 #else /* WORDS_BIGENDIAN */
92 #define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | (ROTL((x), 8) & 0x00ff00ffL))
94 static unsigned long long _byteswap64(unsigned long long x)
96 unsigned int a = x >> 32;
97 unsigned int b = (unsigned int) x;
98 return ((unsigned long long) BYTESWAP(b) << 32) | (unsigned long long) BYTESWAP(a);
101 #define BYTESWAP64(x) _byteswap64(x)
105 #endif /* WORDS_BIGENDIAN */
107 #else /* !RUNTIME_ENDIAN */
109 #define BYTESWAP(x) _byteswap(sc->littleEndian, x)
110 #define BYTESWAP64(x) _byteswap64(sc->littleEndian, x)
112 #define _BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00L) | \
113 (ROTL((x), 8) & 0x00ff00ffL))
114 #define _BYTESWAP64(x) __byteswap64(x)
116 static unsigned long long __byteswap64(unsigned long long x)
118 unsigned int a = x >> 32;
119 unsigned int b = (unsigned int) x;
120 return ((unsigned long long) _BYTESWAP(b) << 32) | (unsigned long long) _BYTESWAP(a);
123 static unsigned int _byteswap(int littleEndian, unsigned int x)
125 if (!littleEndian)
126 return x;
127 else
128 return _BYTESWAP(x);
131 static unsigned long long _byteswap64(int littleEndian, unsigned long long x)
133 if (!littleEndian)
134 return x;
135 else
136 return _BYTESWAP64(x);
139 static void setEndian(int *littleEndianp)
141 union {
142 unsigned int w;
143 unsigned char b[4];
144 } endian;
146 endian.w = 1L;
147 *littleEndianp = endian.b[0] != 0;
150 #endif /* !RUNTIME_ENDIAN */
152 static const unsigned char padding[64] = {
153 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
163 void
164 SHA1Init (SHA1Context *sc)
166 #ifdef RUNTIME_ENDIAN
167 setEndian (&sc->littleEndian);
168 #endif /* RUNTIME_ENDIAN */
170 sc->totalLength = 0LL;
171 sc->hash[0] = 0x67452301L;
172 sc->hash[1] = 0xefcdab89L;
173 sc->hash[2] = 0x98badcfeL;
174 sc->hash[3] = 0x10325476L;
175 sc->hash[4] = 0xc3d2e1f0L;
176 sc->bufferLength = 0L;
179 static void
180 burnStack (int size)
182 char buf[128];
184 memset (buf, 0, sizeof (buf));
185 size -= sizeof (buf);
186 if (size > 0)
187 burnStack (size);
190 static void
191 SHA1Guts (SHA1Context *sc, const unsigned int *cbuf)
193 unsigned int buf[80];
194 unsigned int *W, *W3, *W8, *W14, *W16;
195 unsigned int a, b, c, d, e, temp;
196 int i;
198 W = buf;
200 for (i = 15; i >= 0; i--) {
201 *(W++) = BYTESWAP(*cbuf);
202 cbuf++;
205 W16 = &buf[0];
206 W14 = &buf[2];
207 W8 = &buf[8];
208 W3 = &buf[13];
210 for (i = 63; i >= 0; i--) {
211 *W = *(W3++) ^ *(W8++) ^ *(W14++) ^ *(W16++);
212 *W = ROTL(*W, 1);
213 W++;
216 a = sc->hash[0];
217 b = sc->hash[1];
218 c = sc->hash[2];
219 d = sc->hash[3];
220 e = sc->hash[4];
222 W = buf;
224 #ifndef SHA1_UNROLL
225 #define SHA1_UNROLL 20
226 #endif /* !SHA1_UNROLL */
228 #if SHA1_UNROLL == 1
229 for (i = 19; i >= 0; i--)
230 DO_ROUND(F_0_19, K_0_19);
232 for (i = 19; i >= 0; i--)
233 DO_ROUND(F_20_39, K_20_39);
235 for (i = 19; i >= 0; i--)
236 DO_ROUND(F_40_59, K_40_59);
238 for (i = 19; i >= 0; i--)
239 DO_ROUND(F_60_79, K_60_79);
240 #elif SHA1_UNROLL == 2
241 for (i = 9; i >= 0; i--) {
242 DO_ROUND(F_0_19, K_0_19);
243 DO_ROUND(F_0_19, K_0_19);
246 for (i = 9; i >= 0; i--) {
247 DO_ROUND(F_20_39, K_20_39);
248 DO_ROUND(F_20_39, K_20_39);
251 for (i = 9; i >= 0; i--) {
252 DO_ROUND(F_40_59, K_40_59);
253 DO_ROUND(F_40_59, K_40_59);
256 for (i = 9; i >= 0; i--) {
257 DO_ROUND(F_60_79, K_60_79);
258 DO_ROUND(F_60_79, K_60_79);
260 #elif SHA1_UNROLL == 4
261 for (i = 4; i >= 0; i--) {
262 DO_ROUND(F_0_19, K_0_19);
263 DO_ROUND(F_0_19, K_0_19);
264 DO_ROUND(F_0_19, K_0_19);
265 DO_ROUND(F_0_19, K_0_19);
268 for (i = 4; i >= 0; i--) {
269 DO_ROUND(F_20_39, K_20_39);
270 DO_ROUND(F_20_39, K_20_39);
271 DO_ROUND(F_20_39, K_20_39);
272 DO_ROUND(F_20_39, K_20_39);
275 for (i = 4; i >= 0; i--) {
276 DO_ROUND(F_40_59, K_40_59);
277 DO_ROUND(F_40_59, K_40_59);
278 DO_ROUND(F_40_59, K_40_59);
279 DO_ROUND(F_40_59, K_40_59);
282 for (i = 4; i >= 0; i--) {
283 DO_ROUND(F_60_79, K_60_79);
284 DO_ROUND(F_60_79, K_60_79);
285 DO_ROUND(F_60_79, K_60_79);
286 DO_ROUND(F_60_79, K_60_79);
288 #elif SHA1_UNROLL == 5
289 for (i = 3; i >= 0; i--) {
290 DO_ROUND(F_0_19, K_0_19);
291 DO_ROUND(F_0_19, K_0_19);
292 DO_ROUND(F_0_19, K_0_19);
293 DO_ROUND(F_0_19, K_0_19);
294 DO_ROUND(F_0_19, K_0_19);
297 for (i = 3; i >= 0; i--) {
298 DO_ROUND(F_20_39, K_20_39);
299 DO_ROUND(F_20_39, K_20_39);
300 DO_ROUND(F_20_39, K_20_39);
301 DO_ROUND(F_20_39, K_20_39);
302 DO_ROUND(F_20_39, K_20_39);
305 for (i = 3; i >= 0; i--) {
306 DO_ROUND(F_40_59, K_40_59);
307 DO_ROUND(F_40_59, K_40_59);
308 DO_ROUND(F_40_59, K_40_59);
309 DO_ROUND(F_40_59, K_40_59);
310 DO_ROUND(F_40_59, K_40_59);
313 for (i = 3; i >= 0; i--) {
314 DO_ROUND(F_60_79, K_60_79);
315 DO_ROUND(F_60_79, K_60_79);
316 DO_ROUND(F_60_79, K_60_79);
317 DO_ROUND(F_60_79, K_60_79);
318 DO_ROUND(F_60_79, K_60_79);
320 #elif SHA1_UNROLL == 10
321 for (i = 1; i >= 0; i--) {
322 DO_ROUND(F_0_19, K_0_19);
323 DO_ROUND(F_0_19, K_0_19);
324 DO_ROUND(F_0_19, K_0_19);
325 DO_ROUND(F_0_19, K_0_19);
326 DO_ROUND(F_0_19, K_0_19);
327 DO_ROUND(F_0_19, K_0_19);
328 DO_ROUND(F_0_19, K_0_19);
329 DO_ROUND(F_0_19, K_0_19);
330 DO_ROUND(F_0_19, K_0_19);
331 DO_ROUND(F_0_19, K_0_19);
334 for (i = 1; i >= 0; i--) {
335 DO_ROUND(F_20_39, K_20_39);
336 DO_ROUND(F_20_39, K_20_39);
337 DO_ROUND(F_20_39, K_20_39);
338 DO_ROUND(F_20_39, K_20_39);
339 DO_ROUND(F_20_39, K_20_39);
340 DO_ROUND(F_20_39, K_20_39);
341 DO_ROUND(F_20_39, K_20_39);
342 DO_ROUND(F_20_39, K_20_39);
343 DO_ROUND(F_20_39, K_20_39);
344 DO_ROUND(F_20_39, K_20_39);
347 for (i = 1; i >= 0; i--) {
348 DO_ROUND(F_40_59, K_40_59);
349 DO_ROUND(F_40_59, K_40_59);
350 DO_ROUND(F_40_59, K_40_59);
351 DO_ROUND(F_40_59, K_40_59);
352 DO_ROUND(F_40_59, K_40_59);
353 DO_ROUND(F_40_59, K_40_59);
354 DO_ROUND(F_40_59, K_40_59);
355 DO_ROUND(F_40_59, K_40_59);
356 DO_ROUND(F_40_59, K_40_59);
357 DO_ROUND(F_40_59, K_40_59);
360 for (i = 1; i >= 0; i--) {
361 DO_ROUND(F_60_79, K_60_79);
362 DO_ROUND(F_60_79, K_60_79);
363 DO_ROUND(F_60_79, K_60_79);
364 DO_ROUND(F_60_79, K_60_79);
365 DO_ROUND(F_60_79, K_60_79);
366 DO_ROUND(F_60_79, K_60_79);
367 DO_ROUND(F_60_79, K_60_79);
368 DO_ROUND(F_60_79, K_60_79);
369 DO_ROUND(F_60_79, K_60_79);
370 DO_ROUND(F_60_79, K_60_79);
372 #elif SHA1_UNROLL == 20
373 DO_ROUND(F_0_19, K_0_19);
374 DO_ROUND(F_0_19, K_0_19);
375 DO_ROUND(F_0_19, K_0_19);
376 DO_ROUND(F_0_19, K_0_19);
377 DO_ROUND(F_0_19, K_0_19);
378 DO_ROUND(F_0_19, K_0_19);
379 DO_ROUND(F_0_19, K_0_19);
380 DO_ROUND(F_0_19, K_0_19);
381 DO_ROUND(F_0_19, K_0_19);
382 DO_ROUND(F_0_19, K_0_19);
383 DO_ROUND(F_0_19, K_0_19);
384 DO_ROUND(F_0_19, K_0_19);
385 DO_ROUND(F_0_19, K_0_19);
386 DO_ROUND(F_0_19, K_0_19);
387 DO_ROUND(F_0_19, K_0_19);
388 DO_ROUND(F_0_19, K_0_19);
389 DO_ROUND(F_0_19, K_0_19);
390 DO_ROUND(F_0_19, K_0_19);
391 DO_ROUND(F_0_19, K_0_19);
392 DO_ROUND(F_0_19, K_0_19);
394 DO_ROUND(F_20_39, K_20_39);
395 DO_ROUND(F_20_39, K_20_39);
396 DO_ROUND(F_20_39, K_20_39);
397 DO_ROUND(F_20_39, K_20_39);
398 DO_ROUND(F_20_39, K_20_39);
399 DO_ROUND(F_20_39, K_20_39);
400 DO_ROUND(F_20_39, K_20_39);
401 DO_ROUND(F_20_39, K_20_39);
402 DO_ROUND(F_20_39, K_20_39);
403 DO_ROUND(F_20_39, K_20_39);
404 DO_ROUND(F_20_39, K_20_39);
405 DO_ROUND(F_20_39, K_20_39);
406 DO_ROUND(F_20_39, K_20_39);
407 DO_ROUND(F_20_39, K_20_39);
408 DO_ROUND(F_20_39, K_20_39);
409 DO_ROUND(F_20_39, K_20_39);
410 DO_ROUND(F_20_39, K_20_39);
411 DO_ROUND(F_20_39, K_20_39);
412 DO_ROUND(F_20_39, K_20_39);
413 DO_ROUND(F_20_39, K_20_39);
415 DO_ROUND(F_40_59, K_40_59);
416 DO_ROUND(F_40_59, K_40_59);
417 DO_ROUND(F_40_59, K_40_59);
418 DO_ROUND(F_40_59, K_40_59);
419 DO_ROUND(F_40_59, K_40_59);
420 DO_ROUND(F_40_59, K_40_59);
421 DO_ROUND(F_40_59, K_40_59);
422 DO_ROUND(F_40_59, K_40_59);
423 DO_ROUND(F_40_59, K_40_59);
424 DO_ROUND(F_40_59, K_40_59);
425 DO_ROUND(F_40_59, K_40_59);
426 DO_ROUND(F_40_59, K_40_59);
427 DO_ROUND(F_40_59, K_40_59);
428 DO_ROUND(F_40_59, K_40_59);
429 DO_ROUND(F_40_59, K_40_59);
430 DO_ROUND(F_40_59, K_40_59);
431 DO_ROUND(F_40_59, K_40_59);
432 DO_ROUND(F_40_59, K_40_59);
433 DO_ROUND(F_40_59, K_40_59);
434 DO_ROUND(F_40_59, K_40_59);
436 DO_ROUND(F_60_79, K_60_79);
437 DO_ROUND(F_60_79, K_60_79);
438 DO_ROUND(F_60_79, K_60_79);
439 DO_ROUND(F_60_79, K_60_79);
440 DO_ROUND(F_60_79, K_60_79);
441 DO_ROUND(F_60_79, K_60_79);
442 DO_ROUND(F_60_79, K_60_79);
443 DO_ROUND(F_60_79, K_60_79);
444 DO_ROUND(F_60_79, K_60_79);
445 DO_ROUND(F_60_79, K_60_79);
446 DO_ROUND(F_60_79, K_60_79);
447 DO_ROUND(F_60_79, K_60_79);
448 DO_ROUND(F_60_79, K_60_79);
449 DO_ROUND(F_60_79, K_60_79);
450 DO_ROUND(F_60_79, K_60_79);
451 DO_ROUND(F_60_79, K_60_79);
452 DO_ROUND(F_60_79, K_60_79);
453 DO_ROUND(F_60_79, K_60_79);
454 DO_ROUND(F_60_79, K_60_79);
455 DO_ROUND(F_60_79, K_60_79);
456 #else /* SHA1_UNROLL */
457 #error SHA1_UNROLL must be 1, 2, 4, 5, 10 or 20!
458 #endif
460 sc->hash[0] += a;
461 sc->hash[1] += b;
462 sc->hash[2] += c;
463 sc->hash[3] += d;
464 sc->hash[4] += e;
467 void
468 SHA1Update (SHA1Context *sc, const void *vdata, unsigned int len)
470 const unsigned char *data = vdata;
471 unsigned int bufferBytesLeft;
472 unsigned int bytesToCopy;
473 int needBurn = 0;
475 #ifdef SHA1_FAST_COPY
476 if (sc->bufferLength) {
477 bufferBytesLeft = 64L - sc->bufferLength;
479 bytesToCopy = bufferBytesLeft;
480 if (bytesToCopy > len)
481 bytesToCopy = len;
483 memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
485 sc->totalLength += bytesToCopy * 8L;
487 sc->bufferLength += bytesToCopy;
488 data += bytesToCopy;
489 len -= bytesToCopy;
491 if (sc->bufferLength == 64L) {
492 SHA1Guts (sc, sc->buffer.words);
493 needBurn = 1;
494 sc->bufferLength = 0L;
498 while (len > 63) {
499 sc->totalLength += 512L;
501 SHA1Guts (sc, data);
502 needBurn = 1;
504 data += 64L;
505 len -= 64L;
508 if (len) {
509 memcpy (&sc->buffer.bytes[sc->bufferLength], data, len);
511 sc->totalLength += len * 8L;
513 sc->bufferLength += len;
515 #else /* SHA1_FAST_COPY */
516 while (len) {
517 bufferBytesLeft = 64L - sc->bufferLength;
519 bytesToCopy = bufferBytesLeft;
520 if (bytesToCopy > len)
521 bytesToCopy = len;
523 memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
525 sc->totalLength += bytesToCopy * 8L;
527 sc->bufferLength += bytesToCopy;
528 data += bytesToCopy;
529 len -= bytesToCopy;
531 if (sc->bufferLength == 64L) {
532 SHA1Guts (sc, sc->buffer.words);
533 needBurn = 1;
534 sc->bufferLength = 0L;
537 #endif /* SHA1_FAST_COPY */
539 if (needBurn)
540 burnStack (sizeof (unsigned int[86]) + sizeof (unsigned int *[5]) + sizeof (int));
543 void
544 SHA1Final (SHA1Context *sc, unsigned char hash[SHA1_HASH_SIZE])
546 unsigned int bytesToPad;
547 unsigned long long lengthPad;
548 int i;
550 bytesToPad = 120L - sc->bufferLength;
551 if (bytesToPad > 64L)
552 bytesToPad -= 64L;
554 lengthPad = BYTESWAP64(sc->totalLength);
556 SHA1Update (sc, padding, bytesToPad);
557 SHA1Update (sc, &lengthPad, 8L);
559 if (hash) {
560 for (i = 0; i < SHA1_HASH_WORDS; i++) {
561 #ifdef SHA1_FAST_COPY
562 *((unsigned int *) hash) = BYTESWAP(sc->hash[i]);
563 #else /* SHA1_FAST_COPY */
564 hash[0] = (unsigned char) (sc->hash[i] >> 24);
565 hash[1] = (unsigned char) (sc->hash[i] >> 16);
566 hash[2] = (unsigned char) (sc->hash[i] >> 8);
567 hash[3] = (unsigned char) sc->hash[i];
568 #endif /* SHA1_FAST_COPY */
569 hash += 4;
574 #ifdef SHA1_TEST
576 #include <stdio.h>
577 #include <stdlib.h>
578 #include <string.h>
581 main (int argc, char *argv[])
583 SHA1Context foo;
584 unsigned char hash[SHA1_HASH_SIZE];
585 char buf[1000];
586 int i;
588 SHA1Init (&foo);
589 SHA1Update (&foo, "abc", 3);
590 SHA1Final (&foo, hash);
592 for (i = 0; i < SHA1_HASH_SIZE;) {
593 printf ("%02x", hash[i++]);
594 if (!(i % 4))
595 printf (" ");
597 printf ("\n");
599 SHA1Init (&foo);
600 SHA1Update (&foo,
601 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
602 56);
603 SHA1Final (&foo, hash);
605 for (i = 0; i < SHA1_HASH_SIZE;) {
606 printf ("%02x", hash[i++]);
607 if (!(i % 4))
608 printf (" ");
610 printf ("\n");
612 SHA1Init (&foo);
613 memset (buf, 'a', sizeof (buf));
614 for (i = 0; i < 1000; i++)
615 SHA1Update (&foo, buf, sizeof (buf));
616 SHA1Final (&foo, hash);
618 for (i = 0; i < SHA1_HASH_SIZE;) {
619 printf ("%02x", hash[i++]);
620 if (!(i % 4))
621 printf (" ");
623 printf ("\n");
625 exit (0);
628 #endif /* SHA1_TEST */