Mercurial > pidgin
annotate src/cipher.c @ 13218:c01aa6ea4947
[gaim-migrate @ 15582]
Whitespace...
committer: Tailor Script <tailor@pidgin.im>
| author | Richard Laager <rlaager@wiktel.com> |
|---|---|
| date | Sat, 11 Feb 2006 05:18:48 +0000 |
| parents | e024601d45c7 |
| children | ff4e85e04adf |
| 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 * | |
| 11329 | 11 * Original md4 taken from linux kernel |
| 12 * MD4 Message Digest Algorithm (RFC1320). | |
| 13 * | |
| 14 * Implementation derived from Andrew Tridgell and Steve French's | |
| 15 * CIFS MD4 implementation, and the cryptoapi implementation | |
| 16 * originally based on the public domain implementation written | |
| 17 * by Colin Plumb in 1993. | |
| 18 * | |
| 19 * Copyright (c) Andrew Tridgell 1997-1998. | |
| 20 * Modified by Steve French (sfrench@us.ibm.com) 2002 | |
| 21 * Copyright (c) Cryptoapi developers. | |
| 22 * Copyright (c) 2002 David S. Miller (davem@redhat.com) | |
| 23 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | |
| 24 * | |
| 11335 | 25 * Original des taken from gpg |
| 26 * | |
| 27 * des.c - DES and Triple-DES encryption/decryption Algorithm | |
| 28 * Copyright (C) 1998 Free Software Foundation, Inc. | |
| 29 * | |
| 30 * Please see below for more legal information! | |
| 31 * | |
| 32 * According to the definition of DES in FIPS PUB 46-2 from December 1993. | |
| 33 * For a description of triple encryption, see: | |
| 34 * Bruce Schneier: Applied Cryptography. Second Edition. | |
| 35 * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. | |
| 36 * | |
| 37 * This file is part of GnuPG. | |
| 38 * | |
| 10684 | 39 * This program is free software; you can redistribute it and/or modify |
| 40 * it under the terms of the GNU General Public License as published by | |
| 41 * the Free Software Foundation; either version 2 of the License, or | |
| 42 * (at your option) any later version. | |
| 43 * | |
| 44 * This program is distributed in the hope that it will be useful, | |
| 45 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 47 * GNU General Public License for more details. | |
| 48 * | |
| 49 * You should have received a copy of the GNU General Public License | |
| 50 * along with this program; if not, write to the Free Software | |
| 51 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 52 */ | |
| 53 #include <glib.h> | |
| 54 #include <string.h> | |
| 55 #include <stdio.h> | |
| 56 | |
| 57 #include "internal.h" | |
| 58 #include "cipher.h" | |
| 59 #include "debug.h" | |
| 60 #include "signals.h" | |
| 61 #include "value.h" | |
| 62 | |
| 63 /******************************************************************************* | |
| 64 * MD5 | |
| 65 ******************************************************************************/ | |
| 66 struct MD5Context { | |
| 67 guint32 total[2]; | |
| 68 guint32 state[4]; | |
| 11183 | 69 guchar buffer[64]; |
| 10684 | 70 }; |
| 71 | |
| 72 #define MD5_GET_GUINT32(n,b,i) { \ | |
| 73 (n) = ((guint32)(b) [(i) ] ) \ | |
| 74 | ((guint32)(b) [(i) + 1] << 8) \ | |
| 75 | ((guint32)(b) [(i) + 2] << 16) \ | |
| 76 | ((guint32)(b) [(i) + 3] << 24); \ | |
| 77 } | |
| 11183 | 78 #define MD5_PUT_GUINT32(n,b,i) { \ |
| 79 (b)[(i) ] = (guchar)((n) ); \ | |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
80 (b)[(i) + 1] = (guchar)((n) >> 8); \ |
| 11183 | 81 (b)[(i) + 2] = (guchar)((n) >> 16); \ |
| 82 (b)[(i) + 3] = (guchar)((n) >> 24); \ | |
| 10684 | 83 } |
| 84 | |
| 85 static void | |
| 86 md5_init(GaimCipherContext *context, gpointer extra) { | |
| 87 struct MD5Context *md5_context; | |
| 88 | |
| 89 md5_context = g_new0(struct MD5Context, 1); | |
| 90 | |
| 91 gaim_cipher_context_set_data(context, md5_context); | |
| 92 | |
| 93 gaim_cipher_context_reset(context, extra); | |
| 94 } | |
| 95 | |
| 96 static void | |
| 97 md5_reset(GaimCipherContext *context, gpointer extra) { | |
| 98 struct MD5Context *md5_context; | |
| 99 | |
| 100 md5_context = gaim_cipher_context_get_data(context); | |
| 101 | |
| 102 md5_context->total[0] = 0; | |
| 103 md5_context->total[1] = 0; | |
| 104 | |
| 105 md5_context->state[0] = 0x67452301; | |
| 106 md5_context->state[1] = 0xEFCDAB89; | |
| 107 md5_context->state[2] = 0x98BADCFE; | |
| 108 md5_context->state[3] = 0x10325476; | |
| 109 | |
| 110 memset(md5_context->buffer, 0, sizeof(md5_context->buffer)); | |
| 111 } | |
| 112 | |
| 113 static void | |
| 114 md5_uninit(GaimCipherContext *context) { | |
| 115 struct MD5Context *md5_context; | |
| 116 | |
| 117 gaim_cipher_context_reset(context, NULL); | |
| 118 | |
| 119 md5_context = gaim_cipher_context_get_data(context); | |
| 120 memset(md5_context, 0, sizeof(md5_context)); | |
| 121 | |
| 122 g_free(md5_context); | |
| 123 md5_context = NULL; | |
| 124 } | |
| 125 | |
| 126 static void | |
| 11183 | 127 md5_process(struct MD5Context *md5_context, const guchar data[64]) { |
| 10684 | 128 guint32 X[16], A, B, C, D; |
| 129 | |
| 130 A = md5_context->state[0]; | |
| 131 B = md5_context->state[1]; | |
| 132 C = md5_context->state[2]; | |
| 133 D = md5_context->state[3]; | |
| 134 | |
| 135 MD5_GET_GUINT32(X[ 0], data, 0); | |
| 136 MD5_GET_GUINT32(X[ 1], data, 4); | |
| 137 MD5_GET_GUINT32(X[ 2], data, 8); | |
| 138 MD5_GET_GUINT32(X[ 3], data, 12); | |
| 139 MD5_GET_GUINT32(X[ 4], data, 16); | |
| 140 MD5_GET_GUINT32(X[ 5], data, 20); | |
| 141 MD5_GET_GUINT32(X[ 6], data, 24); | |
| 142 MD5_GET_GUINT32(X[ 7], data, 28); | |
| 143 MD5_GET_GUINT32(X[ 8], data, 32); | |
| 144 MD5_GET_GUINT32(X[ 9], data, 36); | |
| 145 MD5_GET_GUINT32(X[10], data, 40); | |
| 146 MD5_GET_GUINT32(X[11], data, 44); | |
| 147 MD5_GET_GUINT32(X[12], data, 48); | |
| 148 MD5_GET_GUINT32(X[13], data, 52); | |
| 149 MD5_GET_GUINT32(X[14], data, 56); | |
| 150 MD5_GET_GUINT32(X[15], data, 60); | |
| 151 | |
| 152 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) | |
| 153 #define P(a,b,c,d,k,s,t) { \ | |
| 154 a += F(b,c,d) + X[k] + t; \ | |
| 155 a = S(a,s) + b; \ | |
| 156 } | |
| 157 | |
| 158 /* first pass */ | |
| 159 #define F(x,y,z) (z ^ (x & (y ^ z))) | |
| 160 P(A, B, C, D, 0, 7, 0xD76AA478); | |
| 161 P(D, A, B, C, 1, 12, 0xE8C7B756); | |
| 162 P(C, D, A, B, 2, 17, 0x242070DB); | |
| 163 P(B, C, D, A, 3, 22, 0xC1BDCEEE); | |
| 164 P(A, B, C, D, 4, 7, 0xF57C0FAF); | |
| 165 P(D, A, B, C, 5, 12, 0x4787C62A); | |
| 166 P(C, D, A, B, 6, 17, 0xA8304613); | |
| 167 P(B, C, D, A, 7, 22, 0xFD469501); | |
| 168 P(A, B, C, D, 8, 7, 0x698098D8); | |
| 169 P(D, A, B, C, 9, 12, 0x8B44F7AF); | |
| 170 P(C, D, A, B, 10, 17, 0xFFFF5BB1); | |
| 171 P(B, C, D, A, 11, 22, 0x895CD7BE); | |
| 172 P(A, B, C, D, 12, 7, 0x6B901122); | |
| 173 P(D, A, B, C, 13, 12, 0xFD987193); | |
| 174 P(C, D, A, B, 14, 17, 0xA679438E); | |
| 175 P(B, C, D, A, 15, 22, 0x49B40821); | |
| 176 #undef F | |
| 177 | |
| 178 /* second pass */ | |
| 179 #define F(x,y,z) (y ^ (z & (x ^ y))) | |
| 180 P(A, B, C, D, 1, 5, 0xF61E2562); | |
| 181 P(D, A, B, C, 6, 9, 0xC040B340); | |
| 182 P(C, D, A, B, 11, 14, 0x265E5A51); | |
| 183 P(B, C, D, A, 0, 20, 0xE9B6C7AA); | |
| 184 P(A, B, C, D, 5, 5, 0xD62F105D); | |
| 185 P(D, A, B, C, 10, 9, 0x02441453); | |
| 186 P(C, D, A, B, 15, 14, 0xD8A1E681); | |
| 187 P(B, C, D, A, 4, 20, 0xE7D3FBC8); | |
| 188 P(A, B, C, D, 9, 5, 0x21E1CDE6); | |
| 189 P(D, A, B, C, 14, 9, 0xC33707D6); | |
| 190 P(C, D, A, B, 3, 14, 0xF4D50D87); | |
| 191 P(B, C, D, A, 8, 20, 0x455A14ED); | |
| 192 P(A, B, C, D, 13, 5, 0xA9E3E905); | |
| 193 P(D, A, B, C, 2, 9, 0xFCEFA3F8); | |
| 194 P(C, D, A, B, 7, 14, 0x676F02D9); | |
| 195 P(B, C, D, A, 12, 20, 0x8D2A4C8A); | |
| 196 #undef F | |
| 11183 | 197 |
| 10684 | 198 /* third pass */ |
| 199 #define F(x,y,z) (x ^ y ^ z) | |
| 200 P(A, B, C, D, 5, 4, 0xFFFA3942); | |
| 201 P(D, A, B, C, 8, 11, 0x8771F681); | |
| 202 P(C, D, A, B, 11, 16, 0x6D9D6122); | |
| 203 P(B, C, D, A, 14, 23, 0xFDE5380C); | |
| 204 P(A, B, C, D, 1, 4, 0xA4BEEA44); | |
| 205 P(D, A, B, C, 4, 11, 0x4BDECFA9); | |
| 206 P(C, D, A, B, 7, 16, 0xF6BB4B60); | |
| 207 P(B, C, D, A, 10, 23, 0xBEBFBC70); | |
| 208 P(A, B, C, D, 13, 4, 0x289B7EC6); | |
| 209 P(D, A, B, C, 0, 11, 0xEAA127FA); | |
| 210 P(C, D, A, B, 3, 16, 0xD4EF3085); | |
| 211 P(B, C, D, A, 6, 23, 0x04881D05); | |
| 212 P(A, B, C, D, 9, 4, 0xD9D4D039); | |
| 213 P(D, A, B, C, 12, 11, 0xE6DB99E5); | |
| 214 P(C, D, A, B, 15, 16, 0x1FA27CF8); | |
| 215 P(B, C, D, A, 2, 23, 0xC4AC5665); | |
| 216 #undef F | |
| 217 | |
| 218 /* forth pass */ | |
| 219 #define F(x,y,z) (y ^ (x | ~z)) | |
| 220 P(A, B, C, D, 0, 6, 0xF4292244); | |
| 221 P(D, A, B, C, 7, 10, 0x432AFF97); | |
| 222 P(C, D, A, B, 14, 15, 0xAB9423A7); | |
| 223 P(B, C, D, A, 5, 21, 0xFC93A039); | |
| 224 P(A, B, C, D, 12, 6, 0x655B59C3); | |
| 225 P(D, A, B, C, 3, 10, 0x8F0CCC92); | |
| 226 P(C, D, A, B, 10, 15, 0xFFEFF47D); | |
| 227 P(B, C, D, A, 1, 21, 0x85845DD1); | |
| 228 P(A, B, C, D, 8, 6, 0x6FA87E4F); | |
| 229 P(D, A, B, C, 15, 10, 0xFE2CE6E0); | |
| 230 P(C, D, A, B, 6, 15, 0xA3014314); | |
| 231 P(B, C, D, A, 13, 21, 0x4E0811A1); | |
| 232 P(A, B, C, D, 4, 6, 0xF7537E82); | |
| 233 P(D, A, B, C, 11, 10, 0xBD3AF235); | |
| 234 P(C, D, A, B, 2, 15, 0x2AD7D2BB); | |
| 235 P(B, C, D, A, 9, 21, 0xEB86D391); | |
| 236 #undef F | |
| 237 #undef P | |
| 238 #undef S | |
| 239 | |
| 240 md5_context->state[0] += A; | |
| 241 md5_context->state[1] += B; | |
| 242 md5_context->state[2] += C; | |
| 243 md5_context->state[3] += D; | |
| 244 } | |
| 245 | |
| 246 static void | |
| 11183 | 247 md5_append(GaimCipherContext *context, const guchar *data, size_t len) { |
| 10684 | 248 struct MD5Context *md5_context = NULL; |
| 249 guint32 left = 0, fill = 0; | |
| 250 | |
| 251 g_return_if_fail(context != NULL); | |
| 252 | |
| 253 md5_context = gaim_cipher_context_get_data(context); | |
| 254 g_return_if_fail(md5_context != NULL); | |
| 255 | |
| 256 left = md5_context->total[0] & 0x3F; | |
| 257 fill = 64 - left; | |
| 258 | |
| 259 md5_context->total[0] += len; | |
| 260 md5_context->total[0] &= 0xFFFFFFFF; | |
| 261 | |
| 262 if(md5_context->total[0] < len) | |
| 263 md5_context->total[1]++; | |
| 264 | |
| 265 if(left && len >= fill) { | |
| 266 memcpy((md5_context->buffer + left), data, fill); | |
| 267 md5_process(md5_context, md5_context->buffer); | |
| 268 len -= fill; | |
| 269 data += fill; | |
| 270 left = 0; | |
| 271 } | |
| 272 | |
| 273 while(len >= 64) { | |
| 274 md5_process(md5_context, data); | |
| 275 len -= 64; | |
| 276 data += 64; | |
| 277 } | |
| 278 | |
| 279 if(len) { | |
| 280 memcpy((md5_context->buffer + left), data, len); | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 static gboolean | |
| 11183 | 285 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
|
286 size_t *out_len) |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
287 { |
| 10684 | 288 struct MD5Context *md5_context = NULL; |
| 289 guint32 last, pad; | |
| 290 guint32 high, low; | |
| 11183 | 291 guchar message[8]; |
| 292 guchar padding[64] = { | |
| 10684 | 293 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| 297 }; | |
| 298 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
299 g_return_val_if_fail(in_len >= 16, FALSE); |
| 10684 | 300 |
| 301 md5_context = gaim_cipher_context_get_data(context); | |
| 302 | |
| 303 high = (md5_context->total[0] >> 29) | |
| 304 | (md5_context->total[1] << 3); | |
| 305 low = (md5_context->total[0] << 3); | |
| 306 | |
| 307 MD5_PUT_GUINT32(low, message, 0); | |
| 308 MD5_PUT_GUINT32(high, message, 4); | |
| 309 | |
| 310 last = md5_context->total[0] & 0x3F; | |
| 311 pad = (last < 56) ? (56 - last) : (120 - last); | |
| 312 | |
| 313 md5_append(context, padding, pad); | |
| 314 md5_append(context, message, 8); | |
| 315 | |
| 316 MD5_PUT_GUINT32(md5_context->state[0], digest, 0); | |
| 317 MD5_PUT_GUINT32(md5_context->state[1], digest, 4); | |
| 318 MD5_PUT_GUINT32(md5_context->state[2], digest, 8); | |
| 319 MD5_PUT_GUINT32(md5_context->state[3], digest, 12); | |
| 320 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
321 if(out_len) |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
322 *out_len = 16; |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
323 |
| 10684 | 324 return TRUE; |
| 325 } | |
| 326 | |
| 327 static GaimCipherOps MD5Ops = { | |
| 328 NULL, /* Set option */ | |
| 329 NULL, /* Get option */ | |
| 330 md5_init, /* init */ | |
| 331 md5_reset, /* reset */ | |
| 332 md5_uninit, /* uninit */ | |
| 333 NULL, /* set iv */ | |
| 334 md5_append, /* append */ | |
| 335 md5_digest, /* digest */ | |
| 336 NULL, /* encrypt */ | |
| 337 NULL, /* decrypt */ | |
| 338 NULL, /* set salt */ | |
| 339 NULL, /* get salt size */ | |
| 340 NULL, /* set key */ | |
| 341 NULL /* get key size */ | |
| 342 }; | |
| 343 | |
| 344 /******************************************************************************* | |
| 11329 | 345 * MD4 |
| 346 ******************************************************************************/ | |
| 347 #define MD4_DIGEST_SIZE 16 | |
| 348 #define MD4_HMAC_BLOCK_SIZE 64 | |
| 349 #define MD4_BLOCK_WORDS 16 | |
| 350 #define MD4_HASH_WORDS 4 | |
| 351 | |
| 352 | |
| 353 | |
| 354 struct MD4_Context { | |
| 355 guint32 hash[MD4_HASH_WORDS]; | |
| 356 guint32 block[MD4_BLOCK_WORDS]; | |
| 357 guint64 byte_count; | |
| 358 }; | |
| 359 | |
| 360 static inline guint32 lshift(guint32 x, unsigned int s) | |
| 361 { | |
| 362 x &= 0xFFFFFFFF; | |
| 363 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); | |
| 364 } | |
| 365 | |
| 366 static inline guint32 F(guint32 x, guint32 y, guint32 z) | |
| 367 { | |
| 368 return (x & y) | ((~x) & z); | |
| 369 } | |
| 370 | |
| 371 static inline guint32 G(guint32 x, guint32 y, guint32 z) | |
| 372 { | |
| 373 return (x & y) | (x & z) | (y & z); | |
| 374 } | |
| 375 | |
| 376 static inline guint32 H(guint32 x, guint32 y, guint32 z) | |
| 377 { | |
| 378 return x ^ y ^ z; | |
| 379 } | |
| 380 | |
| 381 #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) | |
| 382 #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (guint32)0x5A827999,s)) | |
| 383 #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (guint32)0x6ED9EBA1,s)) | |
| 384 | |
| 385 static inline void le32_to_cpu_array(guint32 *buf, unsigned int words) | |
| 386 { | |
| 387 while (words--) { | |
| 388 *buf=GUINT_FROM_LE(*buf); | |
| 389 buf++; | |
| 390 } | |
| 391 } | |
| 392 | |
| 393 static inline void cpu_to_le32_array(guint32 *buf, unsigned int words) | |
| 394 { | |
| 395 while (words--) { | |
| 396 *buf=GUINT_TO_LE(*buf); | |
| 397 buf++; | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 static void md4_transform(guint32 *hash, guint32 const *in) | |
| 402 { | |
| 403 guint32 a, b, c, d; | |
| 404 | |
| 405 a = hash[0]; | |
| 406 b = hash[1]; | |
| 407 c = hash[2]; | |
| 408 d = hash[3]; | |
| 409 | |
| 410 ROUND1(a, b, c, d, in[0], 3); | |
| 411 ROUND1(d, a, b, c, in[1], 7); | |
| 412 ROUND1(c, d, a, b, in[2], 11); | |
| 413 ROUND1(b, c, d, a, in[3], 19); | |
| 414 ROUND1(a, b, c, d, in[4], 3); | |
| 415 ROUND1(d, a, b, c, in[5], 7); | |
| 416 ROUND1(c, d, a, b, in[6], 11); | |
| 417 ROUND1(b, c, d, a, in[7], 19); | |
| 418 ROUND1(a, b, c, d, in[8], 3); | |
| 419 ROUND1(d, a, b, c, in[9], 7); | |
| 420 ROUND1(c, d, a, b, in[10], 11); | |
| 421 ROUND1(b, c, d, a, in[11], 19); | |
| 422 ROUND1(a, b, c, d, in[12], 3); | |
| 423 ROUND1(d, a, b, c, in[13], 7); | |
| 424 ROUND1(c, d, a, b, in[14], 11); | |
| 425 ROUND1(b, c, d, a, in[15], 19); | |
| 426 | |
| 427 ROUND2(a, b, c, d,in[ 0], 3); | |
| 428 ROUND2(d, a, b, c, in[4], 5); | |
| 429 ROUND2(c, d, a, b, in[8], 9); | |
| 430 ROUND2(b, c, d, a, in[12], 13); | |
| 431 ROUND2(a, b, c, d, in[1], 3); | |
| 432 ROUND2(d, a, b, c, in[5], 5); | |
| 433 ROUND2(c, d, a, b, in[9], 9); | |
| 434 ROUND2(b, c, d, a, in[13], 13); | |
| 435 ROUND2(a, b, c, d, in[2], 3); | |
| 436 ROUND2(d, a, b, c, in[6], 5); | |
| 437 ROUND2(c, d, a, b, in[10], 9); | |
| 438 ROUND2(b, c, d, a, in[14], 13); | |
| 439 ROUND2(a, b, c, d, in[3], 3); | |
| 440 ROUND2(d, a, b, c, in[7], 5); | |
| 441 ROUND2(c, d, a, b, in[11], 9); | |
| 442 ROUND2(b, c, d, a, in[15], 13); | |
| 443 | |
| 444 ROUND3(a, b, c, d,in[ 0], 3); | |
| 445 ROUND3(d, a, b, c, in[8], 9); | |
| 446 ROUND3(c, d, a, b, in[4], 11); | |
| 447 ROUND3(b, c, d, a, in[12], 15); | |
| 448 ROUND3(a, b, c, d, in[2], 3); | |
| 449 ROUND3(d, a, b, c, in[10], 9); | |
| 450 ROUND3(c, d, a, b, in[6], 11); | |
| 451 ROUND3(b, c, d, a, in[14], 15); | |
| 452 ROUND3(a, b, c, d, in[1], 3); | |
| 453 ROUND3(d, a, b, c, in[9], 9); | |
| 454 ROUND3(c, d, a, b, in[5], 11); | |
| 455 ROUND3(b, c, d, a, in[13], 15); | |
| 456 ROUND3(a, b, c, d, in[3], 3); | |
| 457 ROUND3(d, a, b, c, in[11], 9); | |
| 458 ROUND3(c, d, a, b, in[7], 11); | |
| 459 ROUND3(b, c, d, a, in[15], 15); | |
| 460 | |
| 461 hash[0] += a; | |
| 462 hash[1] += b; | |
| 463 hash[2] += c; | |
| 464 hash[3] += d; | |
| 465 } | |
| 466 | |
| 467 static inline void md4_transform_helper(struct MD4_Context *ctx) | |
| 468 { | |
| 469 le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(guint32)); | |
| 470 md4_transform(ctx->hash, ctx->block); | |
| 471 } | |
| 472 | |
| 473 static void | |
| 474 md4_init(GaimCipherContext *context, gpointer extra) { | |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
475 struct MD4_Context *mctx; |
|
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
476 mctx = g_new0(struct MD4_Context, 1); |
|
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
477 gaim_cipher_context_set_data(context, mctx); |
|
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
478 gaim_cipher_context_reset(context, extra); |
| 11329 | 479 |
| 480 mctx->hash[0] = 0x67452301; | |
| 481 mctx->hash[1] = 0xefcdab89; | |
| 482 mctx->hash[2] = 0x98badcfe; | |
| 483 mctx->hash[3] = 0x10325476; | |
| 484 mctx->byte_count = 0; | |
| 485 } | |
| 486 | |
| 487 static void | |
| 488 md4_reset(GaimCipherContext *context, gpointer extra) { | |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
489 struct MD4_Context *mctx; |
| 11329 | 490 |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
491 mctx = gaim_cipher_context_get_data(context); |
| 11329 | 492 |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
493 mctx->hash[0] = 0x67452301; |
| 11329 | 494 mctx->hash[1] = 0xefcdab89; |
| 495 mctx->hash[2] = 0x98badcfe; | |
| 496 mctx->hash[3] = 0x10325476; | |
| 497 mctx->byte_count = 0; | |
| 498 } | |
| 499 | |
| 500 static void | |
| 501 md4_append(GaimCipherContext *context, const guchar *data, size_t len) | |
| 502 { | |
| 503 struct MD4_Context *mctx = gaim_cipher_context_get_data(context); | |
| 504 const guint32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); | |
| 505 | |
| 506 mctx->byte_count += len; | |
| 507 | |
| 508 if (avail > len) { | |
| 509 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), | |
| 510 data, len); | |
| 511 return; | |
| 512 } | |
| 513 | |
| 514 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), | |
| 515 data, avail); | |
| 516 | |
| 517 md4_transform_helper(mctx); | |
| 518 data += avail; | |
| 519 len -= avail; | |
| 520 | |
| 521 while (len >= sizeof(mctx->block)) { | |
| 522 memcpy(mctx->block, data, sizeof(mctx->block)); | |
| 523 md4_transform_helper(mctx); | |
| 524 data += sizeof(mctx->block); | |
| 525 len -= sizeof(mctx->block); | |
| 526 } | |
| 527 | |
| 528 memcpy(mctx->block, data, len); | |
| 529 } | |
| 530 | |
| 531 static gboolean | |
| 532 md4_digest(GaimCipherContext *context, size_t in_len, guchar *out, | |
| 533 size_t *out_len) | |
| 534 { | |
| 535 struct MD4_Context *mctx = gaim_cipher_context_get_data(context); | |
| 536 const unsigned int offset = mctx->byte_count & 0x3f; | |
| 537 char *p = (char *)mctx->block + offset; | |
| 538 int padding = 56 - (offset + 1); | |
| 539 | |
| 540 | |
| 541 if(in_len<16) return FALSE; | |
| 542 if(out_len) *out_len = 16; | |
| 543 *p++ = 0x80; | |
| 544 if (padding < 0) { | |
| 545 memset(p, 0x00, padding + sizeof (guint64)); | |
| 546 md4_transform_helper(mctx); | |
| 547 p = (char *)mctx->block; | |
| 548 padding = 56; | |
| 549 } | |
| 550 | |
| 551 memset(p, 0, padding); | |
| 552 mctx->block[14] = mctx->byte_count << 3; | |
| 553 mctx->block[15] = mctx->byte_count >> 29; | |
| 554 le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - | |
| 555 sizeof(guint64)) / sizeof(guint32)); | |
| 556 md4_transform(mctx->hash, mctx->block); | |
| 557 cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(guint32)); | |
| 558 memcpy(out, mctx->hash, sizeof(mctx->hash)); | |
| 559 memset(mctx, 0, sizeof(*mctx)); | |
| 560 return TRUE; | |
| 561 } | |
| 562 | |
| 563 static void | |
| 564 md4_uninit(GaimCipherContext *context) { | |
| 565 struct MD4_Context *md4_context; | |
| 566 | |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
567 gaim_cipher_context_reset(context, NULL); |
| 11329 | 568 |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
569 md4_context = gaim_cipher_context_get_data(context); |
| 11329 | 570 memset(md4_context, 0, sizeof(md4_context)); |
| 571 | |
| 572 g_free(md4_context); | |
| 573 md4_context = NULL; | |
| 574 } | |
| 575 | |
| 576 static GaimCipherOps MD4Ops = { | |
| 577 NULL, /* Set option */ | |
| 578 NULL, /* Get option */ | |
| 579 md4_init, /* init */ | |
| 580 md4_reset, /* reset */ | |
| 581 md4_uninit, /* uninit */ | |
| 582 NULL, /* set iv */ | |
| 583 md4_append, /* append */ | |
| 584 md4_digest, /* digest */ | |
| 585 NULL, /* encrypt */ | |
| 586 NULL, /* decrypt */ | |
| 587 NULL, /* set salt */ | |
| 588 NULL, /* get salt size */ | |
| 589 NULL, /* set key */ | |
| 590 NULL /* get key size */ | |
| 591 }; | |
| 592 | |
| 11335 | 593 /****************************************************************************** |
| 594 * DES | |
| 595 *****************************************************************************/ | |
| 596 | |
| 597 typedef struct _des_ctx | |
| 598 { | |
| 599 guint32 encrypt_subkeys[32]; | |
| 600 guint32 decrypt_subkeys[32]; | |
| 601 } des_ctx[1]; | |
| 602 | |
| 603 /* | |
| 604 * The s-box values are permuted according to the 'primitive function P' | |
| 605 */ | |
| 606 static guint32 sbox1[64] = | |
| 607 { | |
| 608 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, | |
| 609 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, | |
| 610 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, | |
| 611 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, | |
| 612 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, | |
| 613 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, | |
| 614 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, | |
| 615 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002 | |
| 616 }; | |
| 617 | |
| 618 static guint32 sbox2[64] = | |
| 619 { | |
| 620 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, | |
| 621 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, | |
| 622 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, | |
| 623 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, | |
| 624 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, | |
| 625 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, | |
| 626 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, | |
| 627 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000 | |
| 628 }; | |
| 629 | |
| 630 static guint32 sbox3[64] = | |
| 631 { | |
| 632 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, | |
| 633 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, | |
| 634 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, | |
| 635 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, | |
| 636 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, | |
| 637 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, | |
| 638 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, | |
| 639 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100 | |
| 640 }; | |
| 641 | |
| 642 static guint32 sbox4[64] = | |
| 643 { | |
| 644 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, | |
| 645 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, | |
| 646 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, | |
| 647 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, | |
| 648 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, | |
| 649 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, | |
| 650 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, | |
| 651 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040 | |
| 652 }; | |
| 653 | |
| 654 static guint32 sbox5[64] = | |
| 655 { | |
| 656 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, | |
| 657 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, | |
| 658 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, | |
| 659 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, | |
| 660 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, | |
| 661 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, | |
| 662 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, | |
| 663 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080 | |
| 664 }; | |
| 665 | |
| 666 static guint32 sbox6[64] = | |
| 667 { | |
| 668 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, | |
| 669 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, | |
| 670 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, | |
| 671 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, | |
| 672 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, | |
| 673 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, | |
| 674 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, | |
| 675 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008 | |
| 676 }; | |
| 677 | |
| 678 static guint32 sbox7[64] = | |
| 679 { | |
| 680 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, | |
| 681 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, | |
| 682 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, | |
| 683 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, | |
| 684 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, | |
| 685 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, | |
| 686 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, | |
| 687 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001 | |
| 688 }; | |
| 689 | |
| 690 static guint32 sbox8[64] = | |
| 691 { | |
| 692 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, | |
| 693 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, | |
| 694 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, | |
| 695 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, | |
| 696 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, | |
| 697 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, | |
| 698 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, | |
| 699 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800 | |
| 700 }; | |
| 701 | |
| 702 | |
| 703 | |
| 704 /* | |
| 705 * * These two tables are part of the 'permuted choice 1' function. | |
| 706 * * In this implementation several speed improvements are done. | |
| 707 * */ | |
| 11677 | 708 static guint32 leftkey_swap[16] = |
| 11335 | 709 { |
| 710 0x00000000, 0x00000001, 0x00000100, 0x00000101, | |
| 711 0x00010000, 0x00010001, 0x00010100, 0x00010101, | |
| 712 0x01000000, 0x01000001, 0x01000100, 0x01000101, | |
| 713 0x01010000, 0x01010001, 0x01010100, 0x01010101 | |
| 714 }; | |
| 715 | |
| 11677 | 716 static guint32 rightkey_swap[16] = |
| 11335 | 717 { |
| 718 0x00000000, 0x01000000, 0x00010000, 0x01010000, | |
| 719 0x00000100, 0x01000100, 0x00010100, 0x01010100, | |
| 720 0x00000001, 0x01000001, 0x00010001, 0x01010001, | |
| 721 0x00000101, 0x01000101, 0x00010101, 0x01010101, | |
| 722 }; | |
| 723 | |
| 724 | |
| 725 | |
| 726 /* | |
| 727 * Numbers of left shifts per round for encryption subkey schedule | |
| 728 * To calculate the decryption key scheduling we just reverse the | |
| 729 * ordering of the subkeys so we can omit the table for decryption | |
| 730 * subkey schedule. | |
| 731 */ | |
| 732 static guint8 encrypt_rotate_tab[16] = | |
| 733 { | |
| 734 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 | |
| 735 }; | |
| 736 | |
| 737 /* | |
| 738 * Macro to swap bits across two words | |
| 739 **/ | |
| 740 #define DO_PERMUTATION(a, temp, b, offset, mask) \ | |
| 741 temp = ((a>>offset) ^ b) & mask; \ | |
| 742 b ^= temp; \ | |
| 743 a ^= temp<<offset; | |
| 744 | |
| 745 | |
| 746 /* | |
| 747 * This performs the 'initial permutation' for the data to be encrypted or decrypted | |
| 748 **/ | |
| 749 #define INITIAL_PERMUTATION(left, temp, right) \ | |
| 750 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \ | |
| 751 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ | |
| 752 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ | |
| 753 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ | |
| 754 DO_PERMUTATION(left, temp, right, 1, 0x55555555) | |
| 755 | |
| 756 | |
| 757 /* | |
| 758 * The 'inverse initial permutation' | |
| 759 **/ | |
| 760 #define FINAL_PERMUTATION(left, temp, right) \ | |
| 761 DO_PERMUTATION(left, temp, right, 1, 0x55555555) \ | |
| 762 DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ | |
| 763 DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ | |
| 764 DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ | |
| 765 DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) | |
| 766 | |
| 767 | |
| 768 /* | |
| 769 * A full DES round including 'expansion function', 'sbox substitution' | |
| 770 * and 'primitive function P' but without swapping the left and right word. | |
| 771 **/ | |
| 772 #define DES_ROUND(from, to, work, subkey) \ | |
| 773 work = ((from<<1) | (from>>31)) ^ *subkey++; \ | |
| 774 to ^= sbox8[ work & 0x3f ]; \ | |
| 775 to ^= sbox6[ (work>>8) & 0x3f ]; \ | |
| 776 to ^= sbox4[ (work>>16) & 0x3f ]; \ | |
| 777 to ^= sbox2[ (work>>24) & 0x3f ]; \ | |
| 778 work = ((from>>3) | (from<<29)) ^ *subkey++; \ | |
| 779 to ^= sbox7[ work & 0x3f ]; \ | |
| 780 to ^= sbox5[ (work>>8) & 0x3f ]; \ | |
| 781 to ^= sbox3[ (work>>16) & 0x3f ]; \ | |
| 782 to ^= sbox1[ (work>>24) & 0x3f ]; | |
| 783 | |
| 784 | |
| 785 /* | |
| 786 * Macros to convert 8 bytes from/to 32bit words | |
| 787 **/ | |
| 788 #define READ_64BIT_DATA(data, left, right) \ | |
| 789 left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ | |
| 790 right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; | |
| 791 | |
| 792 #define WRITE_64BIT_DATA(data, left, right) \ | |
| 793 data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ | |
| 794 data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ | |
| 795 data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ | |
| 796 data[6] = (right >> 8) &0xff; data[7] = right &0xff; | |
| 797 | |
| 798 | |
| 799 | |
| 800 | |
| 801 | |
| 802 | |
| 803 /* | |
| 804 * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for | |
| 805 * 16 encryption rounds. | |
| 806 * To calculate subkeys for decryption the caller | |
| 807 * have to reorder the generated subkeys. | |
| 808 * | |
| 809 * rawkey: 8 Bytes of key data | |
| 810 * subkey: Array of at least 32 guint32s. Will be filled | |
| 811 * with calculated subkeys. | |
| 812 * | |
| 813 **/ | |
| 11597 | 814 static void |
| 11335 | 815 des_key_schedule (const guint8 * rawkey, guint32 * subkey) |
| 816 { | |
| 817 guint32 left, right, work; | |
| 818 int round; | |
| 819 | |
| 820 READ_64BIT_DATA (rawkey, left, right) | |
| 821 | |
| 822 DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) | |
| 823 DO_PERMUTATION (right, work, left, 0, 0x10101010) | |
| 824 | |
| 825 left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) | |
| 826 | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) | |
| 827 | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) | |
| 828 | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4); | |
| 829 | |
| 830 left &= 0x0fffffff; | |
| 831 | |
| 832 right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) | |
| 833 | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) | |
| 834 | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) | |
| 835 | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4); | |
| 836 | |
| 837 right &= 0x0fffffff; | |
| 838 | |
| 839 for (round = 0; round < 16; ++round) | |
| 840 { | |
| 841 left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; | |
| 842 right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; | |
| 843 | |
| 844 *subkey++ = ((left << 4) & 0x24000000) | |
| 845 | ((left << 28) & 0x10000000) | |
| 846 | ((left << 14) & 0x08000000) | |
| 847 | ((left << 18) & 0x02080000) | |
| 848 | ((left << 6) & 0x01000000) | |
| 849 | ((left << 9) & 0x00200000) | |
| 850 | ((left >> 1) & 0x00100000) | |
| 851 | ((left << 10) & 0x00040000) | |
| 852 | ((left << 2) & 0x00020000) | |
| 853 | ((left >> 10) & 0x00010000) | |
| 854 | ((right >> 13) & 0x00002000) | |
| 855 | ((right >> 4) & 0x00001000) | |
| 856 | ((right << 6) & 0x00000800) | |
| 857 | ((right >> 1) & 0x00000400) | |
| 858 | ((right >> 14) & 0x00000200) | |
| 859 | (right & 0x00000100) | |
| 860 | ((right >> 5) & 0x00000020) | |
| 861 | ((right >> 10) & 0x00000010) | |
| 862 | ((right >> 3) & 0x00000008) | |
| 863 | ((right >> 18) & 0x00000004) | |
| 864 | ((right >> 26) & 0x00000002) | |
| 865 | ((right >> 24) & 0x00000001); | |
| 866 | |
| 867 *subkey++ = ((left << 15) & 0x20000000) | |
| 868 | ((left << 17) & 0x10000000) | |
| 869 | ((left << 10) & 0x08000000) | |
| 870 | ((left << 22) & 0x04000000) | |
| 871 | ((left >> 2) & 0x02000000) | |
| 872 | ((left << 1) & 0x01000000) | |
| 873 | ((left << 16) & 0x00200000) | |
| 874 | ((left << 11) & 0x00100000) | |
| 875 | ((left << 3) & 0x00080000) | |
| 876 | ((left >> 6) & 0x00040000) | |
| 877 | ((left << 15) & 0x00020000) | |
| 878 | ((left >> 4) & 0x00010000) | |
| 879 | ((right >> 2) & 0x00002000) | |
| 880 | ((right << 8) & 0x00001000) | |
| 881 | ((right >> 14) & 0x00000808) | |
| 882 | ((right >> 9) & 0x00000400) | |
| 883 | ((right) & 0x00000200) | |
| 884 | ((right << 7) & 0x00000100) | |
| 885 | ((right >> 7) & 0x00000020) | |
| 886 | ((right >> 3) & 0x00000011) | |
| 887 | ((right << 2) & 0x00000004) | |
| 888 | ((right >> 21) & 0x00000002); | |
| 889 } | |
| 890 } | |
| 891 | |
| 892 | |
| 893 | |
| 894 /* | |
| 895 * Fill a DES context with subkeys calculated from a 64bit key. | |
| 896 * Does not check parity bits, but simply ignore them. | |
| 897 * Does not check for weak keys. | |
| 898 **/ | |
| 11597 | 899 static void |
| 900 des_set_key (GaimCipherContext *context, guchar * key) | |
| 11335 | 901 { |
| 902 struct _des_ctx *ctx = gaim_cipher_context_get_data(context); | |
| 903 int i; | |
| 904 | |
| 905 des_key_schedule (key, ctx->encrypt_subkeys); | |
| 906 | |
| 907 for(i=0; i<32; i+=2) | |
| 908 { | |
| 909 ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; | |
| 910 ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; | |
| 911 } | |
| 912 } | |
| 913 | |
| 914 | |
| 915 | |
| 916 /* | |
| 917 * Electronic Codebook Mode DES encryption/decryption of data according | |
| 918 * to 'mode'. | |
| 919 **/ | |
| 11597 | 920 static int |
| 11335 | 921 des_ecb_crypt (struct _des_ctx *ctx, const guint8 * from, guint8 * to, int mode) |
| 922 { | |
| 923 guint32 left, right, work; | |
| 924 guint32 *keys; | |
| 925 | |
| 926 keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; | |
| 927 | |
| 928 READ_64BIT_DATA (from, left, right) | |
| 929 INITIAL_PERMUTATION (left, work, right) | |
| 930 | |
| 931 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 932 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 933 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 934 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 935 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 936 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 937 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 938 DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) | |
| 939 | |
| 940 FINAL_PERMUTATION (right, work, left) | |
| 941 WRITE_64BIT_DATA (to, right, left) | |
| 942 | |
| 943 return 0; | |
| 944 } | |
| 945 | |
| 11597 | 946 static gint |
| 947 des_encrypt(GaimCipherContext *context, const guchar data[], | |
| 948 size_t len, guchar output[], size_t *outlen) { | |
| 11335 | 949 int offset = 0; |
| 950 int i = 0; | |
| 951 int tmp; | |
| 952 guint8 buf[8] = {0,0,0,0,0,0,0,0}; | |
| 953 while(offset+8<=len) { | |
| 954 des_ecb_crypt(gaim_cipher_context_get_data(context), | |
| 955 data+offset, | |
| 956 output+offset, | |
| 957 0); | |
| 958 offset+=8; | |
| 959 } | |
| 960 *outlen = len; | |
| 961 if(offset<len) { | |
| 962 *outlen += len - offset; | |
| 963 tmp = offset; | |
| 964 while(tmp<len) { | |
| 965 buf[i++] = data[tmp]; | |
| 966 tmp++; | |
| 967 } | |
| 968 des_ecb_crypt(gaim_cipher_context_get_data(context), | |
| 969 buf, | |
| 970 output+offset, | |
| 971 0); | |
| 972 } | |
| 973 return 0; | |
| 974 } | |
| 975 | |
| 976 static void | |
| 977 des_init(GaimCipherContext *context, gpointer extra) { | |
| 978 struct _des_ctx *mctx; | |
| 979 mctx = g_new0(struct _des_ctx, 1); | |
| 980 gaim_cipher_context_set_data(context, mctx); | |
| 981 } | |
| 982 | |
| 983 static void | |
| 984 des_uninit(GaimCipherContext *context) { | |
| 985 struct _des_ctx *des_context; | |
| 986 | |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
987 des_context = gaim_cipher_context_get_data(context); |
| 11335 | 988 memset(des_context, 0, sizeof(des_context)); |
| 989 | |
| 990 g_free(des_context); | |
| 991 des_context = NULL; | |
| 992 } | |
| 993 | |
| 994 static GaimCipherOps DESOps = { | |
| 995 NULL, /* Set option */ | |
| 996 NULL, /* Get option */ | |
| 997 des_init, /* init */ | |
| 998 NULL, /* reset */ | |
| 999 des_uninit, /* uninit */ | |
| 1000 NULL, /* set iv */ | |
| 1001 NULL, /* append */ | |
| 1002 NULL, /* digest */ | |
| 1003 des_encrypt, /* encrypt */ | |
| 1004 NULL, /* decrypt */ | |
| 1005 NULL, /* set salt */ | |
| 1006 NULL, /* get salt size */ | |
| 11597 | 1007 des_set_key, /* set key */ |
| 11335 | 1008 NULL /* get key size */ |
| 1009 }; | |
| 1010 | |
| 1011 | |
| 11329 | 1012 /******************************************************************************* |
| 10684 | 1013 * SHA-1 |
| 1014 ******************************************************************************/ | |
| 1015 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) | |
| 1016 | |
| 1017 struct SHA1Context { | |
| 1018 guint32 H[5]; | |
| 1019 guint32 W[80]; | |
| 1020 | |
|
13218
c01aa6ea4947
[gaim-migrate @ 15582]
Richard Laager <rlaager@wiktel.com>
parents:
12389
diff
changeset
|
1021 gint lenW; |
| 10684 | 1022 |
| 1023 guint32 sizeHi; | |
| 1024 guint32 sizeLo; | |
| 1025 }; | |
| 1026 | |
| 1027 static void | |
| 1028 sha1_hash_block(struct SHA1Context *sha1_ctx) { | |
| 1029 gint i; | |
| 1030 guint32 A, B, C, D, E, T; | |
| 1031 | |
| 1032 for(i = 16; i < 80; i++) { | |
| 1033 sha1_ctx->W[i] = SHA1_ROTL(sha1_ctx->W[i - 3] ^ | |
| 1034 sha1_ctx->W[i - 8] ^ | |
| 1035 sha1_ctx->W[i - 14] ^ | |
| 1036 sha1_ctx->W[i - 16], 1); | |
| 1037 } | |
| 1038 | |
| 1039 A = sha1_ctx->H[0]; | |
| 1040 B = sha1_ctx->H[1]; | |
| 1041 C = sha1_ctx->H[2]; | |
| 1042 D = sha1_ctx->H[3]; | |
| 1043 E = sha1_ctx->H[4]; | |
| 1044 | |
| 1045 for(i = 0; i < 20; i++) { | |
| 1046 T = (SHA1_ROTL(A, 5) + (((C ^ D) & B) ^ D) + E + sha1_ctx->W[i] + 0x5A827999) & 0xFFFFFFFF; | |
| 1047 E = D; | |
| 1048 D = C; | |
| 1049 C = SHA1_ROTL(B, 30); | |
| 1050 B = A; | |
| 1051 A = T; | |
| 1052 } | |
| 1053 | |
| 1054 for(i = 20; i < 40; i++) { | |
| 1055 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0x6ED9EBA1) & 0xFFFFFFFF; | |
| 1056 E = D; | |
| 1057 D = C; | |
| 1058 C = SHA1_ROTL(B, 30); | |
| 1059 B = A; | |
| 1060 A = T; | |
| 1061 } | |
| 1062 | |
| 1063 for(i = 40; i < 60; i++) { | |
| 1064 T = (SHA1_ROTL(A, 5) + ((B & C) | (D & (B | C))) + E + sha1_ctx->W[i] + 0x8F1BBCDC) & 0xFFFFFFFF; | |
| 1065 E = D; | |
| 1066 D = C; | |
| 1067 C = SHA1_ROTL(B, 30); | |
| 1068 B = A; | |
| 1069 A = T; | |
| 1070 } | |
| 1071 | |
| 1072 for(i = 60; i < 80; i++) { | |
| 1073 T = (SHA1_ROTL(A, 5) + (B ^ C ^ D) + E + sha1_ctx->W[i] + 0xCA62C1D6) & 0xFFFFFFFF; | |
| 1074 E = D; | |
| 1075 D = C; | |
| 1076 C = SHA1_ROTL(B, 30); | |
| 1077 B = A; | |
| 1078 A = T; | |
| 1079 } | |
| 1080 | |
| 1081 sha1_ctx->H[0] += A; | |
| 1082 sha1_ctx->H[1] += B; | |
| 1083 sha1_ctx->H[2] += C; | |
| 1084 sha1_ctx->H[3] += D; | |
| 11183 | 1085 sha1_ctx->H[4] += E; |
| 10684 | 1086 } |
| 1087 | |
| 1088 static void | |
| 1089 sha1_set_opt(GaimCipherContext *context, const gchar *name, void *value) { | |
| 1090 struct SHA1Context *ctx; | |
| 1091 | |
| 1092 ctx = gaim_cipher_context_get_data(context); | |
| 1093 | |
| 1094 if(!strcmp(name, "sizeHi")) { | |
| 1095 ctx->sizeHi = GPOINTER_TO_INT(value); | |
| 1096 } else if(!strcmp(name, "sizeLo")) { | |
| 1097 ctx->sizeLo = GPOINTER_TO_INT(value); | |
| 1098 } else if(!strcmp(name, "lenW")) { | |
| 1099 ctx->lenW = GPOINTER_TO_INT(value); | |
| 1100 } | |
| 1101 } | |
| 1102 | |
| 1103 static void * | |
| 1104 sha1_get_opt(GaimCipherContext *context, const gchar *name) { | |
| 1105 struct SHA1Context *ctx; | |
| 1106 | |
| 1107 ctx = gaim_cipher_context_get_data(context); | |
| 1108 | |
| 1109 if(!strcmp(name, "sizeHi")) { | |
| 1110 return GINT_TO_POINTER(ctx->sizeHi); | |
| 1111 } else if(!strcmp(name, "sizeLo")) { | |
| 1112 return GINT_TO_POINTER(ctx->sizeLo); | |
| 1113 } else if(!strcmp(name, "lenW")) { | |
| 1114 return GINT_TO_POINTER(ctx->lenW); | |
| 1115 } | |
| 1116 | |
| 1117 return NULL; | |
| 1118 } | |
| 1119 | |
| 1120 static void | |
| 1121 sha1_init(GaimCipherContext *context, void *extra) { | |
| 1122 struct SHA1Context *sha1_ctx; | |
| 1123 | |
| 1124 sha1_ctx = g_new0(struct SHA1Context, 1); | |
| 1125 | |
| 1126 gaim_cipher_context_set_data(context, sha1_ctx); | |
| 1127 | |
| 1128 gaim_cipher_context_reset(context, extra); | |
| 1129 } | |
| 1130 | |
| 1131 static void | |
| 1132 sha1_reset(GaimCipherContext *context, void *extra) { | |
| 1133 struct SHA1Context *sha1_ctx; | |
| 1134 gint i; | |
| 1135 | |
| 1136 sha1_ctx = gaim_cipher_context_get_data(context); | |
| 1137 | |
| 1138 g_return_if_fail(sha1_ctx); | |
| 1139 | |
| 1140 sha1_ctx->lenW = 0; | |
| 1141 sha1_ctx->sizeHi = 0; | |
| 1142 sha1_ctx->sizeLo = 0; | |
| 1143 | |
| 1144 sha1_ctx->H[0] = 0x67452301; | |
| 1145 sha1_ctx->H[1] = 0xEFCDAB89; | |
| 1146 sha1_ctx->H[2] = 0x98BADCFE; | |
| 1147 sha1_ctx->H[3] = 0x10325476; | |
| 1148 sha1_ctx->H[4] = 0xC3D2E1F0; | |
| 1149 | |
| 1150 for(i = 0; i < 80; i++) | |
| 1151 sha1_ctx->W[i] = 0; | |
| 1152 } | |
| 1153 | |
| 1154 static void | |
| 1155 sha1_uninit(GaimCipherContext *context) { | |
| 1156 struct SHA1Context *sha1_ctx; | |
| 1157 | |
| 1158 gaim_cipher_context_reset(context, NULL); | |
| 1159 | |
| 1160 sha1_ctx = gaim_cipher_context_get_data(context); | |
| 1161 | |
| 1162 memset(sha1_ctx, 0, sizeof(struct SHA1Context)); | |
| 1163 | |
| 1164 g_free(sha1_ctx); | |
| 1165 sha1_ctx = NULL; | |
| 1166 } | |
| 1167 | |
| 1168 | |
| 1169 static void | |
| 11183 | 1170 sha1_append(GaimCipherContext *context, const guchar *data, size_t len) { |
| 10684 | 1171 struct SHA1Context *sha1_ctx; |
| 1172 gint i; | |
| 1173 | |
| 1174 sha1_ctx = gaim_cipher_context_get_data(context); | |
| 1175 | |
| 1176 g_return_if_fail(sha1_ctx); | |
| 1177 | |
| 1178 for(i = 0; i < len; i++) { | |
| 1179 sha1_ctx->W[sha1_ctx->lenW / 4] <<= 8; | |
| 1180 sha1_ctx->W[sha1_ctx->lenW / 4] |= data[i]; | |
| 1181 | |
| 1182 if((++sha1_ctx->lenW) % 64 == 0) { | |
| 1183 sha1_hash_block(sha1_ctx); | |
| 1184 sha1_ctx->lenW = 0; | |
| 1185 } | |
| 1186 | |
| 1187 sha1_ctx->sizeLo += 8; | |
| 1188 sha1_ctx->sizeHi += (sha1_ctx->sizeLo < 8); | |
| 1189 } | |
| 1190 } | |
| 1191 | |
| 1192 static gboolean | |
| 11183 | 1193 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
|
1194 size_t *out_len) |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1195 { |
| 10684 | 1196 struct SHA1Context *sha1_ctx; |
| 11183 | 1197 guchar pad0x80 = 0x80, pad0x00 = 0x00; |
| 1198 guchar padlen[8]; | |
| 10684 | 1199 gint i; |
| 1200 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1201 g_return_val_if_fail(in_len >= 20, FALSE); |
| 10684 | 1202 |
| 1203 sha1_ctx = gaim_cipher_context_get_data(context); | |
| 1204 | |
| 1205 g_return_val_if_fail(sha1_ctx, FALSE); | |
| 1206 | |
| 11183 | 1207 padlen[0] = (guchar)((sha1_ctx->sizeHi >> 24) & 255); |
| 1208 padlen[1] = (guchar)((sha1_ctx->sizeHi >> 16) & 255); | |
| 1209 padlen[2] = (guchar)((sha1_ctx->sizeHi >> 8) & 255); | |
| 1210 padlen[3] = (guchar)((sha1_ctx->sizeHi >> 0) & 255); | |
| 1211 padlen[4] = (guchar)((sha1_ctx->sizeLo >> 24) & 255); | |
| 1212 padlen[5] = (guchar)((sha1_ctx->sizeLo >> 16) & 255); | |
| 1213 padlen[6] = (guchar)((sha1_ctx->sizeLo >> 8) & 255); | |
| 1214 padlen[7] = (guchar)((sha1_ctx->sizeLo >> 0) & 255); | |
| 10684 | 1215 |
| 1216 /* pad with a 1, then zeroes, then length */ | |
| 1217 gaim_cipher_context_append(context, &pad0x80, 1); | |
| 1218 while(sha1_ctx->lenW != 56) | |
| 1219 gaim_cipher_context_append(context, &pad0x00, 1); | |
| 1220 gaim_cipher_context_append(context, padlen, 8); | |
| 1221 | |
| 1222 for(i = 0; i < 20; i++) { | |
| 11183 | 1223 digest[i] = (guchar)(sha1_ctx->H[i / 4] >> 24); |
| 10684 | 1224 sha1_ctx->H[i / 4] <<= 8; |
| 1225 } | |
| 1226 | |
| 1227 gaim_cipher_context_reset(context, NULL); | |
| 1228 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1229 if(out_len) |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1230 *out_len = 20; |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1231 |
| 10684 | 1232 return TRUE; |
| 1233 } | |
| 1234 | |
| 1235 static GaimCipherOps SHA1Ops = { | |
| 1236 sha1_set_opt, /* Set Option */ | |
| 1237 sha1_get_opt, /* Get Option */ | |
| 1238 sha1_init, /* init */ | |
| 1239 sha1_reset, /* reset */ | |
| 1240 sha1_uninit, /* uninit */ | |
| 1241 NULL, /* set iv */ | |
| 1242 sha1_append, /* append */ | |
| 1243 sha1_digest, /* digest */ | |
| 1244 NULL, /* encrypt */ | |
| 1245 NULL, /* decrypt */ | |
| 1246 NULL, /* set salt */ | |
| 1247 NULL, /* get salt size */ | |
| 1248 NULL, /* set key */ | |
| 1249 NULL /* get key size */ | |
| 1250 }; | |
| 1251 | |
| 1252 /******************************************************************************* | |
| 1253 * Structs | |
| 1254 ******************************************************************************/ | |
| 1255 struct _GaimCipher { | |
| 1256 gchar *name; | |
| 1257 GaimCipherOps *ops; | |
| 1258 guint ref; | |
| 1259 }; | |
| 1260 | |
| 1261 struct _GaimCipherContext { | |
| 1262 GaimCipher *cipher; | |
| 1263 gpointer data; | |
| 1264 }; | |
| 1265 | |
| 1266 /****************************************************************************** | |
| 1267 * Globals | |
| 1268 *****************************************************************************/ | |
| 1269 static GList *ciphers = NULL; | |
| 1270 | |
| 1271 /****************************************************************************** | |
| 1272 * GaimCipher API | |
| 1273 *****************************************************************************/ | |
| 1274 const gchar * | |
| 1275 gaim_cipher_get_name(GaimCipher *cipher) { | |
| 1276 g_return_val_if_fail(cipher, NULL); | |
| 1277 | |
| 1278 return cipher->name; | |
| 1279 } | |
| 1280 | |
| 1281 guint | |
| 1282 gaim_cipher_get_capabilities(GaimCipher *cipher) { | |
| 1283 GaimCipherOps *ops = NULL; | |
| 1284 guint caps = 0; | |
| 1285 | |
| 1286 g_return_val_if_fail(cipher, 0); | |
| 1287 | |
| 1288 ops = cipher->ops; | |
| 1289 g_return_val_if_fail(ops, 0); | |
| 1290 | |
| 1291 if(ops->set_option) | |
| 1292 caps |= GAIM_CIPHER_CAPS_SET_OPT; | |
| 1293 if(ops->get_option) | |
| 1294 caps |= GAIM_CIPHER_CAPS_GET_OPT; | |
| 1295 if(ops->init) | |
| 1296 caps |= GAIM_CIPHER_CAPS_INIT; | |
| 1297 if(ops->reset) | |
| 1298 caps |= GAIM_CIPHER_CAPS_RESET; | |
| 1299 if(ops->uninit) | |
| 1300 caps |= GAIM_CIPHER_CAPS_UNINIT; | |
| 1301 if(ops->set_iv) | |
| 1302 caps |= GAIM_CIPHER_CAPS_SET_IV; | |
| 1303 if(ops->append) | |
| 1304 caps |= GAIM_CIPHER_CAPS_APPEND; | |
| 1305 if(ops->digest) | |
| 1306 caps |= GAIM_CIPHER_CAPS_DIGEST; | |
| 1307 if(ops->encrypt) | |
| 1308 caps |= GAIM_CIPHER_CAPS_ENCRYPT; | |
| 1309 if(ops->decrypt) | |
| 1310 caps |= GAIM_CIPHER_CAPS_DECRYPT; | |
| 1311 if(ops->set_salt) | |
| 1312 caps |= GAIM_CIPHER_CAPS_SET_SALT; | |
| 1313 if(ops->get_salt_size) | |
| 1314 caps |= GAIM_CIPHER_CAPS_GET_SALT_SIZE; | |
| 1315 if(ops->set_key) | |
| 1316 caps |= GAIM_CIPHER_CAPS_SET_KEY; | |
| 1317 if(ops->get_key_size) | |
| 1318 caps |= GAIM_CIPHER_CAPS_GET_KEY_SIZE; | |
| 1319 | |
| 1320 return caps; | |
| 1321 } | |
| 1322 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1323 gboolean |
| 11183 | 1324 gaim_cipher_digest_region(const gchar *name, const guchar *data, |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1325 size_t data_len, size_t in_len, |
| 11183 | 1326 guchar digest[], size_t *out_len) |
| 10684 | 1327 { |
| 1328 GaimCipher *cipher; | |
| 1329 GaimCipherContext *context; | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1330 gboolean ret = FALSE; |
| 10684 | 1331 |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1332 g_return_val_if_fail(name, FALSE); |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1333 g_return_val_if_fail(data, FALSE); |
| 10684 | 1334 |
| 1335 cipher = gaim_ciphers_find_cipher(name); | |
| 1336 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1337 g_return_val_if_fail(cipher, FALSE); |
| 10684 | 1338 |
| 1339 if(!cipher->ops->append || !cipher->ops->digest) { | |
| 1340 gaim_debug_info("cipher", "gaim_cipher_region failed: " | |
| 1341 "the %s cipher does not support appending and or " | |
| 1342 "digesting.", cipher->name); | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1343 return FALSE; |
| 10684 | 1344 } |
| 1345 | |
| 1346 context = gaim_cipher_context_new(cipher, NULL); | |
| 1347 gaim_cipher_context_append(context, data, data_len); | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1348 ret = gaim_cipher_context_digest(context, in_len, digest, out_len); |
| 11143 | 1349 gaim_cipher_context_destroy(context); |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1350 |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1351 return ret; |
| 10684 | 1352 } |
| 1353 | |
| 1354 /****************************************************************************** | |
| 1355 * GaimCiphers API | |
| 1356 *****************************************************************************/ | |
| 1357 GaimCipher * | |
| 1358 gaim_ciphers_find_cipher(const gchar *name) { | |
| 1359 GaimCipher *cipher; | |
| 1360 GList *l; | |
| 1361 | |
| 1362 g_return_val_if_fail(name, NULL); | |
| 1363 | |
| 1364 for(l = ciphers; l; l = l->next) { | |
| 1365 cipher = GAIM_CIPHER(l->data); | |
| 1366 | |
| 1367 if(!g_ascii_strcasecmp(cipher->name, name)) | |
| 1368 return cipher; | |
| 1369 } | |
| 1370 | |
| 1371 return NULL; | |
| 1372 } | |
| 1373 | |
| 1374 GaimCipher * | |
| 1375 gaim_ciphers_register_cipher(const gchar *name, GaimCipherOps *ops) { | |
| 1376 GaimCipher *cipher = NULL; | |
| 1377 | |
| 1378 g_return_val_if_fail(name, NULL); | |
| 1379 g_return_val_if_fail(ops, NULL); | |
| 1380 g_return_val_if_fail(!gaim_ciphers_find_cipher(name), NULL); | |
| 1381 | |
| 1382 cipher = g_new0(GaimCipher, 1); | |
| 1383 | |
| 1384 cipher->name = g_strdup(name); | |
| 1385 cipher->ops = ops; | |
| 1386 | |
| 1387 ciphers = g_list_append(ciphers, cipher); | |
| 1388 | |
| 1389 gaim_signal_emit(gaim_ciphers_get_handle(), "cipher-added", cipher); | |
| 1390 | |
| 1391 return cipher; | |
| 1392 } | |
| 1393 | |
| 1394 gboolean | |
| 1395 gaim_ciphers_unregister_cipher(GaimCipher *cipher) { | |
| 1396 g_return_val_if_fail(cipher, FALSE); | |
| 1397 g_return_val_if_fail(cipher->ref == 0, FALSE); | |
| 1398 | |
| 1399 gaim_signal_emit(gaim_ciphers_get_handle(), "cipher-removed", cipher); | |
| 1400 | |
| 1401 ciphers = g_list_remove(ciphers, cipher); | |
| 1402 | |
| 1403 g_free(cipher->name); | |
| 1404 g_free(cipher); | |
| 1405 | |
| 1406 return TRUE; | |
| 1407 } | |
| 1408 | |
| 1409 GList * | |
| 1410 gaim_ciphers_get_ciphers() { | |
| 1411 return ciphers; | |
| 1412 } | |
| 1413 | |
| 1414 /****************************************************************************** | |
| 1415 * GaimCipher Subsystem API | |
| 1416 *****************************************************************************/ | |
| 1417 gpointer | |
| 1418 gaim_ciphers_get_handle() { | |
| 1419 static gint handle; | |
| 1420 | |
| 1421 return &handle; | |
| 1422 } | |
| 1423 | |
| 1424 void | |
| 1425 gaim_ciphers_init() { | |
| 1426 gpointer handle; | |
| 1427 | |
| 1428 handle = gaim_ciphers_get_handle(); | |
| 1429 | |
| 1430 gaim_signal_register(handle, "cipher-added", | |
| 1431 gaim_marshal_VOID__POINTER, NULL, 1, | |
| 1432 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
| 1433 GAIM_SUBTYPE_CIPHER)); | |
| 1434 gaim_signal_register(handle, "cipher-removed", | |
| 1435 gaim_marshal_VOID__POINTER, NULL, 1, | |
| 1436 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
| 1437 GAIM_SUBTYPE_CIPHER)); | |
| 1438 | |
| 1439 gaim_ciphers_register_cipher("md5", &MD5Ops); | |
| 1440 gaim_ciphers_register_cipher("sha1", &SHA1Ops); | |
| 11329 | 1441 gaim_ciphers_register_cipher("md4", &MD4Ops); |
| 11335 | 1442 gaim_ciphers_register_cipher("des", &DESOps); |
| 10684 | 1443 } |
| 1444 | |
| 1445 void | |
| 1446 gaim_ciphers_uninit() { | |
| 1447 GaimCipher *cipher; | |
| 1448 GList *l, *ll; | |
| 1449 | |
| 1450 for(l = ciphers; l; l = ll) { | |
| 1451 ll = l->next; | |
| 1452 | |
| 1453 cipher = GAIM_CIPHER(l->data); | |
| 1454 gaim_ciphers_unregister_cipher(cipher); | |
| 1455 | |
| 1456 ciphers = g_list_remove(ciphers, cipher); | |
| 1457 } | |
| 1458 | |
| 1459 g_list_free(ciphers); | |
| 1460 | |
| 1461 gaim_signals_unregister_by_instance(gaim_ciphers_get_handle()); | |
| 1462 } | |
| 1463 /****************************************************************************** | |
| 1464 * GaimCipherContext API | |
| 1465 *****************************************************************************/ | |
| 1466 void | |
| 1467 gaim_cipher_context_set_option(GaimCipherContext *context, const gchar *name, | |
| 1468 gpointer value) | |
| 1469 { | |
| 1470 GaimCipher *cipher = NULL; | |
| 1471 | |
| 1472 g_return_if_fail(context); | |
| 1473 g_return_if_fail(name); | |
| 1474 | |
| 1475 cipher = context->cipher; | |
| 1476 g_return_if_fail(cipher); | |
| 1477 | |
| 1478 if(cipher->ops && cipher->ops->set_option) | |
| 1479 cipher->ops->set_option(context, name, value); | |
| 1480 else | |
| 1481 gaim_debug_info("cipher", "the %s cipher does not support the " | |
| 1482 "set_option operation\n", cipher->name); | |
| 1483 } | |
| 1484 | |
| 1485 gpointer | |
| 1486 gaim_cipher_context_get_option(GaimCipherContext *context, const gchar *name) { | |
| 1487 GaimCipher *cipher = NULL; | |
| 1488 | |
| 1489 g_return_val_if_fail(context, NULL); | |
| 1490 g_return_val_if_fail(name, NULL); | |
| 1491 | |
| 1492 cipher = context->cipher; | |
| 1493 g_return_val_if_fail(cipher, NULL); | |
| 1494 | |
| 1495 if(cipher->ops && cipher->ops->get_option) | |
| 1496 return cipher->ops->get_option(context, name); | |
| 1497 else { | |
| 1498 gaim_debug_info("cipher", "the %s cipher does not support the " | |
| 1499 "get_option operation\n", cipher->name); | |
| 1500 | |
| 1501 return NULL; | |
| 1502 } | |
| 1503 } | |
| 1504 | |
| 1505 GaimCipherContext * | |
| 1506 gaim_cipher_context_new(GaimCipher *cipher, void *extra) { | |
| 1507 GaimCipherContext *context = NULL; | |
| 1508 | |
| 1509 g_return_val_if_fail(cipher, NULL); | |
| 1510 | |
| 1511 cipher->ref++; | |
| 1512 | |
| 1513 context = g_new0(GaimCipherContext, 1); | |
| 1514 context->cipher = cipher; | |
| 1515 | |
| 1516 if(cipher->ops->init) | |
| 1517 cipher->ops->init(context, extra); | |
| 1518 | |
| 1519 return context; | |
| 1520 } | |
| 1521 | |
| 1522 GaimCipherContext * | |
| 1523 gaim_cipher_context_new_by_name(const gchar *name, void *extra) { | |
| 1524 GaimCipher *cipher; | |
| 1525 | |
| 1526 g_return_val_if_fail(name, NULL); | |
| 1527 | |
| 1528 cipher = gaim_ciphers_find_cipher(name); | |
| 1529 | |
| 1530 g_return_val_if_fail(cipher, NULL); | |
| 1531 | |
| 1532 return gaim_cipher_context_new(cipher, extra); | |
| 1533 } | |
| 1534 | |
| 1535 void | |
| 1536 gaim_cipher_context_reset(GaimCipherContext *context, void *extra) { | |
| 1537 GaimCipher *cipher = NULL; | |
| 1538 | |
| 1539 g_return_if_fail(context); | |
| 1540 | |
| 1541 cipher = context->cipher; | |
| 1542 g_return_if_fail(cipher); | |
| 1543 | |
| 1544 if(cipher->ops && cipher->ops->reset) | |
| 1545 context->cipher->ops->reset(context, extra); | |
| 1546 } | |
| 1547 | |
| 1548 void | |
| 1549 gaim_cipher_context_destroy(GaimCipherContext *context) { | |
| 1550 GaimCipher *cipher = NULL; | |
| 1551 | |
| 1552 g_return_if_fail(context); | |
| 1553 | |
| 1554 cipher = context->cipher; | |
| 1555 g_return_if_fail(cipher); | |
| 1556 | |
| 1557 cipher->ref--; | |
| 1558 | |
| 1559 if(cipher->ops && cipher->ops->uninit) | |
| 1560 cipher->ops->uninit(context); | |
| 1561 | |
| 1562 memset(context, 0, sizeof(context)); | |
| 1563 g_free(context); | |
| 1564 context = NULL; | |
| 1565 } | |
| 1566 | |
| 1567 void | |
| 11183 | 1568 gaim_cipher_context_set_iv(GaimCipherContext *context, guchar *iv, size_t len) |
| 10684 | 1569 { |
| 1570 GaimCipher *cipher = NULL; | |
| 1571 | |
| 1572 g_return_if_fail(context); | |
| 1573 g_return_if_fail(iv); | |
| 1574 | |
| 1575 cipher = context->cipher; | |
| 1576 g_return_if_fail(cipher); | |
| 1577 | |
| 1578 if(cipher->ops && cipher->ops->set_iv) | |
| 1579 cipher->ops->set_iv(context, iv, len); | |
| 1580 else | |
| 1581 gaim_debug_info("cipher", "the %s cipher does not support the set" | |
| 1582 "initialization vector operation\n", cipher->name); | |
| 1583 } | |
| 1584 | |
| 1585 void | |
| 11183 | 1586 gaim_cipher_context_append(GaimCipherContext *context, const guchar *data, |
| 10684 | 1587 size_t len) |
| 1588 { | |
| 1589 GaimCipher *cipher = NULL; | |
| 1590 | |
| 1591 g_return_if_fail(context); | |
| 1592 | |
| 1593 cipher = context->cipher; | |
| 1594 g_return_if_fail(cipher); | |
| 1595 | |
| 1596 if(cipher->ops && cipher->ops->append) | |
| 1597 cipher->ops->append(context, data, len); | |
| 1598 else | |
| 1599 gaim_debug_info("cipher", "the %s cipher does not support the append " | |
| 1600 "operation\n", cipher->name); | |
| 1601 } | |
| 1602 | |
| 1603 gboolean | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1604 gaim_cipher_context_digest(GaimCipherContext *context, size_t in_len, |
| 11183 | 1605 guchar digest[], size_t *out_len) |
| 10684 | 1606 { |
| 1607 GaimCipher *cipher = NULL; | |
| 1608 | |
| 1609 g_return_val_if_fail(context, FALSE); | |
| 1610 | |
| 1611 cipher = context->cipher; | |
| 1612 g_return_val_if_fail(context, FALSE); | |
| 1613 | |
| 1614 if(cipher->ops && cipher->ops->digest) | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1615 return cipher->ops->digest(context, in_len, digest, out_len); |
| 10684 | 1616 else { |
| 1617 gaim_debug_info("cipher", "the %s cipher does not support the digest " | |
| 1618 "operation\n", cipher->name); | |
| 1619 return FALSE; | |
| 1620 } | |
| 1621 } | |
| 1622 | |
| 1623 gboolean | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1624 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
|
1625 gchar digest_s[], size_t *out_len) |
| 10684 | 1626 { |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1627 /* 8k is a bit excessive, will tweak later. */ |
| 11183 | 1628 guchar digest[BUF_LEN * 4]; |
| 10684 | 1629 gint n = 0; |
| 1630 size_t dlen = 0; | |
| 1631 | |
| 1632 g_return_val_if_fail(context, FALSE); | |
| 1633 g_return_val_if_fail(digest_s, FALSE); | |
| 1634 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1635 if(!gaim_cipher_context_digest(context, sizeof(digest), digest, &dlen)) |
| 10684 | 1636 return FALSE; |
| 1637 | |
|
12388
4e045668b9d0
[gaim-migrate @ 14694]
Richard Laager <rlaager@wiktel.com>
parents:
12382
diff
changeset
|
1638 /* in_len must be greater than dlen * 2 so we have room for the NUL. */ |
|
4e045668b9d0
[gaim-migrate @ 14694]
Richard Laager <rlaager@wiktel.com>
parents:
12382
diff
changeset
|
1639 if(in_len <= dlen * 2) |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1640 return FALSE; |
| 10684 | 1641 |
| 1642 for(n = 0; n < dlen; n++) | |
| 1643 sprintf(digest_s + (n * 2), "%02x", digest[n]); | |
| 1644 | |
| 1645 digest_s[n * 2] = '\0'; | |
| 1646 | |
|
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1647 if(out_len) |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1648 *out_len = dlen * 2; |
|
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
1649 |
| 10684 | 1650 return TRUE; |
| 1651 } | |
| 1652 | |
| 1653 gint | |
| 11183 | 1654 gaim_cipher_context_encrypt(GaimCipherContext *context, const guchar data[], |
| 1655 size_t len, guchar output[], size_t *outlen) | |
| 10684 | 1656 { |
| 1657 GaimCipher *cipher = NULL; | |
| 1658 | |
| 1659 g_return_val_if_fail(context, -1); | |
| 1660 | |
| 1661 cipher = context->cipher; | |
| 1662 g_return_val_if_fail(cipher, -1); | |
| 1663 | |
| 1664 if(cipher->ops && cipher->ops->encrypt) | |
| 1665 return cipher->ops->encrypt(context, data, len, output, outlen); | |
| 1666 else { | |
| 1667 gaim_debug_info("cipher", "the %s cipher does not support the encrypt" | |
| 1668 "operation\n", cipher->name); | |
| 1669 | |
| 1670 if(outlen) | |
| 1671 *outlen = -1; | |
| 1672 | |
| 1673 return -1; | |
| 1674 } | |
| 1675 } | |
| 1676 | |
| 1677 gint | |
| 11183 | 1678 gaim_cipher_context_decrypt(GaimCipherContext *context, const guchar data[], |
| 1679 size_t len, guchar output[], size_t *outlen) | |
| 10684 | 1680 { |
| 1681 GaimCipher *cipher = NULL; | |
| 1682 | |
| 1683 g_return_val_if_fail(context, -1); | |
| 1684 | |
| 1685 cipher = context->cipher; | |
| 1686 g_return_val_if_fail(cipher, -1); | |
| 1687 | |
| 1688 if(cipher->ops && cipher->ops->decrypt) | |
| 1689 return cipher->ops->decrypt(context, data, len, output, outlen); | |
| 1690 else { | |
| 1691 gaim_debug_info("cipher", "the %s cipher does not support the decrypt" | |
| 1692 "operation\n", cipher->name); | |
| 1693 | |
| 1694 if(outlen) | |
| 1695 *outlen = -1; | |
| 1696 | |
| 1697 return -1; | |
| 1698 } | |
| 1699 } | |
| 1700 | |
| 1701 void | |
| 11183 | 1702 gaim_cipher_context_set_salt(GaimCipherContext *context, guchar *salt) { |
| 10684 | 1703 GaimCipher *cipher = NULL; |
| 1704 | |
| 1705 g_return_if_fail(context); | |
| 1706 | |
| 1707 cipher = context->cipher; | |
| 1708 g_return_if_fail(cipher); | |
| 1709 | |
| 1710 if(cipher->ops && cipher->ops->set_salt) | |
| 1711 cipher->ops->set_salt(context, salt); | |
| 1712 else | |
| 1713 gaim_debug_info("cipher", "the %s cipher does not support the " | |
| 1714 "set_salt operation\n", cipher->name); | |
| 1715 } | |
| 1716 | |
| 1717 size_t | |
| 1718 gaim_cipher_context_get_salt_size(GaimCipherContext *context) { | |
| 1719 GaimCipher *cipher = NULL; | |
| 1720 | |
| 1721 g_return_val_if_fail(context, -1); | |
| 1722 | |
| 1723 cipher = context->cipher; | |
| 1724 g_return_val_if_fail(cipher, -1); | |
| 1725 | |
| 1726 if(cipher->ops && cipher->ops->get_salt_size) | |
| 1727 return cipher->ops->get_salt_size(context); | |
| 1728 else { | |
| 1729 gaim_debug_info("cipher", "the %s cipher does not support the " | |
| 1730 "get_salt_size operation\n", cipher->name); | |
| 1731 | |
| 1732 return -1; | |
| 1733 } | |
| 1734 } | |
| 1735 | |
| 1736 void | |
| 11183 | 1737 gaim_cipher_context_set_key(GaimCipherContext *context, guchar *key) { |
| 10684 | 1738 GaimCipher *cipher = NULL; |
| 1739 | |
| 1740 g_return_if_fail(context); | |
| 1741 | |
| 1742 cipher = context->cipher; | |
| 1743 g_return_if_fail(cipher); | |
| 1744 | |
| 1745 if(cipher->ops && cipher->ops->set_key) | |
| 1746 cipher->ops->set_key(context, key); | |
| 1747 else | |
| 1748 gaim_debug_info("cipher", "the %s cipher does not support the " | |
| 1749 "set_key operation\n", cipher->name); | |
| 1750 } | |
| 1751 | |
| 1752 size_t | |
| 1753 gaim_cipher_context_get_key_size(GaimCipherContext *context) { | |
| 1754 GaimCipher *cipher = NULL; | |
| 1755 | |
| 1756 g_return_val_if_fail(context, -1); | |
| 1757 | |
| 1758 cipher = context->cipher; | |
| 1759 g_return_val_if_fail(cipher, -1); | |
| 1760 | |
| 1761 if(cipher->ops && cipher->ops->get_key_size) | |
| 1762 return cipher->ops->get_key_size(context); | |
| 1763 else { | |
| 1764 gaim_debug_info("cipher", "the %s cipher does not support the " | |
| 1765 "get_key_size operation\n", cipher->name); | |
| 1766 | |
| 1767 return -1; | |
| 1768 } | |
| 1769 } | |
| 1770 | |
| 1771 void | |
| 1772 gaim_cipher_context_set_data(GaimCipherContext *context, gpointer data) { | |
| 1773 g_return_if_fail(context); | |
| 1774 | |
| 1775 context->data = data; | |
| 1776 } | |
| 1777 | |
| 1778 gpointer | |
| 1779 gaim_cipher_context_get_data(GaimCipherContext *context) { | |
| 1780 g_return_val_if_fail(context, NULL); | |
| 1781 | |
| 1782 return context->data; | |
| 1783 } | |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1784 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1785 gchar *gaim_cipher_http_digest_calculate_session_key( |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1786 const gchar *algorithm, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1787 const gchar *username, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1788 const gchar *realm, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1789 const gchar *password, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1790 const gchar *nonce, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1791 const gchar *client_nonce) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1792 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1793 GaimCipher *cipher; |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1794 GaimCipherContext *context; |
|
12388
4e045668b9d0
[gaim-migrate @ 14694]
Richard Laager <rlaager@wiktel.com>
parents:
12382
diff
changeset
|
1795 gchar hash[33]; /* We only support MD5. */ |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1796 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1797 g_return_val_if_fail(username != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1798 g_return_val_if_fail(realm != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1799 g_return_val_if_fail(password != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1800 g_return_val_if_fail(nonce != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1801 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1802 /* Check for a supported algorithm. */ |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1803 g_return_val_if_fail(algorithm == NULL || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1804 *algorithm == '\0' || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1805 strcasecmp(algorithm, "MD5") || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1806 strcasecmp(algorithm, "MD5-sess"), NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1807 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1808 cipher = gaim_ciphers_find_cipher("md5"); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1809 g_return_val_if_fail(cipher != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1810 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1811 context = gaim_cipher_context_new(cipher, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1812 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1813 gaim_cipher_context_append(context, (guchar *)username, strlen(username)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1814 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1815 gaim_cipher_context_append(context, (guchar *)realm, strlen(realm)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1816 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1817 gaim_cipher_context_append(context, (guchar *)password, strlen(password)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1818 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1819 if (algorithm != NULL && !strcasecmp(algorithm, "MD5-sess")) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1820 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1821 guchar digest[16]; |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1822 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1823 if (client_nonce == NULL) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1824 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1825 gaim_cipher_context_destroy(context); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1826 gaim_debug_error("cipher", "Required client_nonce missing for MD5-sess digest calculation."); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1827 return NULL; |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1828 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1829 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1830 gaim_cipher_context_digest(context, sizeof(digest), digest, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1831 gaim_cipher_context_destroy(context); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1832 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1833 context = gaim_cipher_context_new(cipher, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1834 gaim_cipher_context_append(context, digest, sizeof(digest)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1835 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1836 gaim_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1837 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1838 gaim_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1839 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1840 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1841 gaim_cipher_context_digest_to_str(context, sizeof(hash), hash, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1842 gaim_cipher_context_destroy(context); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1843 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1844 return g_strdup(hash); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1845 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1846 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1847 gchar *gaim_cipher_http_digest_calculate_response( |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1848 const gchar *algorithm, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1849 const gchar *method, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1850 const gchar *digest_uri, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1851 const gchar *qop, |
|
12389
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1852 const gchar *entity, |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1853 const gchar *nonce, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1854 const gchar *nonce_count, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1855 const gchar *client_nonce, |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1856 const gchar *session_key) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1857 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1858 GaimCipher *cipher; |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1859 GaimCipherContext *context; |
|
12388
4e045668b9d0
[gaim-migrate @ 14694]
Richard Laager <rlaager@wiktel.com>
parents:
12382
diff
changeset
|
1860 static gchar hash2[33]; /* We only support MD5. */ |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1861 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1862 g_return_val_if_fail(method != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1863 g_return_val_if_fail(digest_uri != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1864 g_return_val_if_fail(nonce != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1865 g_return_val_if_fail(session_key != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1866 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1867 /* Check for a supported algorithm. */ |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1868 g_return_val_if_fail(algorithm == NULL || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1869 *algorithm == '\0' || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1870 strcasecmp(algorithm, "MD5") || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1871 strcasecmp(algorithm, "MD5-sess"), NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1872 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1873 /* Check for a supported "quality of protection". */ |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1874 g_return_val_if_fail(qop == NULL || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1875 *qop == '\0' || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1876 strcasecmp(qop, "auth") || |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1877 strcasecmp(qop, "auth-int"), NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1878 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1879 cipher = gaim_ciphers_find_cipher("md5"); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1880 g_return_val_if_fail(cipher != NULL, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1881 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1882 context = gaim_cipher_context_new(cipher, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1883 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1884 gaim_cipher_context_append(context, (guchar *)method, strlen(method)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1885 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1886 gaim_cipher_context_append(context, (guchar *)digest_uri, strlen(digest_uri)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1887 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1888 if (qop != NULL && !strcasecmp(qop, "auth-int")) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1889 { |
|
12389
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1890 GaimCipherContext *context2; |
|
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1891 gchar entity_hash[33]; |
|
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1892 |
|
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1893 if (entity == NULL) |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1894 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1895 gaim_cipher_context_destroy(context); |
|
12389
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1896 gaim_debug_error("cipher", "Required entity missing for auth-int digest calculation."); |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1897 return NULL; |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1898 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1899 |
|
12389
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1900 context2 = gaim_cipher_context_new(cipher, NULL); |
|
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1901 gaim_cipher_context_append(context2, (guchar *)entity, strlen(entity)); |
|
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1902 gaim_cipher_context_digest_to_str(context2, sizeof(entity_hash), entity_hash, NULL); |
|
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1903 gaim_cipher_context_destroy(context2); |
|
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1904 |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1905 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
12389
e024601d45c7
[gaim-migrate @ 14695]
Richard Laager <rlaager@wiktel.com>
parents:
12388
diff
changeset
|
1906 gaim_cipher_context_append(context, (guchar *)entity_hash, strlen(entity_hash)); |
|
12382
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1907 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1908 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1909 gaim_cipher_context_digest_to_str(context, sizeof(hash2), hash2, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1910 gaim_cipher_context_destroy(context); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1911 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1912 context = gaim_cipher_context_new(cipher, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1913 gaim_cipher_context_append(context, (guchar *)session_key, strlen(session_key)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1914 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1915 gaim_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1916 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1917 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1918 if (qop != NULL && *qop != '\0') |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1919 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1920 if (nonce_count == NULL) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1921 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1922 gaim_cipher_context_destroy(context); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1923 gaim_debug_error("cipher", "Required nonce_count missing for digest calculation."); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1924 return NULL; |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1925 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1926 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1927 if (client_nonce == NULL) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1928 { |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1929 gaim_cipher_context_destroy(context); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1930 gaim_debug_error("cipher", "Required client_nonce missing for digest calculation."); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1931 return NULL; |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1932 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1933 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1934 gaim_cipher_context_append(context, (guchar *)nonce_count, strlen(nonce_count)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1935 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1936 gaim_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1937 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1938 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1939 if (qop != NULL) |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1940 gaim_cipher_context_append(context, (guchar *)qop, strlen(qop)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1941 else |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1942 gaim_cipher_context_append(context, (guchar *)"", 0); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1943 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1944 gaim_cipher_context_append(context, (guchar *)":", 1); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1945 } |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1946 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1947 gaim_cipher_context_append(context, (guchar *)hash2, strlen(hash2)); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1948 gaim_cipher_context_digest_to_str(context, sizeof(hash2), hash2, NULL); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1949 gaim_cipher_context_destroy(context); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1950 |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1951 return g_strdup(hash2); |
|
cfc808463763
[gaim-migrate @ 14688]
Richard Laager <rlaager@wiktel.com>
parents:
11677
diff
changeset
|
1952 } |
