Mercurial > pidgin
annotate libpurple/ciphers/sha1.c @ 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
author | Gary Kramlich <grim@reaperworld.com> |
---|---|
date | Thu, 17 Feb 2011 00:42:53 +0000 |
parents | 2d3c1197f930 |
children | 4418c97490ed |
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> | |
23 | |
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
|
24 #if !GLIB_CHECK_VERSION(2,16,0) |
31215 | 25 |
26 #define SHA1_HMAC_BLOCK_SIZE 64 | |
27 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) | |
28 | |
29 struct SHA1Context { | |
30 guint32 H[5]; | |
31 guint32 W[80]; | |
32 | |
33 gint lenW; | |
34 | |
35 guint32 sizeHi; | |
36 guint32 sizeLo; | |
37 }; | |
38 | |
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
|
39 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
|
40 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
|
41 { |
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 /* 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
|
43 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
|
44 } |
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 |
31215 | 46 static void |
47 sha1_hash_block(struct SHA1Context *sha1_ctx) { | |
48 gint i; | |
49 guint32 A, B, C, D, E, T; | |
50 | |
51 for(i = 16; i < 80; i++) { | |
52 sha1_ctx->W[i] = SHA1_ROTL(sha1_ctx->W[i - 3] ^ | |
53 sha1_ctx->W[i - 8] ^ | |
54 sha1_ctx->W[i - 14] ^ | |
55 sha1_ctx->W[i - 16], 1); | |
56 } | |
57 | |
58 A = sha1_ctx->H[0]; | |
59 B = sha1_ctx->H[1]; | |
60 C = sha1_ctx->H[2]; | |
61 D = sha1_ctx->H[3]; | |
62 E = sha1_ctx->H[4]; | |
63 | |
64 for(i = 0; i < 20; i++) { | |
65 T = (SHA1_ROTL(A, 5) + (((C ^ D) & B) ^ D) + E + sha1_ctx->W[i] + 0x5A827999) & 0xFFFFFFFF; | |
66 E = D; | |
67 D = C; | |
68 C = SHA1_ROTL(B, 30); | |
69 B = A; | |
70 A = T; | |
71 } | |
72 | |
73 for(i = 20; i < 40; i++) { | |
74 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0x6ED9EBA1) & 0xFFFFFFFF; | |
75 E = D; | |
76 D = C; | |
77 C = SHA1_ROTL(B, 30); | |
78 B = A; | |
79 A = T; | |
80 } | |
81 | |
82 for(i = 40; i < 60; i++) { | |
83 T = (SHA1_ROTL(A, 5) + ((B & C) | (D & (B | C))) + E + sha1_ctx->W[i] + 0x8F1BBCDC) & 0xFFFFFFFF | |
84 E = D; | |
85 D = C; | |
86 C = SHA1_ROTL(B, 30); | |
87 B = A; | |
88 A = T; | |
89 } | |
90 | |
91 for(i = 60; i < 80; i++) { | |
92 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0xCA62C1D6) & 0xFFFFFFFF; | |
93 E = D; | |
94 D = C; | |
95 C = SHA1_ROTL(B, 30); | |
96 B = A; | |
97 A = T; | |
98 } | |
99 | |
100 sha1_ctx->H[0] += A; | |
101 sha1_ctx->H[1] += B; | |
102 sha1_ctx->H[2] += C; | |
103 sha1_ctx->H[3] += D; | |
104 sha1_ctx->H[4] += E; | |
105 } | |
106 | |
107 static void | |
108 sha1_set_opt(PurpleCipherContext *context, const gchar *name, void *value) { | |
109 struct SHA1Context *ctx; | |
110 | |
111 ctx = purple_cipher_context_get_data(context); | |
112 | |
113 if(purple_strequal(name, "sizeHi")) { | |
114 ctx->sizeHi = GPOINTER_TO_INT(value); | |
115 } else if(purple_strequal(name, "sizeLo")) { | |
116 ctx->sizeLo = GPOINTER_TO_INT(value); | |
117 } else if(purple_strequal(name, "lenW")) { | |
118 ctx->lenW = GPOINTER_TO_INT(value); | |
119 } | |
120 } | |
121 | |
122 static void * | |
123 sha1_get_opt(PurpleCipherContext *context, const gchar *name) { | |
124 struct SHA1Context *ctx; | |
125 | |
126 ctx = purple_cipher_context_get_data(context); | |
127 | |
128 if(purple_strequal(name, "sizeHi")) { | |
129 return GINT_TO_POINTER(ctx->sizeHi); | |
130 } else if(purple_strequal(name, "sizeLo")) { | |
131 return GINT_TO_POINTER(ctx->sizeLo); | |
132 } else if(purple_strequal(name, "lenW")) { | |
133 return GINT_TO_POINTER(ctx->lenW); | |
134 } | |
135 | |
136 return NULL; | |
137 } | |
138 | |
139 static void | |
140 sha1_init(PurpleCipherContext *context, void *extra) { | |
141 struct SHA1Context *sha1_ctx; | |
142 | |
143 sha1_ctx = g_new0(struct SHA1Context, 1); | |
144 | |
145 purple_cipher_context_set_data(context, sha1_ctx); | |
146 | |
147 purple_cipher_context_reset(context, extra); | |
148 } | |
149 | |
150 static void | |
151 sha1_reset(PurpleCipherContext *context, void *extra) { | |
152 struct SHA1Context *sha1_ctx; | |
153 gint i; | |
154 | |
155 sha1_ctx = purple_cipher_context_get_data(context); | |
156 | |
157 g_return_if_fail(sha1_ctx); | |
158 | |
159 sha1_ctx->lenW = 0; | |
160 sha1_ctx->sizeHi = 0; | |
161 sha1_ctx->sizeLo = 0; | |
162 | |
163 sha1_ctx->H[0] = 0x67452301; | |
164 sha1_ctx->H[1] = 0xEFCDAB89; | |
165 sha1_ctx->H[2] = 0x98BADCFE; | |
166 sha1_ctx->H[3] = 0x10325476; | |
167 sha1_ctx->H[4] = 0xC3D2E1F0; | |
168 | |
169 for(i = 0; i < 80; i++) | |
170 sha1_ctx->W[i] = 0; | |
171 } | |
172 | |
173 static void | |
174 sha1_uninit(PurpleCipherContext *context) { | |
175 struct SHA1Context *sha1_ctx; | |
176 | |
177 purple_cipher_context_reset(context, NULL); | |
178 | |
179 sha1_ctx = purple_cipher_context_get_data(context); | |
180 | |
181 memset(sha1_ctx, 0, sizeof(struct SHA1Context)); | |
182 | |
183 g_free(sha1_ctx); | |
184 sha1_ctx = NULL; | |
185 } | |
186 | |
187 static void | |
188 sha1_append(PurpleCipherContext *context, const guchar *data, size_t len) { | |
189 struct SHA1Context *sha1_ctx; | |
190 gint i; | |
191 | |
192 sha1_ctx = purple_cipher_context_get_data(context); | |
193 | |
194 g_return_if_fail(sha1_ctx); | |
195 | |
196 for(i = 0; i < len; i++) { | |
197 sha1_ctx->W[sha1_ctx->lenW / 4] <<= 8; | |
198 sha1_ctx->W[sha1_ctx->lenW / 4] |= data[i]; | |
199 | |
200 if((++sha1_ctx->lenW) % 64 == 0) { | |
201 sha1_hash_block(sha1_ctx); | |
202 sha1_ctx->lenW = 0; | |
203 } | |
204 | |
205 sha1_ctx->sizeLo += 8; | |
206 sha1_ctx->sizeHi += (sha1_ctx->sizeLo < 8); | |
207 } | |
208 } | |
209 | |
210 static gboolean | |
211 sha1_digest(PurpleCipherContext *context, size_t in_len, guchar digest[20], | |
212 size_t *out_len) | |
213 { | |
214 struct SHA1Context *sha1_ctx; | |
215 guchar pad0x80 = 0x80, pad0x00 = 0x00; | |
216 guchar padlen[8]; | |
217 gint i; | |
218 | |
219 g_return_val_if_fail(in_len >= 20, FALSE); | |
220 | |
221 sha1_ctx = purple_cipher_context_get_data(context); | |
222 | |
223 g_return_val_if_fail(sha1_ctx, FALSE); | |
224 | |
225 padlen[0] = (guchar)((sha1_ctx->sizeHi >> 24) & 255); | |
226 padlen[1] = (guchar)((sha1_ctx->sizeHi >> 16) & 255); | |
227 padlen[2] = (guchar)((sha1_ctx->sizeHi >> 8) & 255); | |
228 padlen[3] = (guchar)((sha1_ctx->sizeHi >> 0) & 255); | |
229 padlen[4] = (guchar)((sha1_ctx->sizeLo >> 24) & 255); | |
230 padlen[5] = (guchar)((sha1_ctx->sizeLo >> 16) & 255); | |
231 padlen[6] = (guchar)((sha1_ctx->sizeLo >> 8) & 255); | |
232 padlen[7] = (guchar)((sha1_ctx->sizeLo >> 0) & 255); | |
233 | |
234 /* pad with a 1, then zeroes, then length */ | |
235 purple_cipher_context_append(context, &pad0x80, 1); | |
236 while(sha1_ctx->lenW != 56) | |
237 purple_cipher_context_append(context, &pad0x00, 1); | |
238 purple_cipher_context_append(context, padlen, 8); | |
239 | |
240 for(i = 0; i < 20; i++) { | |
241 digest[i] = (guchar)(sha1_ctx->H[i / 4] >> 24); | |
242 sha1_ctx->H[i / 4] <<= 8; | |
243 } | |
244 | |
245 purple_cipher_context_reset(context, NULL); | |
246 | |
247 if(out_len) | |
248 *out_len = 20; | |
249 | |
250 return TRUE; | |
251 } | |
252 | |
253 static PurpleCipherOps SHA1Ops = { | |
254 .set_option = sha1_set_opt, | |
255 .get_option = sha1_get_opt, | |
256 .init = sha1_init, | |
257 .reset = sha1_reset, | |
258 .uninit = sha1_uninit, | |
259 .append = sha1_append, | |
260 .digest = sha1_digest, | |
261 .get_block_size = sha1_get_block_size, | |
262 }; | |
263 | |
264 PurpleCipherOps * | |
265 purple_sha1_cipher_get_ops(void) { | |
266 return &SHA1Ops; | |
267 } | |
268 | |
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
|
269 #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
|
270 |