Mercurial > pidgin.yaz
comparison libpurple/protocols/gg/lib/sha1.c @ 29938:6359fde67f4c
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
Refs #10542. The Windows build errors are the only reason this isn't on
`im.pidgin.pidgin` already.
author | John Bailey <rekkanoryo@rekkanoryo.org> |
---|---|
date | Sun, 21 Feb 2010 16:52:42 +0000 |
parents | |
children | a8cc50c2279f |
comparison
equal
deleted
inserted
replaced
29868:551253814063 | 29938:6359fde67f4c |
---|---|
1 /* $Id: sha1.c 632 2008-07-30 18:40:06Z darkjames $ */ | |
2 | |
3 /* | |
4 * (C) Copyright 2007 Wojtek Kaniewski <wojtekka@irc.pl> | |
5 * | |
6 * Public domain SHA-1 implementation by Steve Reid <steve@edmweb.com> | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU Lesser General Public License Version | |
10 * 2.1 as published by the Free Software Foundation. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, | |
20 * USA. | |
21 */ | |
22 | |
23 /** | |
24 * \file sha1.c | |
25 * | |
26 * \brief Funkcje wyznaczania skrĂłtu SHA1 | |
27 */ | |
28 | |
29 #include <string.h> | |
30 #include <sys/types.h> | |
31 #include <unistd.h> | |
32 | |
33 #include "libgadu.h" | |
34 | |
35 /** \cond ignore */ | |
36 | |
37 #ifdef GG_CONFIG_HAVE_OPENSSL | |
38 | |
39 #include <openssl/sha.h> | |
40 | |
41 #else | |
42 | |
43 /* | |
44 SHA-1 in C | |
45 By Steve Reid <steve@edmweb.com> | |
46 100% Public Domain | |
47 | |
48 Modified by Wojtek Kaniewski <wojtekka@toxygen.net> for compatibility | |
49 with libgadu and OpenSSL API. | |
50 | |
51 Test Vectors (from FIPS PUB 180-1) | |
52 "abc" | |
53 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D | |
54 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" | |
55 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 | |
56 A million repetitions of "a" | |
57 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F | |
58 */ | |
59 | |
60 /* #define LITTLE_ENDIAN * This should be #define'd if true. */ | |
61 /* #define SHA1HANDSOFF * Copies data before messing with it. */ | |
62 | |
63 #include <string.h> | |
64 | |
65 typedef struct { | |
66 uint32_t state[5]; | |
67 uint32_t count[2]; | |
68 unsigned char buffer[64]; | |
69 } SHA_CTX; | |
70 | |
71 static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64]); | |
72 static void SHA1_Init(SHA_CTX* context); | |
73 static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len); | |
74 static void SHA1_Final(unsigned char digest[20], SHA_CTX* context); | |
75 | |
76 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) | |
77 | |
78 /* blk0() and blk() perform the initial expand. */ | |
79 /* I got the idea of expanding during the round function from SSLeay */ | |
80 #ifndef GG_CONFIG_BIGENDIAN | |
81 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ | |
82 |(rol(block->l[i],8)&0x00FF00FF)) | |
83 #else | |
84 #define blk0(i) block->l[i] | |
85 #endif | |
86 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ | |
87 ^block->l[(i+2)&15]^block->l[i&15],1)) | |
88 | |
89 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ | |
90 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); | |
91 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); | |
92 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); | |
93 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); | |
94 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); | |
95 | |
96 | |
97 /* Hash a single 512-bit block. This is the core of the algorithm. */ | |
98 | |
99 static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64]) | |
100 { | |
101 uint32_t a, b, c, d, e; | |
102 typedef union { | |
103 unsigned char c[64]; | |
104 uint32_t l[16]; | |
105 } CHAR64LONG16; | |
106 CHAR64LONG16* block; | |
107 static unsigned char workspace[64]; | |
108 block = (CHAR64LONG16*)workspace; | |
109 memcpy(block, buffer, 64); | |
110 /* Copy context->state[] to working vars */ | |
111 a = state[0]; | |
112 b = state[1]; | |
113 c = state[2]; | |
114 d = state[3]; | |
115 e = state[4]; | |
116 /* 4 rounds of 20 operations each. Loop unrolled. */ | |
117 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); | |
118 R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); | |
119 R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); | |
120 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); | |
121 R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); | |
122 R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); | |
123 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); | |
124 R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); | |
125 R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); | |
126 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); | |
127 R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); | |
128 R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); | |
129 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); | |
130 R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); | |
131 R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); | |
132 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); | |
133 R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); | |
134 R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); | |
135 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); | |
136 R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); | |
137 /* Add the working vars back into context.state[] */ | |
138 state[0] += a; | |
139 state[1] += b; | |
140 state[2] += c; | |
141 state[3] += d; | |
142 state[4] += e; | |
143 /* Wipe variables */ | |
144 a = b = c = d = e = 0; | |
145 } | |
146 | |
147 | |
148 /* SHA1_Init - Initialize new context */ | |
149 | |
150 static void SHA1_Init(SHA_CTX* context) | |
151 { | |
152 /* SHA1 initialization constants */ | |
153 context->state[0] = 0x67452301; | |
154 context->state[1] = 0xEFCDAB89; | |
155 context->state[2] = 0x98BADCFE; | |
156 context->state[3] = 0x10325476; | |
157 context->state[4] = 0xC3D2E1F0; | |
158 context->count[0] = context->count[1] = 0; | |
159 } | |
160 | |
161 | |
162 /* Run your data through this. */ | |
163 | |
164 static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len) | |
165 { | |
166 unsigned int i, j; | |
167 | |
168 j = (context->count[0] >> 3) & 63; | |
169 if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; | |
170 context->count[1] += (len >> 29); | |
171 if ((j + len) > 63) { | |
172 memcpy(&context->buffer[j], data, (i = 64-j)); | |
173 SHA1_Transform(context->state, context->buffer); | |
174 for ( ; i + 63 < len; i += 64) { | |
175 SHA1_Transform(context->state, &data[i]); | |
176 } | |
177 j = 0; | |
178 } | |
179 else i = 0; | |
180 memcpy(&context->buffer[j], &data[i], len - i); | |
181 } | |
182 | |
183 | |
184 /* Add padding and return the message digest. */ | |
185 | |
186 static void SHA1_Final(unsigned char digest[20], SHA_CTX* context) | |
187 { | |
188 uint32_t i, j; | |
189 unsigned char finalcount[8]; | |
190 | |
191 for (i = 0; i < 8; i++) { | |
192 finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] | |
193 >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ | |
194 } | |
195 SHA1_Update(context, (unsigned char *)"\200", 1); | |
196 while ((context->count[0] & 504) != 448) { | |
197 SHA1_Update(context, (unsigned char *)"\0", 1); | |
198 } | |
199 SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ | |
200 for (i = 0; i < 20; i++) { | |
201 digest[i] = (unsigned char) | |
202 ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); | |
203 } | |
204 /* Wipe variables */ | |
205 i = j = 0; | |
206 memset(context->buffer, 0, 64); | |
207 memset(context->state, 0, 20); | |
208 memset(context->count, 0, 8); | |
209 memset(&finalcount, 0, 8); | |
210 #ifdef SHA1HANDSOFF /* make SHA1_Transform overwrite it's own static vars */ | |
211 SHA1_Transform(context->state, context->buffer); | |
212 #endif | |
213 } | |
214 | |
215 #endif /* GG_CONFIG_HAVE_OPENSSL */ | |
216 | |
217 /** \endcond */ | |
218 | |
219 /** \cond internal */ | |
220 | |
221 /** | |
222 * \internal Liczy skrĂłt SHA1 z ziarna i hasĹa. | |
223 * | |
224 * \param password HasĹo | |
225 * \param seed Ziarno | |
226 * \param result Bufor na wynik funkcji skrĂłtu (20 bajtĂłw) | |
227 */ | |
228 void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result) | |
229 { | |
230 SHA_CTX ctx; | |
231 | |
232 SHA1_Init(&ctx); | |
233 SHA1_Update(&ctx, (const unsigned char*) password, strlen(password)); | |
234 seed = gg_fix32(seed); | |
235 SHA1_Update(&ctx, (uint8_t*) &seed, 4); | |
236 | |
237 SHA1_Final(result, &ctx); | |
238 } | |
239 | |
240 /** | |
241 * \internal Liczy skrĂłt SHA1 z pliku. | |
242 * | |
243 * \param fd Deskryptor pliku | |
244 * \param result WskaĹşnik na skrĂłt | |
245 * | |
246 * \return 0 lub -1 | |
247 */ | |
248 int gg_file_hash_sha1(int fd, uint8_t *result) | |
249 { | |
250 unsigned char buf[4096]; | |
251 SHA_CTX ctx; | |
252 off_t pos, len; | |
253 int res; | |
254 | |
255 if ((pos = lseek(fd, 0, SEEK_CUR)) == (off_t) -1) | |
256 return -1; | |
257 | |
258 if ((len = lseek(fd, 0, SEEK_END)) == (off_t) -1) | |
259 return -1; | |
260 | |
261 if (lseek(fd, 0, SEEK_SET) == (off_t) -1) | |
262 return -1; | |
263 | |
264 SHA1_Init(&ctx); | |
265 | |
266 if (len <= 10485760) { | |
267 while ((res = read(fd, buf, sizeof(buf))) > 0) | |
268 SHA1_Update(&ctx, buf, res); | |
269 } else { | |
270 int i; | |
271 | |
272 for (i = 0; i < 9; i++) { | |
273 int j; | |
274 | |
275 if (lseek(fd, (len - 1048576) / 9 * i, SEEK_SET) == (off_t) - 1) | |
276 return -1; | |
277 | |
278 for (j = 0; j < 1048576 / sizeof(buf); j++) { | |
279 if ((res = read(fd, buf, sizeof(buf))) != sizeof(buf)) { | |
280 res = -1; | |
281 break; | |
282 } | |
283 | |
284 SHA1_Update(&ctx, buf, res); | |
285 } | |
286 | |
287 if (res == -1) | |
288 break; | |
289 } | |
290 } | |
291 | |
292 if (res == -1) | |
293 return -1; | |
294 | |
295 SHA1_Final(result, &ctx); | |
296 | |
297 if (lseek(fd, pos, SEEK_SET) == (off_t) -1) | |
298 return -1; | |
299 | |
300 return 0; | |
301 } | |
302 | |
303 /** \endcond */ |