Mercurial > pidgin
annotate src/cipher.c @ 11261:b53606580f68
[gaim-migrate @ 13439]
Patch #1226486 from Levi Bard
Fixes bug #1224178
If you change the topic in a chat room and that topic change is rejected, the
topic field is wrong -- it shows the new topic even thought it didn't get set.
This patch resets the GUI's topic immediately when you hit enter. Then, if the
topic change is successful, the server will echo the topic change back to us
and we'll update the GUI to the new topic.
The only question is, does the server always echo the topic back to us? From the
core's point of view, I'm ready to assume yes. It's the case for both IRC and
Jabber*. If someone could test changing a topic in SILC or Zephyr, that'd be
great. If servers using those protocols do not echo the topic back, the prpl
will have to fake it as appropriate.
* I didn't actually test on Jabber, but Nathan said the server will echo the
topic change back. If it's broken, let me know.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 14 Aug 2005 06:55:57 +0000 |
parents | 8dca96cbcd64 |
children | f93d434ee222 |
rev | line source |
---|---|
10684 | 1 /* |
2 * gaim | |
3 * | |
4 * Gaim 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 * Original md5 | |
9 * Copyright (C) 2001-2003 Christophe Devine <c.devine@cr0.net> | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 #include <glib.h> | |
26 #include <string.h> | |
27 #include <stdio.h> | |
28 | |
29 #include "internal.h" | |
30 #include "cipher.h" | |
31 #include "debug.h" | |
32 #include "signals.h" | |
33 #include "value.h" | |
34 | |
35 /******************************************************************************* | |
36 * MD5 | |
37 ******************************************************************************/ | |
38 struct MD5Context { | |
39 guint32 total[2]; | |
40 guint32 state[4]; | |
11183 | 41 guchar buffer[64]; |
10684 | 42 }; |
43 | |
44 #define MD5_GET_GUINT32(n,b,i) { \ | |
45 (n) = ((guint32)(b) [(i) ] ) \ | |
46 | ((guint32)(b) [(i) + 1] << 8) \ | |
47 | ((guint32)(b) [(i) + 2] << 16) \ | |
48 | ((guint32)(b) [(i) + 3] << 24); \ | |
49 } | |
11183 | 50 #define MD5_PUT_GUINT32(n,b,i) { \ |
51 (b)[(i) ] = (guchar)((n) ); \ | |
52 (b)[(i) + 1] = (guchar)((n) >> 8); \ | |
53 (b)[(i) + 2] = (guchar)((n) >> 16); \ | |
54 (b)[(i) + 3] = (guchar)((n) >> 24); \ | |
10684 | 55 } |
56 | |
57 static void | |
58 md5_init(GaimCipherContext *context, gpointer extra) { | |
59 struct MD5Context *md5_context; | |
60 | |
61 md5_context = g_new0(struct MD5Context, 1); | |
62 | |
63 gaim_cipher_context_set_data(context, md5_context); | |
64 | |
65 gaim_cipher_context_reset(context, extra); | |
66 } | |
67 | |
68 static void | |
69 md5_reset(GaimCipherContext *context, gpointer extra) { | |
70 struct MD5Context *md5_context; | |
71 | |
72 md5_context = gaim_cipher_context_get_data(context); | |
73 | |
74 md5_context->total[0] = 0; | |
75 md5_context->total[1] = 0; | |
76 | |
77 md5_context->state[0] = 0x67452301; | |
78 md5_context->state[1] = 0xEFCDAB89; | |
79 md5_context->state[2] = 0x98BADCFE; | |
80 md5_context->state[3] = 0x10325476; | |
81 | |
82 memset(md5_context->buffer, 0, sizeof(md5_context->buffer)); | |
83 } | |
84 | |
85 static void | |
86 md5_uninit(GaimCipherContext *context) { | |
87 struct MD5Context *md5_context; | |
88 | |
89 gaim_cipher_context_reset(context, NULL); | |
90 | |
91 md5_context = gaim_cipher_context_get_data(context); | |
92 memset(md5_context, 0, sizeof(md5_context)); | |
93 | |
94 g_free(md5_context); | |
95 md5_context = NULL; | |
96 } | |
97 | |
98 static void | |
11183 | 99 md5_process(struct MD5Context *md5_context, const guchar data[64]) { |
10684 | 100 guint32 X[16], A, B, C, D; |
101 | |
102 A = md5_context->state[0]; | |
103 B = md5_context->state[1]; | |
104 C = md5_context->state[2]; | |
105 D = md5_context->state[3]; | |
106 | |
107 MD5_GET_GUINT32(X[ 0], data, 0); | |
108 MD5_GET_GUINT32(X[ 1], data, 4); | |
109 MD5_GET_GUINT32(X[ 2], data, 8); | |
110 MD5_GET_GUINT32(X[ 3], data, 12); | |
111 MD5_GET_GUINT32(X[ 4], data, 16); | |
112 MD5_GET_GUINT32(X[ 5], data, 20); | |
113 MD5_GET_GUINT32(X[ 6], data, 24); | |
114 MD5_GET_GUINT32(X[ 7], data, 28); | |
115 MD5_GET_GUINT32(X[ 8], data, 32); | |
116 MD5_GET_GUINT32(X[ 9], data, 36); | |
117 MD5_GET_GUINT32(X[10], data, 40); | |
118 MD5_GET_GUINT32(X[11], data, 44); | |
119 MD5_GET_GUINT32(X[12], data, 48); | |
120 MD5_GET_GUINT32(X[13], data, 52); | |
121 MD5_GET_GUINT32(X[14], data, 56); | |
122 MD5_GET_GUINT32(X[15], data, 60); | |
123 | |
124 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) | |
125 #define P(a,b,c,d,k,s,t) { \ | |
126 a += F(b,c,d) + X[k] + t; \ | |
127 a = S(a,s) + b; \ | |
128 } | |
129 | |
130 /* first pass */ | |
131 #define F(x,y,z) (z ^ (x & (y ^ z))) | |
132 P(A, B, C, D, 0, 7, 0xD76AA478); | |
133 P(D, A, B, C, 1, 12, 0xE8C7B756); | |
134 P(C, D, A, B, 2, 17, 0x242070DB); | |
135 P(B, C, D, A, 3, 22, 0xC1BDCEEE); | |
136 P(A, B, C, D, 4, 7, 0xF57C0FAF); | |
137 P(D, A, B, C, 5, 12, 0x4787C62A); | |
138 P(C, D, A, B, 6, 17, 0xA8304613); | |
139 P(B, C, D, A, 7, 22, 0xFD469501); | |
140 P(A, B, C, D, 8, 7, 0x698098D8); | |
141 P(D, A, B, C, 9, 12, 0x8B44F7AF); | |
142 P(C, D, A, B, 10, 17, 0xFFFF5BB1); | |
143 P(B, C, D, A, 11, 22, 0x895CD7BE); | |
144 P(A, B, C, D, 12, 7, 0x6B901122); | |
145 P(D, A, B, C, 13, 12, 0xFD987193); | |
146 P(C, D, A, B, 14, 17, 0xA679438E); | |
147 P(B, C, D, A, 15, 22, 0x49B40821); | |
148 #undef F | |
149 | |
150 /* second pass */ | |
151 #define F(x,y,z) (y ^ (z & (x ^ y))) | |
152 P(A, B, C, D, 1, 5, 0xF61E2562); | |
153 P(D, A, B, C, 6, 9, 0xC040B340); | |
154 P(C, D, A, B, 11, 14, 0x265E5A51); | |
155 P(B, C, D, A, 0, 20, 0xE9B6C7AA); | |
156 P(A, B, C, D, 5, 5, 0xD62F105D); | |
157 P(D, A, B, C, 10, 9, 0x02441453); | |
158 P(C, D, A, B, 15, 14, 0xD8A1E681); | |
159 P(B, C, D, A, 4, 20, 0xE7D3FBC8); | |
160 P(A, B, C, D, 9, 5, 0x21E1CDE6); | |
161 P(D, A, B, C, 14, 9, 0xC33707D6); | |
162 P(C, D, A, B, 3, 14, 0xF4D50D87); | |
163 P(B, C, D, A, 8, 20, 0x455A14ED); | |
164 P(A, B, C, D, 13, 5, 0xA9E3E905); | |
165 P(D, A, B, C, 2, 9, 0xFCEFA3F8); | |
166 P(C, D, A, B, 7, 14, 0x676F02D9); | |
167 P(B, C, D, A, 12, 20, 0x8D2A4C8A); | |
168 #undef F | |
11183 | 169 |
10684 | 170 /* third pass */ |
171 #define F(x,y,z) (x ^ y ^ z) | |
172 P(A, B, C, D, 5, 4, 0xFFFA3942); | |
173 P(D, A, B, C, 8, 11, 0x8771F681); | |
174 P(C, D, A, B, 11, 16, 0x6D9D6122); | |
175 P(B, C, D, A, 14, 23, 0xFDE5380C); | |
176 P(A, B, C, D, 1, 4, 0xA4BEEA44); | |
177 P(D, A, B, C, 4, 11, 0x4BDECFA9); | |
178 P(C, D, A, B, 7, 16, 0xF6BB4B60); | |
179 P(B, C, D, A, 10, 23, 0xBEBFBC70); | |
180 P(A, B, C, D, 13, 4, 0x289B7EC6); | |
181 P(D, A, B, C, 0, 11, 0xEAA127FA); | |
182 P(C, D, A, B, 3, 16, 0xD4EF3085); | |
183 P(B, C, D, A, 6, 23, 0x04881D05); | |
184 P(A, B, C, D, 9, 4, 0xD9D4D039); | |
185 P(D, A, B, C, 12, 11, 0xE6DB99E5); | |
186 P(C, D, A, B, 15, 16, 0x1FA27CF8); | |
187 P(B, C, D, A, 2, 23, 0xC4AC5665); | |
188 #undef F | |
189 | |
190 /* forth pass */ | |
191 #define F(x,y,z) (y ^ (x | ~z)) | |
192 P(A, B, C, D, 0, 6, 0xF4292244); | |
193 P(D, A, B, C, 7, 10, 0x432AFF97); | |
194 P(C, D, A, B, 14, 15, 0xAB9423A7); | |
195 P(B, C, D, A, 5, 21, 0xFC93A039); | |
196 P(A, B, C, D, 12, 6, 0x655B59C3); | |
197 P(D, A, B, C, 3, 10, 0x8F0CCC92); | |
198 P(C, D, A, B, 10, 15, 0xFFEFF47D); | |
199 P(B, C, D, A, 1, 21, 0x85845DD1); | |
200 P(A, B, C, D, 8, 6, 0x6FA87E4F); | |
201 P(D, A, B, C, 15, 10, 0xFE2CE6E0); | |
202 P(C, D, A, B, 6, 15, 0xA3014314); | |
203 P(B, C, D, A, 13, 21, 0x4E0811A1); | |
204 P(A, B, C, D, 4, 6, 0xF7537E82); | |
205 P(D, A, B, C, 11, 10, 0xBD3AF235); | |
206 P(C, D, A, B, 2, 15, 0x2AD7D2BB); | |
207 P(B, C, D, A, 9, 21, 0xEB86D391); | |
208 #undef F | |
209 #undef P | |
210 #undef S | |
211 | |
212 md5_context->state[0] += A; | |
213 md5_context->state[1] += B; | |
214 md5_context->state[2] += C; | |
215 md5_context->state[3] += D; | |
216 } | |
217 | |
218 static void | |
11183 | 219 md5_append(GaimCipherContext *context, const guchar *data, size_t len) { |
10684 | 220 struct MD5Context *md5_context = NULL; |
221 guint32 left = 0, fill = 0; | |
222 | |
223 g_return_if_fail(context != NULL); | |
224 | |
225 md5_context = gaim_cipher_context_get_data(context); | |
226 g_return_if_fail(md5_context != NULL); | |
227 | |
228 left = md5_context->total[0] & 0x3F; | |
229 fill = 64 - left; | |
230 | |
231 md5_context->total[0] += len; | |
232 md5_context->total[0] &= 0xFFFFFFFF; | |
233 | |
234 if(md5_context->total[0] < len) | |
235 md5_context->total[1]++; | |
236 | |
237 if(left && len >= fill) { | |
238 memcpy((md5_context->buffer + left), data, fill); | |
239 md5_process(md5_context, md5_context->buffer); | |
240 len -= fill; | |
241 data += fill; | |
242 left = 0; | |
243 } | |
244 | |
245 while(len >= 64) { | |
246 md5_process(md5_context, data); | |
247 len -= 64; | |
248 data += 64; | |
249 } | |
250 | |
251 if(len) { | |
252 memcpy((md5_context->buffer + left), data, len); | |
253 } | |
254 } | |
255 | |
256 static gboolean | |
11183 | 257 md5_digest(GaimCipherContext *context, size_t in_len, guchar digest[16], |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
258 size_t *out_len) |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
259 { |
10684 | 260 struct MD5Context *md5_context = NULL; |
261 guint32 last, pad; | |
262 guint32 high, low; | |
11183 | 263 guchar message[8]; |
264 guchar padding[64] = { | |
10684 | 265 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
269 }; | |
270 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
271 g_return_val_if_fail(in_len >= 16, FALSE); |
10684 | 272 |
273 md5_context = gaim_cipher_context_get_data(context); | |
274 | |
275 high = (md5_context->total[0] >> 29) | |
276 | (md5_context->total[1] << 3); | |
277 low = (md5_context->total[0] << 3); | |
278 | |
279 MD5_PUT_GUINT32(low, message, 0); | |
280 MD5_PUT_GUINT32(high, message, 4); | |
281 | |
282 last = md5_context->total[0] & 0x3F; | |
283 pad = (last < 56) ? (56 - last) : (120 - last); | |
284 | |
285 md5_append(context, padding, pad); | |
286 md5_append(context, message, 8); | |
287 | |
288 MD5_PUT_GUINT32(md5_context->state[0], digest, 0); | |
289 MD5_PUT_GUINT32(md5_context->state[1], digest, 4); | |
290 MD5_PUT_GUINT32(md5_context->state[2], digest, 8); | |
291 MD5_PUT_GUINT32(md5_context->state[3], digest, 12); | |
292 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
293 if(out_len) |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
294 *out_len = 16; |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
295 |
10684 | 296 return TRUE; |
297 } | |
298 | |
299 static GaimCipherOps MD5Ops = { | |
300 NULL, /* Set option */ | |
301 NULL, /* Get option */ | |
302 md5_init, /* init */ | |
303 md5_reset, /* reset */ | |
304 md5_uninit, /* uninit */ | |
305 NULL, /* set iv */ | |
306 md5_append, /* append */ | |
307 md5_digest, /* digest */ | |
308 NULL, /* encrypt */ | |
309 NULL, /* decrypt */ | |
310 NULL, /* set salt */ | |
311 NULL, /* get salt size */ | |
312 NULL, /* set key */ | |
313 NULL /* get key size */ | |
314 }; | |
315 | |
316 /******************************************************************************* | |
317 * SHA-1 | |
318 ******************************************************************************/ | |
319 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) | |
320 | |
321 struct SHA1Context { | |
322 guint32 H[5]; | |
323 guint32 W[80]; | |
324 | |
325 gint lenW; | |
326 | |
327 guint32 sizeHi; | |
328 guint32 sizeLo; | |
329 }; | |
330 | |
331 static void | |
332 sha1_hash_block(struct SHA1Context *sha1_ctx) { | |
333 gint i; | |
334 guint32 A, B, C, D, E, T; | |
335 | |
336 for(i = 16; i < 80; i++) { | |
337 sha1_ctx->W[i] = SHA1_ROTL(sha1_ctx->W[i - 3] ^ | |
338 sha1_ctx->W[i - 8] ^ | |
339 sha1_ctx->W[i - 14] ^ | |
340 sha1_ctx->W[i - 16], 1); | |
341 } | |
342 | |
343 A = sha1_ctx->H[0]; | |
344 B = sha1_ctx->H[1]; | |
345 C = sha1_ctx->H[2]; | |
346 D = sha1_ctx->H[3]; | |
347 E = sha1_ctx->H[4]; | |
348 | |
349 for(i = 0; i < 20; i++) { | |
350 T = (SHA1_ROTL(A, 5) + (((C ^ D) & B) ^ D) + E + sha1_ctx->W[i] + 0x5A827999) & 0xFFFFFFFF; | |
351 E = D; | |
352 D = C; | |
353 C = SHA1_ROTL(B, 30); | |
354 B = A; | |
355 A = T; | |
356 } | |
357 | |
358 for(i = 20; i < 40; i++) { | |
359 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0x6ED9EBA1) & 0xFFFFFFFF; | |
360 E = D; | |
361 D = C; | |
362 C = SHA1_ROTL(B, 30); | |
363 B = A; | |
364 A = T; | |
365 } | |
366 | |
367 for(i = 40; i < 60; i++) { | |
368 T = (SHA1_ROTL(A, 5) + ((B & C) | (D & (B | C))) + E + sha1_ctx->W[i] + 0x8F1BBCDC) & 0xFFFFFFFF; | |
369 E = D; | |
370 D = C; | |
371 C = SHA1_ROTL(B, 30); | |
372 B = A; | |
373 A = T; | |
374 } | |
375 | |
376 for(i = 60; i < 80; i++) { | |
377 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0xCA62C1D6) & 0xFFFFFFFF; | |
378 E = D; | |
379 D = C; | |
380 C = SHA1_ROTL(B, 30); | |
381 B = A; | |
382 A = T; | |
383 } | |
384 | |
385 sha1_ctx->H[0] += A; | |
386 sha1_ctx->H[1] += B; | |
387 sha1_ctx->H[2] += C; | |
388 sha1_ctx->H[3] += D; | |
11183 | 389 sha1_ctx->H[4] += E; |
10684 | 390 } |
391 | |
392 static void | |
393 sha1_set_opt(GaimCipherContext *context, const gchar *name, void *value) { | |
394 struct SHA1Context *ctx; | |
395 | |
396 ctx = gaim_cipher_context_get_data(context); | |
397 | |
398 if(!strcmp(name, "sizeHi")) { | |
399 ctx->sizeHi = GPOINTER_TO_INT(value); | |
400 } else if(!strcmp(name, "sizeLo")) { | |
401 ctx->sizeLo = GPOINTER_TO_INT(value); | |
402 } else if(!strcmp(name, "lenW")) { | |
403 ctx->lenW = GPOINTER_TO_INT(value); | |
404 } | |
405 } | |
406 | |
407 static void * | |
408 sha1_get_opt(GaimCipherContext *context, const gchar *name) { | |
409 struct SHA1Context *ctx; | |
410 | |
411 ctx = gaim_cipher_context_get_data(context); | |
412 | |
413 if(!strcmp(name, "sizeHi")) { | |
414 return GINT_TO_POINTER(ctx->sizeHi); | |
415 } else if(!strcmp(name, "sizeLo")) { | |
416 return GINT_TO_POINTER(ctx->sizeLo); | |
417 } else if(!strcmp(name, "lenW")) { | |
418 return GINT_TO_POINTER(ctx->lenW); | |
419 } | |
420 | |
421 return NULL; | |
422 } | |
423 | |
424 static void | |
425 sha1_init(GaimCipherContext *context, void *extra) { | |
426 struct SHA1Context *sha1_ctx; | |
427 | |
428 sha1_ctx = g_new0(struct SHA1Context, 1); | |
429 | |
430 gaim_cipher_context_set_data(context, sha1_ctx); | |
431 | |
432 gaim_cipher_context_reset(context, extra); | |
433 } | |
434 | |
435 static void | |
436 sha1_reset(GaimCipherContext *context, void *extra) { | |
437 struct SHA1Context *sha1_ctx; | |
438 gint i; | |
439 | |
440 sha1_ctx = gaim_cipher_context_get_data(context); | |
441 | |
442 g_return_if_fail(sha1_ctx); | |
443 | |
444 sha1_ctx->lenW = 0; | |
445 sha1_ctx->sizeHi = 0; | |
446 sha1_ctx->sizeLo = 0; | |
447 | |
448 sha1_ctx->H[0] = 0x67452301; | |
449 sha1_ctx->H[1] = 0xEFCDAB89; | |
450 sha1_ctx->H[2] = 0x98BADCFE; | |
451 sha1_ctx->H[3] = 0x10325476; | |
452 sha1_ctx->H[4] = 0xC3D2E1F0; | |
453 | |
454 for(i = 0; i < 80; i++) | |
455 sha1_ctx->W[i] = 0; | |
456 } | |
457 | |
458 static void | |
459 sha1_uninit(GaimCipherContext *context) { | |
460 struct SHA1Context *sha1_ctx; | |
461 | |
462 gaim_cipher_context_reset(context, NULL); | |
463 | |
464 sha1_ctx = gaim_cipher_context_get_data(context); | |
465 | |
466 memset(sha1_ctx, 0, sizeof(struct SHA1Context)); | |
467 | |
468 g_free(sha1_ctx); | |
469 sha1_ctx = NULL; | |
470 } | |
471 | |
472 | |
473 static void | |
11183 | 474 sha1_append(GaimCipherContext *context, const guchar *data, size_t len) { |
10684 | 475 struct SHA1Context *sha1_ctx; |
476 gint i; | |
477 | |
478 sha1_ctx = gaim_cipher_context_get_data(context); | |
479 | |
480 g_return_if_fail(sha1_ctx); | |
481 | |
482 for(i = 0; i < len; i++) { | |
483 sha1_ctx->W[sha1_ctx->lenW / 4] <<= 8; | |
484 sha1_ctx->W[sha1_ctx->lenW / 4] |= data[i]; | |
485 | |
486 if((++sha1_ctx->lenW) % 64 == 0) { | |
487 sha1_hash_block(sha1_ctx); | |
488 sha1_ctx->lenW = 0; | |
489 } | |
490 | |
491 sha1_ctx->sizeLo += 8; | |
492 sha1_ctx->sizeHi += (sha1_ctx->sizeLo < 8); | |
493 } | |
494 } | |
495 | |
496 static gboolean | |
11183 | 497 sha1_digest(GaimCipherContext *context, size_t in_len, guchar digest[20], |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
498 size_t *out_len) |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
499 { |
10684 | 500 struct SHA1Context *sha1_ctx; |
11183 | 501 guchar pad0x80 = 0x80, pad0x00 = 0x00; |
502 guchar padlen[8]; | |
10684 | 503 gint i; |
504 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
505 g_return_val_if_fail(in_len >= 20, FALSE); |
10684 | 506 |
507 sha1_ctx = gaim_cipher_context_get_data(context); | |
508 | |
509 g_return_val_if_fail(sha1_ctx, FALSE); | |
510 | |
11183 | 511 padlen[0] = (guchar)((sha1_ctx->sizeHi >> 24) & 255); |
512 padlen[1] = (guchar)((sha1_ctx->sizeHi >> 16) & 255); | |
513 padlen[2] = (guchar)((sha1_ctx->sizeHi >> 8) & 255); | |
514 padlen[3] = (guchar)((sha1_ctx->sizeHi >> 0) & 255); | |
515 padlen[4] = (guchar)((sha1_ctx->sizeLo >> 24) & 255); | |
516 padlen[5] = (guchar)((sha1_ctx->sizeLo >> 16) & 255); | |
517 padlen[6] = (guchar)((sha1_ctx->sizeLo >> 8) & 255); | |
518 padlen[7] = (guchar)((sha1_ctx->sizeLo >> 0) & 255); | |
10684 | 519 |
520 /* pad with a 1, then zeroes, then length */ | |
521 gaim_cipher_context_append(context, &pad0x80, 1); | |
522 while(sha1_ctx->lenW != 56) | |
523 gaim_cipher_context_append(context, &pad0x00, 1); | |
524 gaim_cipher_context_append(context, padlen, 8); | |
525 | |
526 for(i = 0; i < 20; i++) { | |
11183 | 527 digest[i] = (guchar)(sha1_ctx->H[i / 4] >> 24); |
10684 | 528 sha1_ctx->H[i / 4] <<= 8; |
529 } | |
530 | |
531 gaim_cipher_context_reset(context, NULL); | |
532 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
533 if(out_len) |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
534 *out_len = 20; |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
535 |
10684 | 536 return TRUE; |
537 } | |
538 | |
539 static GaimCipherOps SHA1Ops = { | |
540 sha1_set_opt, /* Set Option */ | |
541 sha1_get_opt, /* Get Option */ | |
542 sha1_init, /* init */ | |
543 sha1_reset, /* reset */ | |
544 sha1_uninit, /* uninit */ | |
545 NULL, /* set iv */ | |
546 sha1_append, /* append */ | |
547 sha1_digest, /* digest */ | |
548 NULL, /* encrypt */ | |
549 NULL, /* decrypt */ | |
550 NULL, /* set salt */ | |
551 NULL, /* get salt size */ | |
552 NULL, /* set key */ | |
553 NULL /* get key size */ | |
554 }; | |
555 | |
556 /******************************************************************************* | |
557 * Structs | |
558 ******************************************************************************/ | |
559 struct _GaimCipher { | |
560 gchar *name; | |
561 GaimCipherOps *ops; | |
562 guint ref; | |
563 }; | |
564 | |
565 struct _GaimCipherContext { | |
566 GaimCipher *cipher; | |
567 gpointer data; | |
568 }; | |
569 | |
570 /****************************************************************************** | |
571 * Globals | |
572 *****************************************************************************/ | |
573 static GList *ciphers = NULL; | |
574 | |
575 /****************************************************************************** | |
576 * GaimCipher API | |
577 *****************************************************************************/ | |
578 const gchar * | |
579 gaim_cipher_get_name(GaimCipher *cipher) { | |
580 g_return_val_if_fail(cipher, NULL); | |
581 | |
582 return cipher->name; | |
583 } | |
584 | |
585 guint | |
586 gaim_cipher_get_capabilities(GaimCipher *cipher) { | |
587 GaimCipherOps *ops = NULL; | |
588 guint caps = 0; | |
589 | |
590 g_return_val_if_fail(cipher, 0); | |
591 | |
592 ops = cipher->ops; | |
593 g_return_val_if_fail(ops, 0); | |
594 | |
595 if(ops->set_option) | |
596 caps |= GAIM_CIPHER_CAPS_SET_OPT; | |
597 if(ops->get_option) | |
598 caps |= GAIM_CIPHER_CAPS_GET_OPT; | |
599 if(ops->init) | |
600 caps |= GAIM_CIPHER_CAPS_INIT; | |
601 if(ops->reset) | |
602 caps |= GAIM_CIPHER_CAPS_RESET; | |
603 if(ops->uninit) | |
604 caps |= GAIM_CIPHER_CAPS_UNINIT; | |
605 if(ops->set_iv) | |
606 caps |= GAIM_CIPHER_CAPS_SET_IV; | |
607 if(ops->append) | |
608 caps |= GAIM_CIPHER_CAPS_APPEND; | |
609 if(ops->digest) | |
610 caps |= GAIM_CIPHER_CAPS_DIGEST; | |
611 if(ops->encrypt) | |
612 caps |= GAIM_CIPHER_CAPS_ENCRYPT; | |
613 if(ops->decrypt) | |
614 caps |= GAIM_CIPHER_CAPS_DECRYPT; | |
615 if(ops->set_salt) | |
616 caps |= GAIM_CIPHER_CAPS_SET_SALT; | |
617 if(ops->get_salt_size) | |
618 caps |= GAIM_CIPHER_CAPS_GET_SALT_SIZE; | |
619 if(ops->set_key) | |
620 caps |= GAIM_CIPHER_CAPS_SET_KEY; | |
621 if(ops->get_key_size) | |
622 caps |= GAIM_CIPHER_CAPS_GET_KEY_SIZE; | |
623 | |
624 return caps; | |
625 } | |
626 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
627 gboolean |
11183 | 628 gaim_cipher_digest_region(const gchar *name, const guchar *data, |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
629 size_t data_len, size_t in_len, |
11183 | 630 guchar digest[], size_t *out_len) |
10684 | 631 { |
632 GaimCipher *cipher; | |
633 GaimCipherContext *context; | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
634 gboolean ret = FALSE; |
10684 | 635 |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
636 g_return_val_if_fail(name, FALSE); |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
637 g_return_val_if_fail(data, FALSE); |
10684 | 638 |
639 cipher = gaim_ciphers_find_cipher(name); | |
640 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
641 g_return_val_if_fail(cipher, FALSE); |
10684 | 642 |
643 if(!cipher->ops->append || !cipher->ops->digest) { | |
644 gaim_debug_info("cipher", "gaim_cipher_region failed: " | |
645 "the %s cipher does not support appending and or " | |
646 "digesting.", cipher->name); | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
647 return FALSE; |
10684 | 648 } |
649 | |
650 context = gaim_cipher_context_new(cipher, NULL); | |
651 gaim_cipher_context_append(context, data, data_len); | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
652 ret = gaim_cipher_context_digest(context, in_len, digest, out_len); |
11143 | 653 gaim_cipher_context_destroy(context); |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
654 |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
655 return ret; |
10684 | 656 } |
657 | |
658 /****************************************************************************** | |
659 * GaimCiphers API | |
660 *****************************************************************************/ | |
661 GaimCipher * | |
662 gaim_ciphers_find_cipher(const gchar *name) { | |
663 GaimCipher *cipher; | |
664 GList *l; | |
665 | |
666 g_return_val_if_fail(name, NULL); | |
667 | |
668 for(l = ciphers; l; l = l->next) { | |
669 cipher = GAIM_CIPHER(l->data); | |
670 | |
671 if(!g_ascii_strcasecmp(cipher->name, name)) | |
672 return cipher; | |
673 } | |
674 | |
675 return NULL; | |
676 } | |
677 | |
678 GaimCipher * | |
679 gaim_ciphers_register_cipher(const gchar *name, GaimCipherOps *ops) { | |
680 GaimCipher *cipher = NULL; | |
681 | |
682 g_return_val_if_fail(name, NULL); | |
683 g_return_val_if_fail(ops, NULL); | |
684 g_return_val_if_fail(!gaim_ciphers_find_cipher(name), NULL); | |
685 | |
686 cipher = g_new0(GaimCipher, 1); | |
687 | |
688 cipher->name = g_strdup(name); | |
689 cipher->ops = ops; | |
690 | |
691 ciphers = g_list_append(ciphers, cipher); | |
692 | |
693 gaim_signal_emit(gaim_ciphers_get_handle(), "cipher-added", cipher); | |
694 | |
695 return cipher; | |
696 } | |
697 | |
698 gboolean | |
699 gaim_ciphers_unregister_cipher(GaimCipher *cipher) { | |
700 g_return_val_if_fail(cipher, FALSE); | |
701 g_return_val_if_fail(cipher->ref == 0, FALSE); | |
702 | |
703 gaim_signal_emit(gaim_ciphers_get_handle(), "cipher-removed", cipher); | |
704 | |
705 ciphers = g_list_remove(ciphers, cipher); | |
706 | |
707 g_free(cipher->name); | |
708 g_free(cipher); | |
709 | |
710 return TRUE; | |
711 } | |
712 | |
713 GList * | |
714 gaim_ciphers_get_ciphers() { | |
715 return ciphers; | |
716 } | |
717 | |
718 /****************************************************************************** | |
719 * GaimCipher Subsystem API | |
720 *****************************************************************************/ | |
721 gpointer | |
722 gaim_ciphers_get_handle() { | |
723 static gint handle; | |
724 | |
725 return &handle; | |
726 } | |
727 | |
728 void | |
729 gaim_ciphers_init() { | |
730 gpointer handle; | |
731 | |
732 handle = gaim_ciphers_get_handle(); | |
733 | |
734 gaim_signal_register(handle, "cipher-added", | |
735 gaim_marshal_VOID__POINTER, NULL, 1, | |
736 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
737 GAIM_SUBTYPE_CIPHER)); | |
738 gaim_signal_register(handle, "cipher-removed", | |
739 gaim_marshal_VOID__POINTER, NULL, 1, | |
740 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
741 GAIM_SUBTYPE_CIPHER)); | |
742 | |
743 gaim_ciphers_register_cipher("md5", &MD5Ops); | |
744 gaim_ciphers_register_cipher("sha1", &SHA1Ops); | |
745 } | |
746 | |
747 void | |
748 gaim_ciphers_uninit() { | |
749 GaimCipher *cipher; | |
750 GList *l, *ll; | |
751 | |
752 for(l = ciphers; l; l = ll) { | |
753 ll = l->next; | |
754 | |
755 cipher = GAIM_CIPHER(l->data); | |
756 gaim_ciphers_unregister_cipher(cipher); | |
757 | |
758 ciphers = g_list_remove(ciphers, cipher); | |
759 } | |
760 | |
761 g_list_free(ciphers); | |
762 | |
763 gaim_signals_unregister_by_instance(gaim_ciphers_get_handle()); | |
764 } | |
765 /****************************************************************************** | |
766 * GaimCipherContext API | |
767 *****************************************************************************/ | |
768 void | |
769 gaim_cipher_context_set_option(GaimCipherContext *context, const gchar *name, | |
770 gpointer value) | |
771 { | |
772 GaimCipher *cipher = NULL; | |
773 | |
774 g_return_if_fail(context); | |
775 g_return_if_fail(name); | |
776 | |
777 cipher = context->cipher; | |
778 g_return_if_fail(cipher); | |
779 | |
780 if(cipher->ops && cipher->ops->set_option) | |
781 cipher->ops->set_option(context, name, value); | |
782 else | |
783 gaim_debug_info("cipher", "the %s cipher does not support the " | |
784 "set_option operation\n", cipher->name); | |
785 } | |
786 | |
787 gpointer | |
788 gaim_cipher_context_get_option(GaimCipherContext *context, const gchar *name) { | |
789 GaimCipher *cipher = NULL; | |
790 | |
791 g_return_val_if_fail(context, NULL); | |
792 g_return_val_if_fail(name, NULL); | |
793 | |
794 cipher = context->cipher; | |
795 g_return_val_if_fail(cipher, NULL); | |
796 | |
797 if(cipher->ops && cipher->ops->get_option) | |
798 return cipher->ops->get_option(context, name); | |
799 else { | |
800 gaim_debug_info("cipher", "the %s cipher does not support the " | |
801 "get_option operation\n", cipher->name); | |
802 | |
803 return NULL; | |
804 } | |
805 } | |
806 | |
807 GaimCipherContext * | |
808 gaim_cipher_context_new(GaimCipher *cipher, void *extra) { | |
809 GaimCipherContext *context = NULL; | |
810 | |
811 g_return_val_if_fail(cipher, NULL); | |
812 | |
813 cipher->ref++; | |
814 | |
815 context = g_new0(GaimCipherContext, 1); | |
816 context->cipher = cipher; | |
817 | |
818 if(cipher->ops->init) | |
819 cipher->ops->init(context, extra); | |
820 | |
821 return context; | |
822 } | |
823 | |
824 GaimCipherContext * | |
825 gaim_cipher_context_new_by_name(const gchar *name, void *extra) { | |
826 GaimCipher *cipher; | |
827 | |
828 g_return_val_if_fail(name, NULL); | |
829 | |
830 cipher = gaim_ciphers_find_cipher(name); | |
831 | |
832 g_return_val_if_fail(cipher, NULL); | |
833 | |
834 return gaim_cipher_context_new(cipher, extra); | |
835 } | |
836 | |
837 void | |
838 gaim_cipher_context_reset(GaimCipherContext *context, void *extra) { | |
839 GaimCipher *cipher = NULL; | |
840 | |
841 g_return_if_fail(context); | |
842 | |
843 cipher = context->cipher; | |
844 g_return_if_fail(cipher); | |
845 | |
846 if(cipher->ops && cipher->ops->reset) | |
847 context->cipher->ops->reset(context, extra); | |
848 } | |
849 | |
850 void | |
851 gaim_cipher_context_destroy(GaimCipherContext *context) { | |
852 GaimCipher *cipher = NULL; | |
853 | |
854 g_return_if_fail(context); | |
855 | |
856 cipher = context->cipher; | |
857 g_return_if_fail(cipher); | |
858 | |
859 cipher->ref--; | |
860 | |
861 if(cipher->ops && cipher->ops->uninit) | |
862 cipher->ops->uninit(context); | |
863 | |
864 memset(context, 0, sizeof(context)); | |
865 g_free(context); | |
866 context = NULL; | |
867 } | |
868 | |
869 void | |
11183 | 870 gaim_cipher_context_set_iv(GaimCipherContext *context, guchar *iv, size_t len) |
10684 | 871 { |
872 GaimCipher *cipher = NULL; | |
873 | |
874 g_return_if_fail(context); | |
875 g_return_if_fail(iv); | |
876 | |
877 cipher = context->cipher; | |
878 g_return_if_fail(cipher); | |
879 | |
880 if(cipher->ops && cipher->ops->set_iv) | |
881 cipher->ops->set_iv(context, iv, len); | |
882 else | |
883 gaim_debug_info("cipher", "the %s cipher does not support the set" | |
884 "initialization vector operation\n", cipher->name); | |
885 } | |
886 | |
887 void | |
11183 | 888 gaim_cipher_context_append(GaimCipherContext *context, const guchar *data, |
10684 | 889 size_t len) |
890 { | |
891 GaimCipher *cipher = NULL; | |
892 | |
893 g_return_if_fail(context); | |
894 | |
895 cipher = context->cipher; | |
896 g_return_if_fail(cipher); | |
897 | |
898 if(cipher->ops && cipher->ops->append) | |
899 cipher->ops->append(context, data, len); | |
900 else | |
901 gaim_debug_info("cipher", "the %s cipher does not support the append " | |
902 "operation\n", cipher->name); | |
903 } | |
904 | |
905 gboolean | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
906 gaim_cipher_context_digest(GaimCipherContext *context, size_t in_len, |
11183 | 907 guchar digest[], size_t *out_len) |
10684 | 908 { |
909 GaimCipher *cipher = NULL; | |
910 | |
911 g_return_val_if_fail(context, FALSE); | |
912 | |
913 cipher = context->cipher; | |
914 g_return_val_if_fail(context, FALSE); | |
915 | |
916 if(cipher->ops && cipher->ops->digest) | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
917 return cipher->ops->digest(context, in_len, digest, out_len); |
10684 | 918 else { |
919 gaim_debug_info("cipher", "the %s cipher does not support the digest " | |
920 "operation\n", cipher->name); | |
921 return FALSE; | |
922 } | |
923 } | |
924 | |
925 gboolean | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
926 gaim_cipher_context_digest_to_str(GaimCipherContext *context, size_t in_len, |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
927 gchar digest_s[], size_t *out_len) |
10684 | 928 { |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
929 /* 8k is a bit excessive, will tweak later. */ |
11183 | 930 guchar digest[BUF_LEN * 4]; |
10684 | 931 gint n = 0; |
932 size_t dlen = 0; | |
933 | |
934 g_return_val_if_fail(context, FALSE); | |
935 g_return_val_if_fail(digest_s, FALSE); | |
936 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
937 if(!gaim_cipher_context_digest(context, sizeof(digest), digest, &dlen)) |
10684 | 938 return FALSE; |
939 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
940 if(in_len < dlen * 2) |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
941 return FALSE; |
10684 | 942 |
943 for(n = 0; n < dlen; n++) | |
944 sprintf(digest_s + (n * 2), "%02x", digest[n]); | |
945 | |
946 digest_s[n * 2] = '\0'; | |
947 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
948 if(out_len) |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
949 *out_len = dlen * 2; |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
950 |
10684 | 951 return TRUE; |
952 } | |
953 | |
954 gint | |
11183 | 955 gaim_cipher_context_encrypt(GaimCipherContext *context, const guchar data[], |
956 size_t len, guchar output[], size_t *outlen) | |
10684 | 957 { |
958 GaimCipher *cipher = NULL; | |
959 | |
960 g_return_val_if_fail(context, -1); | |
961 | |
962 cipher = context->cipher; | |
963 g_return_val_if_fail(cipher, -1); | |
964 | |
965 if(cipher->ops && cipher->ops->encrypt) | |
966 return cipher->ops->encrypt(context, data, len, output, outlen); | |
967 else { | |
968 gaim_debug_info("cipher", "the %s cipher does not support the encrypt" | |
969 "operation\n", cipher->name); | |
970 | |
971 if(outlen) | |
972 *outlen = -1; | |
973 | |
974 return -1; | |
975 } | |
976 } | |
977 | |
978 gint | |
11183 | 979 gaim_cipher_context_decrypt(GaimCipherContext *context, const guchar data[], |
980 size_t len, guchar output[], size_t *outlen) | |
10684 | 981 { |
982 GaimCipher *cipher = NULL; | |
983 | |
984 g_return_val_if_fail(context, -1); | |
985 | |
986 cipher = context->cipher; | |
987 g_return_val_if_fail(cipher, -1); | |
988 | |
989 if(cipher->ops && cipher->ops->decrypt) | |
990 return cipher->ops->decrypt(context, data, len, output, outlen); | |
991 else { | |
992 gaim_debug_info("cipher", "the %s cipher does not support the decrypt" | |
993 "operation\n", cipher->name); | |
994 | |
995 if(outlen) | |
996 *outlen = -1; | |
997 | |
998 return -1; | |
999 } | |
1000 } | |
1001 | |
1002 void | |
11183 | 1003 gaim_cipher_context_set_salt(GaimCipherContext *context, guchar *salt) { |
10684 | 1004 GaimCipher *cipher = NULL; |
1005 | |
1006 g_return_if_fail(context); | |
1007 | |
1008 cipher = context->cipher; | |
1009 g_return_if_fail(cipher); | |
1010 | |
1011 if(cipher->ops && cipher->ops->set_salt) | |
1012 cipher->ops->set_salt(context, salt); | |
1013 else | |
1014 gaim_debug_info("cipher", "the %s cipher does not support the " | |
1015 "set_salt operation\n", cipher->name); | |
1016 } | |
1017 | |
1018 size_t | |
1019 gaim_cipher_context_get_salt_size(GaimCipherContext *context) { | |
1020 GaimCipher *cipher = NULL; | |
1021 | |
1022 g_return_val_if_fail(context, -1); | |
1023 | |
1024 cipher = context->cipher; | |
1025 g_return_val_if_fail(cipher, -1); | |
1026 | |
1027 if(cipher->ops && cipher->ops->get_salt_size) | |
1028 return cipher->ops->get_salt_size(context); | |
1029 else { | |
1030 gaim_debug_info("cipher", "the %s cipher does not support the " | |
1031 "get_salt_size operation\n", cipher->name); | |
1032 | |
1033 return -1; | |
1034 } | |
1035 } | |
1036 | |
1037 void | |
11183 | 1038 gaim_cipher_context_set_key(GaimCipherContext *context, guchar *key) { |
10684 | 1039 GaimCipher *cipher = NULL; |
1040 | |
1041 g_return_if_fail(context); | |
1042 | |
1043 cipher = context->cipher; | |
1044 g_return_if_fail(cipher); | |
1045 | |
1046 if(cipher->ops && cipher->ops->set_key) | |
1047 cipher->ops->set_key(context, key); | |
1048 else | |
1049 gaim_debug_info("cipher", "the %s cipher does not support the " | |
1050 "set_key operation\n", cipher->name); | |
1051 } | |
1052 | |
1053 size_t | |
1054 gaim_cipher_context_get_key_size(GaimCipherContext *context) { | |
1055 GaimCipher *cipher = NULL; | |
1056 | |
1057 g_return_val_if_fail(context, -1); | |
1058 | |
1059 cipher = context->cipher; | |
1060 g_return_val_if_fail(cipher, -1); | |
1061 | |
1062 if(cipher->ops && cipher->ops->get_key_size) | |
1063 return cipher->ops->get_key_size(context); | |
1064 else { | |
1065 gaim_debug_info("cipher", "the %s cipher does not support the " | |
1066 "get_key_size operation\n", cipher->name); | |
1067 | |
1068 return -1; | |
1069 } | |
1070 } | |
1071 | |
1072 void | |
1073 gaim_cipher_context_set_data(GaimCipherContext *context, gpointer data) { | |
1074 g_return_if_fail(context); | |
1075 | |
1076 context->data = data; | |
1077 } | |
1078 | |
1079 gpointer | |
1080 gaim_cipher_context_get_data(GaimCipherContext *context) { | |
1081 g_return_val_if_fail(context, NULL); | |
1082 | |
1083 return context->data; | |
1084 } |