Mercurial > pidgin
annotate src/cipher.c @ 10895:ffb30c2e82cb
[gaim-migrate @ 12609]
sf patch #1193187, from Rainer Blessing
Fix an infinite loop. Infinity is a long time.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Tue, 03 May 2005 01:37:30 +0000 |
parents | b256ce6b85b8 |
children | 5c56223fa24f |
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]; | |
41 guint8 buffer[64]; | |
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 } | |
50 #define MD5_PUT_GUINT32(n,b,i) { \ | |
51 (b)[(i) ] = (guint8)((n) ); \ | |
52 (b)[(i) + 1] = (guint8)((n) >> 8); \ | |
53 (b)[(i) + 2] = (guint8)((n) >> 16); \ | |
54 (b)[(i) + 3] = (guint8)((n) >> 24); \ | |
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 | |
99 md5_process(struct MD5Context *md5_context, const guint8 data[64]) { | |
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 | |
169 | |
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 | |
219 md5_append(GaimCipherContext *context, const guint8 *data, size_t len) { | |
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 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
257 md5_digest(GaimCipherContext *context, size_t in_len, guint8 digest[16], |
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; | |
263 guint8 message[8]; | |
264 guint8 padding[64] = { | |
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; | |
389 sha1_ctx->H[4] += E; | |
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 | |
474 sha1_append(GaimCipherContext *context, const guint8 *data, size_t len) { | |
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 | |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
497 sha1_digest(GaimCipherContext *context, size_t in_len, guint8 digest[20], |
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; |
501 guint8 pad0x80 = 0x80, pad0x00 = 0x00; | |
502 guint8 padlen[8]; | |
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 | |
511 padlen[0] = (guint8)((sha1_ctx->sizeHi >> 24) & 255); | |
512 padlen[1] = (guint8)((sha1_ctx->sizeHi >> 16) & 255); | |
513 padlen[2] = (guint8)((sha1_ctx->sizeHi >> 8) & 255); | |
514 padlen[3] = (guint8)((sha1_ctx->sizeHi >> 0) & 255); | |
515 padlen[4] = (guint8)((sha1_ctx->sizeLo >> 24) & 255); | |
516 padlen[5] = (guint8)((sha1_ctx->sizeLo >> 16) & 255); | |
517 padlen[6] = (guint8)((sha1_ctx->sizeLo >> 8) & 255); | |
518 padlen[7] = (guint8)((sha1_ctx->sizeLo >> 0) & 255); | |
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++) { | |
527 digest[i] = (guint8)(sha1_ctx->H[i / 4] >> 24); | |
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 |
10684 | 628 gaim_cipher_digest_region(const gchar *name, const guint8 *data, |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
629 size_t data_len, size_t in_len, |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
630 guint8 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); |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
653 gaim_cipher_context_destroy(context); |
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 | |
870 gaim_cipher_context_set_iv(GaimCipherContext *context, guint8 *iv, size_t len) | |
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 | |
888 gaim_cipher_context_append(GaimCipherContext *context, const guint8 *data, | |
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, |
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
907 guint8 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. */ |
10684 | 930 guint8 digest[BUF_LEN * 4]; |
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 | |
955 gaim_cipher_context_encrypt(GaimCipherContext *context, const guint8 data[], | |
956 size_t len, guint8 output[], size_t *outlen) | |
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 | |
979 gaim_cipher_context_decrypt(GaimCipherContext *context, const guint8 data[], | |
980 size_t len, guint8 output[], size_t *outlen) | |
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 | |
1003 gaim_cipher_context_set_salt(GaimCipherContext *context, guint8 *salt) { | |
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 | |
1038 gaim_cipher_context_set_key(GaimCipherContext *context, guint8 *key) { | |
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 } |