Mercurial > pidgin
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; |