comparison libpurple/ciphers/md4.c @ 31213:a1a0936d10c3

Fixed indentation, forgot to do so on my first commit. Added additional info from cipher.c to the file header
author Gary Kramlich <grim@reaperworld.com>
date Mon, 14 Feb 2011 05:55:02 +0000
parents 64587c6084e3
children 2d3c1197f930
comparison
equal deleted inserted replaced
31212:64587c6084e3 31213:a1a0936d10c3
10 * 10 *
11 * Implementation derived from Andrew Tridgell and Steve French's 11 * Implementation derived from Andrew Tridgell and Steve French's
12 * CIFS MD4 implementation, and the cryptoapi implementation 12 * CIFS MD4 implementation, and the cryptoapi implementation
13 * originally based on the public domain implementation written 13 * originally based on the public domain implementation written
14 * by Colin Plumb in 1993. 14 * by Colin Plumb in 1993.
15 *
16 * Copyright (c) Andrew Tridgell 1997-1998.
17 * Modified by Steve French (sfrench@us.ibm.com) 2002
18 * Copyright (c) Cryptoapi developers.
19 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
20 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
15 * 21 *
16 * This program is free software; you can redistribute it and/or modify 22 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by 23 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or 24 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version. 25 * (at your option) any later version.
34 #define MD4_HMAC_BLOCK_SIZE 64 40 #define MD4_HMAC_BLOCK_SIZE 64
35 #define MD4_BLOCK_WORDS 16 41 #define MD4_BLOCK_WORDS 16
36 #define MD4_HASH_WORDS 4 42 #define MD4_HASH_WORDS 4
37 43
38 struct MD4_Context { 44 struct MD4_Context {
39 guint32 hash[MD4_HASH_WORDS]; 45 guint32 hash[MD4_HASH_WORDS];
40 guint32 block[MD4_BLOCK_WORDS]; 46 guint32 block[MD4_BLOCK_WORDS];
41 guint64 byte_count; 47 guint64 byte_count;
42 }; 48 };
43 49
44 static inline guint32 lshift(guint32 x, unsigned int s) 50 static inline guint32 lshift(guint32 x, unsigned int s)
45 { 51 {
46 x &= 0xFFFFFFFF; 52 x &= 0xFFFFFFFF;
47 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); 53 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
48 } 54 }
49 55
50 static inline guint32 F(guint32 x, guint32 y, guint32 z) 56 static inline guint32 F(guint32 x, guint32 y, guint32 z)
51 { 57 {
52 return (x & y) | ((~x) & z); 58 return (x & y) | ((~x) & z);
53 } 59 }
54 60
55 static inline guint32 G(guint32 x, guint32 y, guint32 z) 61 static inline guint32 G(guint32 x, guint32 y, guint32 z)
56 { 62 {
57 return (x & y) | (x & z) | (y & z); 63 return (x & y) | (x & z) | (y & z);
58 } 64 }
59 65
60 static inline guint32 H(guint32 x, guint32 y, guint32 z) 66 static inline guint32 H(guint32 x, guint32 y, guint32 z)
61 { 67 {
62 return x ^ y ^ z; 68 return x ^ y ^ z;
63 } 69 }
64 70
65 #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) 71 #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
66 #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (guint32)0x5A827999,s)) 72 #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (guint32)0x5A827999,s))
67 #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (guint32)0x6ED9EBA1,s)) 73 #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (guint32)0x6ED9EBA1,s))
68 74
69 static inline void le32_to_cpu_array(guint32 *buf, unsigned int words) 75 static inline void le32_to_cpu_array(guint32 *buf, unsigned int words)
70 { 76 {
71 while (words--) { 77 while (words--) {
72 *buf=GUINT_FROM_LE(*buf); 78 *buf=GUINT_FROM_LE(*buf);
73 buf++; 79 buf++;
74 } 80 }
75 } 81 }
76 82
77 static inline void cpu_to_le32_array(guint32 *buf, unsigned int words) 83 static inline void cpu_to_le32_array(guint32 *buf, unsigned int words)
78 { 84 {
79 while (words--) { 85 while (words--) {
80 *buf=GUINT_TO_LE(*buf); 86 *buf=GUINT_TO_LE(*buf);
81 buf++; 87 buf++;
82 } 88 }
83 } 89 }
84 90
85 static void md4_transform(guint32 *hash, guint32 const *in) 91 static void md4_transform(guint32 *hash, guint32 const *in)
86 { 92 {
87 guint32 a, b, c, d; 93 guint32 a, b, c, d;
88 94
89 a = hash[0]; 95 a = hash[0];
90 b = hash[1]; 96 b = hash[1];
91 c = hash[2]; 97 c = hash[2];
92 d = hash[3]; 98 d = hash[3];
93 99
94 ROUND1(a, b, c, d, in[0], 3); 100 ROUND1(a, b, c, d, in[0], 3);
95 ROUND1(d, a, b, c, in[1], 7); 101 ROUND1(d, a, b, c, in[1], 7);
96 ROUND1(c, d, a, b, in[2], 11); 102 ROUND1(c, d, a, b, in[2], 11);
97 ROUND1(b, c, d, a, in[3], 19); 103 ROUND1(b, c, d, a, in[3], 19);
98 ROUND1(a, b, c, d, in[4], 3); 104 ROUND1(a, b, c, d, in[4], 3);
99 ROUND1(d, a, b, c, in[5], 7); 105 ROUND1(d, a, b, c, in[5], 7);
100 ROUND1(c, d, a, b, in[6], 11); 106 ROUND1(c, d, a, b, in[6], 11);
101 ROUND1(b, c, d, a, in[7], 19); 107 ROUND1(b, c, d, a, in[7], 19);
102 ROUND1(a, b, c, d, in[8], 3); 108 ROUND1(a, b, c, d, in[8], 3);
103 ROUND1(d, a, b, c, in[9], 7); 109 ROUND1(d, a, b, c, in[9], 7);
104 ROUND1(c, d, a, b, in[10], 11); 110 ROUND1(c, d, a, b, in[10], 11);
105 ROUND1(b, c, d, a, in[11], 19); 111 ROUND1(b, c, d, a, in[11], 19);
106 ROUND1(a, b, c, d, in[12], 3); 112 ROUND1(a, b, c, d, in[12], 3);
107 ROUND1(d, a, b, c, in[13], 7); 113 ROUND1(d, a, b, c, in[13], 7);
108 ROUND1(c, d, a, b, in[14], 11); 114 ROUND1(c, d, a, b, in[14], 11);
109 ROUND1(b, c, d, a, in[15], 19); 115 ROUND1(b, c, d, a, in[15], 19);
110 116
111 ROUND2(a, b, c, d,in[ 0], 3); 117 ROUND2(a, b, c, d,in[ 0], 3);
112 ROUND2(d, a, b, c, in[4], 5); 118 ROUND2(d, a, b, c, in[4], 5);
113 ROUND2(c, d, a, b, in[8], 9); 119 ROUND2(c, d, a, b, in[8], 9);
114 ROUND2(b, c, d, a, in[12], 13); 120 ROUND2(b, c, d, a, in[12], 13);
115 ROUND2(a, b, c, d, in[1], 3); 121 ROUND2(a, b, c, d, in[1], 3);
116 ROUND2(d, a, b, c, in[5], 5); 122 ROUND2(d, a, b, c, in[5], 5);
117 ROUND2(c, d, a, b, in[9], 9); 123 ROUND2(c, d, a, b, in[9], 9);
118 ROUND2(b, c, d, a, in[13], 13); 124 ROUND2(b, c, d, a, in[13], 13);
119 ROUND2(a, b, c, d, in[2], 3); 125 ROUND2(a, b, c, d, in[2], 3);
120 ROUND2(d, a, b, c, in[6], 5); 126 ROUND2(d, a, b, c, in[6], 5);
121 ROUND2(c, d, a, b, in[10], 9); 127 ROUND2(c, d, a, b, in[10], 9);
122 ROUND2(b, c, d, a, in[14], 13); 128 ROUND2(b, c, d, a, in[14], 13);
123 ROUND2(a, b, c, d, in[3], 3); 129 ROUND2(a, b, c, d, in[3], 3);
124 ROUND2(d, a, b, c, in[7], 5); 130 ROUND2(d, a, b, c, in[7], 5);
125 ROUND2(c, d, a, b, in[11], 9); 131 ROUND2(c, d, a, b, in[11], 9);
126 ROUND2(b, c, d, a, in[15], 13); 132 ROUND2(b, c, d, a, in[15], 13);
127 133
128 ROUND3(a, b, c, d,in[ 0], 3); 134 ROUND3(a, b, c, d,in[ 0], 3);
129 ROUND3(d, a, b, c, in[8], 9); 135 ROUND3(d, a, b, c, in[8], 9);
130 ROUND3(c, d, a, b, in[4], 11); 136 ROUND3(c, d, a, b, in[4], 11);
131 ROUND3(b, c, d, a, in[12], 15); 137 ROUND3(b, c, d, a, in[12], 15);
132 ROUND3(a, b, c, d, in[2], 3); 138 ROUND3(a, b, c, d, in[2], 3);
133 ROUND3(d, a, b, c, in[10], 9); 139 ROUND3(d, a, b, c, in[10], 9);
134 ROUND3(c, d, a, b, in[6], 11); 140 ROUND3(c, d, a, b, in[6], 11);
135 ROUND3(b, c, d, a, in[14], 15); 141 ROUND3(b, c, d, a, in[14], 15);
136 ROUND3(a, b, c, d, in[1], 3); 142 ROUND3(a, b, c, d, in[1], 3);
137 ROUND3(d, a, b, c, in[9], 9); 143 ROUND3(d, a, b, c, in[9], 9);
138 ROUND3(c, d, a, b, in[5], 11); 144 ROUND3(c, d, a, b, in[5], 11);
139 ROUND3(b, c, d, a, in[13], 15); 145 ROUND3(b, c, d, a, in[13], 15);
140 ROUND3(a, b, c, d, in[3], 3); 146 ROUND3(a, b, c, d, in[3], 3);
141 ROUND3(d, a, b, c, in[11], 9); 147 ROUND3(d, a, b, c, in[11], 9);
142 ROUND3(c, d, a, b, in[7], 11); 148 ROUND3(c, d, a, b, in[7], 11);
143 ROUND3(b, c, d, a, in[15], 15); 149 ROUND3(b, c, d, a, in[15], 15);
144 150
145 hash[0] += a; 151 hash[0] += a;
146 hash[1] += b; 152 hash[1] += b;
147 hash[2] += c; 153 hash[2] += c;
148 hash[3] += d; 154 hash[3] += d;
149 } 155 }
150 156
151 static inline void md4_transform_helper(struct MD4_Context *ctx) 157 static inline void md4_transform_helper(struct MD4_Context *ctx)
152 { 158 {
153 le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(guint32)); 159 le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(guint32));
154 md4_transform(ctx->hash, ctx->block); 160 md4_transform(ctx->hash, ctx->block);
155 } 161 }
156 162
157 static void 163 static void
158 md4_init(PurpleCipherContext *context, gpointer extra) { 164 md4_init(PurpleCipherContext *context, gpointer extra) {
159 struct MD4_Context *mctx; 165 struct MD4_Context *mctx;
160 mctx = g_new0(struct MD4_Context, 1); 166 mctx = g_new0(struct MD4_Context, 1);
161 purple_cipher_context_set_data(context, mctx); 167 purple_cipher_context_set_data(context, mctx);
162 purple_cipher_context_reset(context, extra); 168 purple_cipher_context_reset(context, extra);
163 169
164 mctx->hash[0] = 0x67452301; 170 mctx->hash[0] = 0x67452301;
165 mctx->hash[1] = 0xefcdab89; 171 mctx->hash[1] = 0xefcdab89;
166 mctx->hash[2] = 0x98badcfe; 172 mctx->hash[2] = 0x98badcfe;
167 mctx->hash[3] = 0x10325476; 173 mctx->hash[3] = 0x10325476;
168 mctx->byte_count = 0; 174 mctx->byte_count = 0;
169 } 175 }
170 176
171 static void 177 static void
172 md4_reset(PurpleCipherContext *context, gpointer extra) { 178 md4_reset(PurpleCipherContext *context, gpointer extra) {
173 struct MD4_Context *mctx; 179 struct MD4_Context *mctx;
174 180
175 mctx = purple_cipher_context_get_data(context); 181 mctx = purple_cipher_context_get_data(context);
176 182
177 mctx->hash[0] = 0x67452301; 183 mctx->hash[0] = 0x67452301;
178 mctx->hash[1] = 0xefcdab89; 184 mctx->hash[1] = 0xefcdab89;
179 mctx->hash[2] = 0x98badcfe; 185 mctx->hash[2] = 0x98badcfe;
180 mctx->hash[3] = 0x10325476; 186 mctx->hash[3] = 0x10325476;
181 mctx->byte_count = 0; 187 mctx->byte_count = 0;
182 } 188 }
183 189
184 static void 190 static void
185 md4_append(PurpleCipherContext *context, const guchar *data, size_t len) 191 md4_append(PurpleCipherContext *context, const guchar *data, size_t len)
186 { 192 {
187 struct MD4_Context *mctx = purple_cipher_context_get_data(context); 193 struct MD4_Context *mctx = purple_cipher_context_get_data(context);
188 const guint32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); 194 const guint32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
189 195
190 mctx->byte_count += len; 196 mctx->byte_count += len;
191 197
192 if (avail > len) { 198 if (avail > len) {
193 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), 199 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
194 data, len); 200 data, len);
195 return; 201 return;
196 } 202 }
197 203
198 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), 204 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
199 data, avail); 205 data, avail);
200 206
201 md4_transform_helper(mctx); 207 md4_transform_helper(mctx);
202 data += avail; 208 data += avail;
203 len -= avail; 209 len -= avail;
204 210
205 while (len >= sizeof(mctx->block)) { 211 while (len >= sizeof(mctx->block)) {
206 memcpy(mctx->block, data, sizeof(mctx->block)); 212 memcpy(mctx->block, data, sizeof(mctx->block));
207 md4_transform_helper(mctx); 213 md4_transform_helper(mctx);
208 data += sizeof(mctx->block); 214 data += sizeof(mctx->block);
209 len -= sizeof(mctx->block); 215 len -= sizeof(mctx->block);
210 } 216 }
211 217
212 memcpy(mctx->block, data, len); 218 memcpy(mctx->block, data, len);
213 } 219 }
214 220
215 static gboolean 221 static gboolean
216 md4_digest(PurpleCipherContext *context, size_t in_len, guchar *out, 222 md4_digest(PurpleCipherContext *context, size_t in_len, guchar *out,
217 size_t *out_len) 223 size_t *out_len)
218 { 224 {
219 struct MD4_Context *mctx = purple_cipher_context_get_data(context); 225 struct MD4_Context *mctx = purple_cipher_context_get_data(context);
220 const unsigned int offset = mctx->byte_count & 0x3f; 226 const unsigned int offset = mctx->byte_count & 0x3f;
221 char *p = (char *)mctx->block + offset; 227 char *p = (char *)mctx->block + offset;
222 int padding = 56 - (offset + 1); 228 int padding = 56 - (offset + 1);
223 229
224 230
225 if(in_len<16) return FALSE; 231 if(in_len<16) return FALSE;
226 if(out_len) *out_len = 16; 232 if(out_len) *out_len = 16;
227 *p++ = 0x80; 233 *p++ = 0x80;
228 if (padding < 0) { 234 if (padding < 0) {
229 memset(p, 0x00, padding + sizeof (guint64)); 235 memset(p, 0x00, padding + sizeof (guint64));
230 md4_transform_helper(mctx); 236 md4_transform_helper(mctx);
231 p = (char *)mctx->block; 237 p = (char *)mctx->block;
232 padding = 56; 238 padding = 56;
233 } 239 }
234 240
235 memset(p, 0, padding); 241 memset(p, 0, padding);
236 mctx->block[14] = mctx->byte_count << 3; 242 mctx->block[14] = mctx->byte_count << 3;
237 mctx->block[15] = mctx->byte_count >> 29; 243 mctx->block[15] = mctx->byte_count >> 29;
238 le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - 244 le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
239 sizeof(guint64)) / sizeof(guint32)); 245 sizeof(guint64)) / sizeof(guint32));
240 md4_transform(mctx->hash, mctx->block); 246 md4_transform(mctx->hash, mctx->block);
241 cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(guint32)); 247 cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(guint32));
242 memcpy(out, mctx->hash, sizeof(mctx->hash)); 248 memcpy(out, mctx->hash, sizeof(mctx->hash));
243 memset(mctx, 0, sizeof(*mctx)); 249 memset(mctx, 0, sizeof(*mctx));
244 return TRUE; 250 return TRUE;
245 } 251 }
246 252
247 static void 253 static void
248 md4_uninit(PurpleCipherContext *context) { 254 md4_uninit(PurpleCipherContext *context) {
249 struct MD4_Context *md4_context; 255 struct MD4_Context *md4_context;
250 256
251 purple_cipher_context_reset(context, NULL); 257 purple_cipher_context_reset(context, NULL);
252 258
253 md4_context = purple_cipher_context_get_data(context); 259 md4_context = purple_cipher_context_get_data(context);
254 memset(md4_context, 0, sizeof(*md4_context)); 260 memset(md4_context, 0, sizeof(*md4_context));
255 261
256 g_free(md4_context); 262 g_free(md4_context);
257 md4_context = NULL; 263 md4_context = NULL;
258 } 264 }
259 265
260 static size_t 266 static size_t
261 md4_get_block_size(PurpleCipherContext *context) 267 md4_get_block_size(PurpleCipherContext *context)
262 { 268 {
263 /* This does not change (in this case) */ 269 /* This does not change (in this case) */
264 return MD4_HMAC_BLOCK_SIZE; 270 return MD4_HMAC_BLOCK_SIZE;
265 } 271 }
266 272
267 static PurpleCipherOps MD4Ops = { 273 static PurpleCipherOps MD4Ops = {
268 .init = md4_init, 274 .init = md4_init,
269 .reset = md4_reset, 275 .reset = md4_reset,
270 .uninit = md4_uninit, 276 .uninit = md4_uninit,
271 .append = md4_append, 277 .append = md4_append,
272 .digest = md4_digest, 278 .digest = md4_digest,
273 .get_block_size = md4_get_block_size, 279 .get_block_size = md4_get_block_size,
274 }; 280 };
275 281
276 PurpleCipherOps * 282 PurpleCipherOps *
277 purple_md4_cipher_get_ops(void) { 283 purple_md4_cipher_get_ops(void) {
278 return &MD4Ops; 284 return &MD4Ops;