Doh. Upon further investigation I think these translations were made
[pidgin-git.git] / libpurple / ciphers / md5.c
blobd739bc258d368353a7676e1dc8b5e81772605656
1 /*
2 * purple
4 * Purple is the legal property of its developers, whose names are too numerous
5 * to list here. Please refer to the COPYRIGHT file distributed with this
6 * source distribution.
8 * Original md5
9 * Copyright (C) 2001-2003 Christophe Devine <c.devine@cr0.net>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 #include <cipher.h>
27 #if !GLIB_CHECK_VERSION(2,16,0)
29 #define MD5_HMAC_BLOCK_SIZE 64
31 struct MD5Context {
32 guint32 total[2];
33 guint32 state[4];
34 guchar buffer[64];
37 #define MD5_GET_GUINT32(n,b,i) { \
38 (n) = ((guint32)(b) [(i) ] ) \
39 | ((guint32)(b) [(i) + 1] << 8) \
40 | ((guint32)(b) [(i) + 2] << 16) \
41 | ((guint32)(b) [(i) + 3] << 24); \
43 #define MD5_PUT_GUINT32(n,b,i) { \
44 (b)[(i) ] = (guchar)((n) ); \
45 (b)[(i) + 1] = (guchar)((n) >> 8); \
46 (b)[(i) + 2] = (guchar)((n) >> 16); \
47 (b)[(i) + 3] = (guchar)((n) >> 24); \
50 static size_t
51 md5_get_block_size(PurpleCipherContext *context)
53 /* This does not change (in this case) */
54 return MD5_HMAC_BLOCK_SIZE;
57 static void
58 md5_init(PurpleCipherContext *context, gpointer extra) {
59 struct MD5Context *md5_context;
61 md5_context = g_new0(struct MD5Context, 1);
63 purple_cipher_context_set_data(context, md5_context);
65 purple_cipher_context_reset(context, extra);
68 static void
69 md5_reset(PurpleCipherContext *context, gpointer extra) {
70 struct MD5Context *md5_context;
72 md5_context = purple_cipher_context_get_data(context);
74 md5_context->total[0] = 0;
75 md5_context->total[1] = 0;
77 md5_context->state[0] = 0x67452301;
78 md5_context->state[1] = 0xEFCDAB89;
79 md5_context->state[2] = 0x98BADCFE;
80 md5_context->state[3] = 0x10325476;
82 memset(md5_context->buffer, 0, sizeof(md5_context->buffer));
85 static void
86 md5_uninit(PurpleCipherContext *context) {
87 struct MD5Context *md5_context;
89 purple_cipher_context_reset(context, NULL);
91 md5_context = purple_cipher_context_get_data(context);
92 memset(md5_context, 0, sizeof(*md5_context));
94 g_free(md5_context);
95 md5_context = NULL;
98 static void
99 md5_process(struct MD5Context *md5_context, const guchar data[64]) {
100 guint32 X[16], A, B, C, D;
102 A = md5_context->state[0];
103 B = md5_context->state[1];
104 C = md5_context->state[2];
105 D = md5_context->state[3];
107 MD5_GET_GUINT32(X[ 0], data, 0);
108 MD5_GET_GUINT32(X[ 1], data, 4);
109 MD5_GET_GUINT32(X[ 2], data, 8);
110 MD5_GET_GUINT32(X[ 3], data, 12);
111 MD5_GET_GUINT32(X[ 4], data, 16);
112 MD5_GET_GUINT32(X[ 5], data, 20);
113 MD5_GET_GUINT32(X[ 6], data, 24);
114 MD5_GET_GUINT32(X[ 7], data, 28);
115 MD5_GET_GUINT32(X[ 8], data, 32);
116 MD5_GET_GUINT32(X[ 9], data, 36);
117 MD5_GET_GUINT32(X[10], data, 40);
118 MD5_GET_GUINT32(X[11], data, 44);
119 MD5_GET_GUINT32(X[12], data, 48);
120 MD5_GET_GUINT32(X[13], data, 52);
121 MD5_GET_GUINT32(X[14], data, 56);
122 MD5_GET_GUINT32(X[15], data, 60);
124 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
125 #define P(a,b,c,d,k,s,t) { \
126 a += F(b,c,d) + X[k] + t; \
127 a = S(a,s) + b; \
130 /* first pass */
131 #define F(x,y,z) (z ^ (x & (y ^ z)))
132 P(A, B, C, D, 0, 7, 0xD76AA478);
133 P(D, A, B, C, 1, 12, 0xE8C7B756);
134 P(C, D, A, B, 2, 17, 0x242070DB);
135 P(B, C, D, A, 3, 22, 0xC1BDCEEE);
136 P(A, B, C, D, 4, 7, 0xF57C0FAF);
137 P(D, A, B, C, 5, 12, 0x4787C62A);
138 P(C, D, A, B, 6, 17, 0xA8304613);
139 P(B, C, D, A, 7, 22, 0xFD469501);
140 P(A, B, C, D, 8, 7, 0x698098D8);
141 P(D, A, B, C, 9, 12, 0x8B44F7AF);
142 P(C, D, A, B, 10, 17, 0xFFFF5BB1);
143 P(B, C, D, A, 11, 22, 0x895CD7BE);
144 P(A, B, C, D, 12, 7, 0x6B901122);
145 P(D, A, B, C, 13, 12, 0xFD987193);
146 P(C, D, A, B, 14, 17, 0xA679438E);
147 P(B, C, D, A, 15, 22, 0x49B40821);
148 #undef F
150 /* second pass */
151 #define F(x,y,z) (y ^ (z & (x ^ y)))
152 P(A, B, C, D, 1, 5, 0xF61E2562);
153 P(D, A, B, C, 6, 9, 0xC040B340);
154 P(C, D, A, B, 11, 14, 0x265E5A51);
155 P(B, C, D, A, 0, 20, 0xE9B6C7AA);
156 P(A, B, C, D, 5, 5, 0xD62F105D);
157 P(D, A, B, C, 10, 9, 0x02441453);
158 P(C, D, A, B, 15, 14, 0xD8A1E681);
159 P(B, C, D, A, 4, 20, 0xE7D3FBC8);
160 P(A, B, C, D, 9, 5, 0x21E1CDE6);
161 P(D, A, B, C, 14, 9, 0xC33707D6);
162 P(C, D, A, B, 3, 14, 0xF4D50D87);
163 P(B, C, D, A, 8, 20, 0x455A14ED);
164 P(A, B, C, D, 13, 5, 0xA9E3E905);
165 P(D, A, B, C, 2, 9, 0xFCEFA3F8);
166 P(C, D, A, B, 7, 14, 0x676F02D9);
167 P(B, C, D, A, 12, 20, 0x8D2A4C8A);
168 #undef F
170 /* third pass */
171 #define F(x,y,z) (x ^ y ^ z)
172 P(A, B, C, D, 5, 4, 0xFFFA3942);
173 P(D, A, B, C, 8, 11, 0x8771F681);
174 P(C, D, A, B, 11, 16, 0x6D9D6122);
175 P(B, C, D, A, 14, 23, 0xFDE5380C);
176 P(A, B, C, D, 1, 4, 0xA4BEEA44);
177 P(D, A, B, C, 4, 11, 0x4BDECFA9);
178 P(C, D, A, B, 7, 16, 0xF6BB4B60);
179 P(B, C, D, A, 10, 23, 0xBEBFBC70);
180 P(A, B, C, D, 13, 4, 0x289B7EC6);
181 P(D, A, B, C, 0, 11, 0xEAA127FA);
182 P(C, D, A, B, 3, 16, 0xD4EF3085);
183 P(B, C, D, A, 6, 23, 0x04881D05);
184 P(A, B, C, D, 9, 4, 0xD9D4D039);
185 P(D, A, B, C, 12, 11, 0xE6DB99E5);
186 P(C, D, A, B, 15, 16, 0x1FA27CF8);
187 P(B, C, D, A, 2, 23, 0xC4AC5665);
188 #undef F
190 /* forth pass */
191 #define F(x,y,z) (y ^ (x | ~z))
192 P(A, B, C, D, 0, 6, 0xF4292244);
193 P(D, A, B, C, 7, 10, 0x432AFF97);
194 P(C, D, A, B, 14, 15, 0xAB9423A7);
195 P(B, C, D, A, 5, 21, 0xFC93A039);
196 P(A, B, C, D, 12, 6, 0x655B59C3);
197 P(D, A, B, C, 3, 10, 0x8F0CCC92);
198 P(C, D, A, B, 10, 15, 0xFFEFF47D);
199 P(B, C, D, A, 1, 21, 0x85845DD1);
200 P(A, B, C, D, 8, 6, 0x6FA87E4F);
201 P(D, A, B, C, 15, 10, 0xFE2CE6E0);
202 P(C, D, A, B, 6, 15, 0xA3014314);
203 P(B, C, D, A, 13, 21, 0x4E0811A1);
204 P(A, B, C, D, 4, 6, 0xF7537E82);
205 P(D, A, B, C, 11, 10, 0xBD3AF235);
206 P(C, D, A, B, 2, 15, 0x2AD7D2BB);
207 P(B, C, D, A, 9, 21, 0xEB86D391);
208 #undef F
209 #undef P
210 #undef S
212 md5_context->state[0] += A;
213 md5_context->state[1] += B;
214 md5_context->state[2] += C;
215 md5_context->state[3] += D;
218 static void
219 md5_append(PurpleCipherContext *context, const guchar *data, size_t len) {
220 struct MD5Context *md5_context = NULL;
221 guint32 left = 0, fill = 0;
223 g_return_if_fail(context != NULL);
225 md5_context = purple_cipher_context_get_data(context);
226 g_return_if_fail(md5_context != NULL);
228 left = md5_context->total[0] & 0x3F;
229 fill = 64 - left;
231 md5_context->total[0] += len;
232 md5_context->total[0] &= 0xFFFFFFFF;
234 if(md5_context->total[0] < len)
235 md5_context->total[1]++;
237 if(left && len >= fill) {
238 memcpy((md5_context->buffer + left), data, fill);
239 md5_process(md5_context, md5_context->buffer);
240 len -= fill;
241 data += fill;
242 left = 0;
245 while(len >= 64) {
246 md5_process(md5_context, data);
247 len -= 64;
248 data += 64;
251 if(len) {
252 memcpy((md5_context->buffer + left), data, len);
256 static gboolean
257 md5_digest(PurpleCipherContext *context, size_t in_len, guchar digest[16],
258 size_t *out_len)
260 struct MD5Context *md5_context = NULL;
261 guint32 last, pad;
262 guint32 high, low;
263 guchar message[8];
264 guchar padding[64] = {
265 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
271 g_return_val_if_fail(in_len >= 16, FALSE);
273 md5_context = purple_cipher_context_get_data(context);
275 high = (md5_context->total[0] >> 29)
276 | (md5_context->total[1] << 3);
277 low = (md5_context->total[0] << 3);
279 MD5_PUT_GUINT32(low, message, 0);
280 MD5_PUT_GUINT32(high, message, 4);
282 last = md5_context->total[0] & 0x3F;
283 pad = (last < 56) ? (56 - last) : (120 - last);
285 md5_append(context, padding, pad);
286 md5_append(context, message, 8);
288 MD5_PUT_GUINT32(md5_context->state[0], digest, 0);
289 MD5_PUT_GUINT32(md5_context->state[1], digest, 4);
290 MD5_PUT_GUINT32(md5_context->state[2], digest, 8);
291 MD5_PUT_GUINT32(md5_context->state[3], digest, 12);
293 if(out_len)
294 *out_len = 16;
296 return TRUE;
299 static PurpleCipherOps MD5Ops = {
300 NULL, /* Set Option */
301 NULL, /* Get Option */
302 md5_init, /* init */
303 md5_reset, /* reset */
304 md5_uninit, /* uninit */
305 NULL, /* set iv */
306 md5_append, /* append */
307 md5_digest, /* digest */
308 NULL, /* encrypt */
309 NULL, /* decrypt */
310 NULL, /* set salt */
311 NULL, /* get salt size */
312 NULL, /* set key */
313 NULL, /* get key size */
314 NULL, /* set batch mode */
315 NULL, /* get batch mode */
316 md5_get_block_size, /* get block size */
317 NULL /* set key with len */
320 PurpleCipherOps *
321 purple_md5_cipher_get_ops(void) {
322 return &MD5Ops;
325 #endif /* !GLIB_CHECK_VERSION(2,16,0) */