1 /* iksemel (XML parser for Jabber)
2 ** Copyright (C) 2000-2003 Gurer Ozen
3 ** This code is free software; you can redistribute it and/or
4 ** modify it under the terms of GNU Lesser General Public License.
5 */
6 
7 #include "common.h"
8 #include "iksemel.h"
9 
10 static void sha_buffer (iksha *sha, const unsigned char *data, int len);
11 static void sha_calculate (iksha *sha);
12 
13 struct iksha_struct {
14 	unsigned int hash[5];
15 	unsigned int buf[80];
16 	int blen;
17 	unsigned int lenhi, lenlo;
18 };
19 
20 iksha *
iks_sha_new(void)21 iks_sha_new (void)
22 {
23 	iksha *sha;
24 
25 	sha = iks_malloc (sizeof (iksha));
26 	if (!sha) return NULL;
27 	iks_sha_reset (sha);
28 	return sha;
29 }
30 
31 void
iks_sha_reset(iksha * sha)32 iks_sha_reset (iksha *sha)
33 {
34 	memset (sha, 0, sizeof (iksha));
35 	sha->hash[0] = 0x67452301;
36 	sha->hash[1] = 0xefcdab89;
37 	sha->hash[2] = 0x98badcfe;
38 	sha->hash[3] = 0x10325476;
39 	sha->hash[4] = 0xc3d2e1f0;
40 }
41 
42 void
iks_sha_hash(iksha * sha,const unsigned char * data,size_t len,int finish)43 iks_sha_hash (iksha *sha, const unsigned char *data, size_t len, int finish)
44 {
45 	unsigned char pad[8];
46 	unsigned char padc;
47 
48 	if (data && len != 0) sha_buffer (sha, data, len);
49 	if (!finish) return;
50 
51 	pad[0] = (unsigned char)((sha->lenhi >> 24) & 0xff);
52 	pad[1] = (unsigned char)((sha->lenhi >> 16) & 0xff);
53 	pad[2] = (unsigned char)((sha->lenhi >> 8) & 0xff);
54 	pad[3] = (unsigned char)(sha->lenhi & 0xff);
55 	pad[4] = (unsigned char)((sha->lenlo >> 24) & 0xff);
56 	pad[5] = (unsigned char)((sha->lenlo >> 16) & 0xff);
57 	pad[6] = (unsigned char)((sha->lenlo >> 8) & 0xff);
58 	pad[7] = (unsigned char)(sha->lenlo & 255);
59 
60 	padc = 0x80;
61 	sha_buffer (sha, &padc, 1);
62 
63 	padc = 0x00;
64 	while (sha->blen != 56)
65 		sha_buffer (sha, &padc, 1);
66 
67 	sha_buffer (sha, pad, 8);
68 }
69 
70 void
iks_sha_print(iksha * sha,char * hash)71 iks_sha_print (iksha *sha, char *hash)
72 {
73 	int i;
74 
75 	for (i=0; i<5; i++)
76 	{
77 		sprintf (hash, "%08x", sha->hash[i]);
78 		hash += 8;
79 	}
80 }
81 
82 void
iks_sha_delete(iksha * sha)83 iks_sha_delete (iksha *sha)
84 {
85 	iks_free (sha);
86 }
87 
88 void
iks_sha(const char * data,char * hash)89 iks_sha (const char *data, char *hash)
90 {
91 	iksha *sha;
92 
93 	sha = iks_sha_new ();
94 	iks_sha_hash (sha, (const unsigned char*)data, strlen (data), 1);
95 	iks_sha_print (sha, hash);
96 	iks_free (sha);
97 }
98 
99 static void
sha_buffer(iksha * sha,const unsigned char * data,int len)100 sha_buffer (iksha *sha, const unsigned char *data, int len)
101 {
102 	int i;
103 
104 	for (i=0; i<len; i++) {
105 		sha->buf[sha->blen / 4] <<= 8;
106 		sha->buf[sha->blen / 4] |= (unsigned int)data[i];
107 		if ((++sha->blen) % 64 == 0) {
108 			sha_calculate (sha);
109 			sha->blen = 0;
110 		}
111 		sha->lenlo += 8;
112 		sha->lenhi += (sha->lenlo < 8);
113 	}
114 }
115 
116 #define SRL(x,y) (((x) << (y)) | ((x) >> (32-(y))))
117 #define SHA(a,b,f,c) \
118 	for (i= (a) ; i<= (b) ; i++) { \
119 		TMP = SRL(A,5) + ( (f) ) + E + sha->buf[i] + (c) ; \
120 		E = D; \
121 		D = C; \
122 		C = SRL(B,30); \
123 		B = A; \
124 		A = TMP; \
125 	}
126 
127 static void
sha_calculate(iksha * sha)128 sha_calculate (iksha *sha)
129 {
130 	int i;
131 	unsigned int A, B, C, D, E, TMP;
132 
133 	for (i=16; i<80; i++)
134 		sha->buf[i] = SRL (sha->buf[i-3] ^ sha->buf[i-8] ^ sha->buf[i-14] ^ sha->buf[i-16], 1);
135 
136 	A = sha->hash[0];
137 	B = sha->hash[1];
138 	C = sha->hash[2];
139 	D = sha->hash[3];
140 	E = sha->hash[4];
141 
142 	SHA (0,  19, ((C^D)&B)^D,     0x5a827999);
143 	SHA (20, 39, B^C^D,           0x6ed9eba1);
144 	SHA (40, 59, (B&C)|(D&(B|C)), 0x8f1bbcdc);
145 	SHA (60, 79, B^C^D,           0xca62c1d6);
146 
147 	sha->hash[0] += A;
148 	sha->hash[1] += B;
149 	sha->hash[2] += C;
150 	sha->hash[3] += D;
151 	sha->hash[4] += E;
152 }
153