Mercurial > pidgin
annotate libpurple/ciphers/sha1.c @ 32785:f911cdafdcd8
changelog WHO fix
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Thu, 03 May 2012 13:14:51 +0000 |
parents | ca94413ccd0e |
children |
rev | line source |
---|---|
31215 | 1 /* |
2 * purple | |
3 * | |
4 * Purple is the legal property of its developers, whose names are too numerous | |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA | |
21 */ | |
22 #include <cipher.h> | |
31225
4418c97490ed
rc4.c and sha1.c needs to include libpurple/util.h as well
Gary Kramlich <grim@reaperworld.com>
parents:
31221
diff
changeset
|
23 #include <util.h> |
31215 | 24 |
31221
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
25 #if !GLIB_CHECK_VERSION(2,16,0) |
31215 | 26 |
27 #define SHA1_HMAC_BLOCK_SIZE 64 | |
28 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) | |
29 | |
30 struct SHA1Context { | |
31 guint32 H[5]; | |
32 guint32 W[80]; | |
33 | |
34 gint lenW; | |
35 | |
36 guint32 sizeHi; | |
37 guint32 sizeLo; | |
38 }; | |
39 | |
31221
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
40 static size_t |
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
41 sha1_get_block_size(PurpleCipherContext *context) |
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
42 { |
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
43 /* This does not change (in this case) */ |
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
44 return SHA1_HMAC_BLOCK_SIZE; |
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
45 } |
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
46 |
31215 | 47 static void |
48 sha1_hash_block(struct SHA1Context *sha1_ctx) { | |
49 gint i; | |
50 guint32 A, B, C, D, E, T; | |
51 | |
52 for(i = 16; i < 80; i++) { | |
53 sha1_ctx->W[i] = SHA1_ROTL(sha1_ctx->W[i - 3] ^ | |
54 sha1_ctx->W[i - 8] ^ | |
55 sha1_ctx->W[i - 14] ^ | |
56 sha1_ctx->W[i - 16], 1); | |
57 } | |
58 | |
59 A = sha1_ctx->H[0]; | |
60 B = sha1_ctx->H[1]; | |
61 C = sha1_ctx->H[2]; | |
62 D = sha1_ctx->H[3]; | |
63 E = sha1_ctx->H[4]; | |
64 | |
65 for(i = 0; i < 20; i++) { | |
66 T = (SHA1_ROTL(A, 5) + (((C ^ D) & B) ^ D) + E + sha1_ctx->W[i] + 0x5A827999) & 0xFFFFFFFF; | |
67 E = D; | |
68 D = C; | |
69 C = SHA1_ROTL(B, 30); | |
70 B = A; | |
71 A = T; | |
72 } | |
73 | |
74 for(i = 20; i < 40; i++) { | |
75 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0x6ED9EBA1) & 0xFFFFFFFF; | |
76 E = D; | |
77 D = C; | |
78 C = SHA1_ROTL(B, 30); | |
79 B = A; | |
80 A = T; | |
81 } | |
82 | |
83 for(i = 40; i < 60; i++) { | |
31257
4ef9165ebe45
Fix compilation on glib < 2.16. Somehow a trailing semicolon got lost.
Mark Doliner <mark@kingant.net>
parents:
31225
diff
changeset
|
84 T = (SHA1_ROTL(A, 5) + ((B & C) | (D & (B | C))) + E + sha1_ctx->W[i] + 0x8F1BBCDC) & 0xFFFFFFFF; |
4ef9165ebe45
Fix compilation on glib < 2.16. Somehow a trailing semicolon got lost.
Mark Doliner <mark@kingant.net>
parents:
31225
diff
changeset
|
85 E = D; |
31215 | 86 D = C; |
87 C = SHA1_ROTL(B, 30); | |
88 B = A; | |
89 A = T; | |
90 } | |
91 | |
92 for(i = 60; i < 80; i++) { | |
93 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0xCA62C1D6) & 0xFFFFFFFF; | |
94 E = D; | |
95 D = C; | |
96 C = SHA1_ROTL(B, 30); | |
97 B = A; | |
98 A = T; | |
99 } | |
100 | |
101 sha1_ctx->H[0] += A; | |
102 sha1_ctx->H[1] += B; | |
103 sha1_ctx->H[2] += C; | |
104 sha1_ctx->H[3] += D; | |
105 sha1_ctx->H[4] += E; | |
106 } | |
107 | |
108 static void | |
109 sha1_set_opt(PurpleCipherContext *context, const gchar *name, void *value) { | |
110 struct SHA1Context *ctx; | |
111 | |
112 ctx = purple_cipher_context_get_data(context); | |
113 | |
114 if(purple_strequal(name, "sizeHi")) { | |
115 ctx->sizeHi = GPOINTER_TO_INT(value); | |
116 } else if(purple_strequal(name, "sizeLo")) { | |
117 ctx->sizeLo = GPOINTER_TO_INT(value); | |
118 } else if(purple_strequal(name, "lenW")) { | |
119 ctx->lenW = GPOINTER_TO_INT(value); | |
120 } | |
121 } | |
122 | |
123 static void * | |
124 sha1_get_opt(PurpleCipherContext *context, const gchar *name) { | |
125 struct SHA1Context *ctx; | |
126 | |
127 ctx = purple_cipher_context_get_data(context); | |
128 | |
129 if(purple_strequal(name, "sizeHi")) { | |
130 return GINT_TO_POINTER(ctx->sizeHi); | |
131 } else if(purple_strequal(name, "sizeLo")) { | |
132 return GINT_TO_POINTER(ctx->sizeLo); | |
133 } else if(purple_strequal(name, "lenW")) { | |
134 return GINT_TO_POINTER(ctx->lenW); | |
135 } | |
136 | |
137 return NULL; | |
138 } | |
139 | |
140 static void | |
141 sha1_init(PurpleCipherContext *context, void *extra) { | |
142 struct SHA1Context *sha1_ctx; | |
143 | |
144 sha1_ctx = g_new0(struct SHA1Context, 1); | |
145 | |
146 purple_cipher_context_set_data(context, sha1_ctx); | |
147 | |
148 purple_cipher_context_reset(context, extra); | |
149 } | |
150 | |
151 static void | |
152 sha1_reset(PurpleCipherContext *context, void *extra) { | |
153 struct SHA1Context *sha1_ctx; | |
154 gint i; | |
155 | |
156 sha1_ctx = purple_cipher_context_get_data(context); | |
157 | |
158 g_return_if_fail(sha1_ctx); | |
159 | |
160 sha1_ctx->lenW = 0; | |
161 sha1_ctx->sizeHi = 0; | |
162 sha1_ctx->sizeLo = 0; | |
163 | |
164 sha1_ctx->H[0] = 0x67452301; | |
165 sha1_ctx->H[1] = 0xEFCDAB89; | |
166 sha1_ctx->H[2] = 0x98BADCFE; | |
167 sha1_ctx->H[3] = 0x10325476; | |
168 sha1_ctx->H[4] = 0xC3D2E1F0; | |
169 | |
170 for(i = 0; i < 80; i++) | |
171 sha1_ctx->W[i] = 0; | |
172 } | |
173 | |
174 static void | |
175 sha1_uninit(PurpleCipherContext *context) { | |
176 struct SHA1Context *sha1_ctx; | |
177 | |
178 purple_cipher_context_reset(context, NULL); | |
179 | |
180 sha1_ctx = purple_cipher_context_get_data(context); | |
181 | |
182 memset(sha1_ctx, 0, sizeof(struct SHA1Context)); | |
183 | |
184 g_free(sha1_ctx); | |
185 sha1_ctx = NULL; | |
186 } | |
187 | |
188 static void | |
189 sha1_append(PurpleCipherContext *context, const guchar *data, size_t len) { | |
190 struct SHA1Context *sha1_ctx; | |
191 gint i; | |
192 | |
193 sha1_ctx = purple_cipher_context_get_data(context); | |
194 | |
195 g_return_if_fail(sha1_ctx); | |
196 | |
197 for(i = 0; i < len; i++) { | |
198 sha1_ctx->W[sha1_ctx->lenW / 4] <<= 8; | |
199 sha1_ctx->W[sha1_ctx->lenW / 4] |= data[i]; | |
200 | |
201 if((++sha1_ctx->lenW) % 64 == 0) { | |
202 sha1_hash_block(sha1_ctx); | |
203 sha1_ctx->lenW = 0; | |
204 } | |
205 | |
206 sha1_ctx->sizeLo += 8; | |
207 sha1_ctx->sizeHi += (sha1_ctx->sizeLo < 8); | |
208 } | |
209 } | |
210 | |
211 static gboolean | |
212 sha1_digest(PurpleCipherContext *context, size_t in_len, guchar digest[20], | |
213 size_t *out_len) | |
214 { | |
215 struct SHA1Context *sha1_ctx; | |
216 guchar pad0x80 = 0x80, pad0x00 = 0x00; | |
217 guchar padlen[8]; | |
218 gint i; | |
219 | |
220 g_return_val_if_fail(in_len >= 20, FALSE); | |
221 | |
222 sha1_ctx = purple_cipher_context_get_data(context); | |
223 | |
224 g_return_val_if_fail(sha1_ctx, FALSE); | |
225 | |
226 padlen[0] = (guchar)((sha1_ctx->sizeHi >> 24) & 255); | |
227 padlen[1] = (guchar)((sha1_ctx->sizeHi >> 16) & 255); | |
228 padlen[2] = (guchar)((sha1_ctx->sizeHi >> 8) & 255); | |
229 padlen[3] = (guchar)((sha1_ctx->sizeHi >> 0) & 255); | |
230 padlen[4] = (guchar)((sha1_ctx->sizeLo >> 24) & 255); | |
231 padlen[5] = (guchar)((sha1_ctx->sizeLo >> 16) & 255); | |
232 padlen[6] = (guchar)((sha1_ctx->sizeLo >> 8) & 255); | |
233 padlen[7] = (guchar)((sha1_ctx->sizeLo >> 0) & 255); | |
234 | |
235 /* pad with a 1, then zeroes, then length */ | |
236 purple_cipher_context_append(context, &pad0x80, 1); | |
237 while(sha1_ctx->lenW != 56) | |
238 purple_cipher_context_append(context, &pad0x00, 1); | |
239 purple_cipher_context_append(context, padlen, 8); | |
240 | |
241 for(i = 0; i < 20; i++) { | |
242 digest[i] = (guchar)(sha1_ctx->H[i / 4] >> 24); | |
243 sha1_ctx->H[i / 4] <<= 8; | |
244 } | |
245 | |
246 purple_cipher_context_reset(context, NULL); | |
247 | |
248 if(out_len) | |
249 *out_len = 20; | |
250 | |
251 return TRUE; | |
252 } | |
253 | |
254 static PurpleCipherOps SHA1Ops = { | |
31353
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
255 sha1_set_opt, /* Set Option */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
256 sha1_get_opt, /* Get Option */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
257 sha1_init, /* init */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
258 sha1_reset, /* reset */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
259 sha1_uninit, /* uninit */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
260 NULL, /* set iv */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
261 sha1_append, /* append */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
262 sha1_digest, /* digest */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
263 NULL, /* encrypt */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
264 NULL, /* decrypt */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
265 NULL, /* set salt */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
266 NULL, /* get salt size */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
267 NULL, /* set key */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
268 NULL, /* get key size */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
269 NULL, /* set batch mode */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
270 NULL, /* get batch mode */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
271 sha1_get_block_size, /* get block size */ |
ca94413ccd0e
Named initializers and most other C99isms don't work in Visual C++ .NET 2005 in
Florian Quèze <florian@instantbird.org>
parents:
31257
diff
changeset
|
272 NULL /* set key with len */ |
31215 | 273 }; |
274 | |
275 PurpleCipherOps * | |
276 purple_sha1_cipher_get_ops(void) { | |
277 return &SHA1Ops; | |
278 } | |
279 | |
31221
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
280 #endif /* !GLIB_CHECK_VERSION(2,16,0) */ |
2b041e31b825
Removed the "new" api I added by moving it to ciphers/gchecksum.c. Moved the gchecksum implements into gchecksum.c as a preproc macro, removed them from their individual files
Gary Kramlich <grim@reaperworld.com>
parents:
31219
diff
changeset
|
281 |