Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
/*
2
MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
3
 
4
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
5
All rights reserved.
6
 
7
License to copy and use this software is granted provided that it
8
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
9
Algorithm" in all material mentioning or referencing this software
10
or this function.
11
 
12
License is also granted to make and use derivative works provided
13
that such works are identified as "derived from the RSA Data
14
Security, Inc. MD5 Message-Digest Algorithm" in all material
15
mentioning or referencing the derived work.
16
 
17
RSA Data Security, Inc. makes no representations concerning either
18
the merchantability of this software or the suitability of this
19
software for any particular purpose. It is provided "as is"
20
without express or implied warranty of any kind.
21
 
22
These notices must be retained in any copies of any part of this
23
documentation and/or software.
24
*/
25
 
26
#include "fitz.h"
27
 
28
/* Constants for MD5Transform routine */
29
enum
30
{
31
	S11 = 7, S12 = 12, S13 = 17, S14 = 22,
32
	S21 = 5, S22 = 9, S23 = 14, S24 = 20,
33
	S31 = 4, S32 = 11, S33 = 16, S34 = 23,
34
	S41 = 6, S42 = 10, S43 = 15, S44 = 21
35
};
36
 
37
static void encode(unsigned char *, const unsigned int *, const unsigned);
38
static void decode(unsigned int *, const unsigned char *, const unsigned);
39
static void transform(unsigned int state[4], const unsigned char block[64]);
40
 
41
static unsigned char padding[64] =
42
{
43
	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
46
};
47
 
48
/* F, G, H and I are basic MD5 functions */
49
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
50
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
51
#define H(x, y, z) ((x) ^ (y) ^ (z))
52
#define I(x, y, z) ((y) ^ ((x) | (~z)))
53
 
54
/* ROTATE rotates x left n bits */
55
#define ROTATE(x, n) (((x) << (n)) | ((x) >> (32-(n))))
56
 
57
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
58
 * Rotation is separate from addition to prevent recomputation.
59
 */
60
#define FF(a, b, c, d, x, s, ac) { \
61
	(a) += F ((b), (c), (d)) + (x) + (unsigned int)(ac); \
62
	(a) = ROTATE ((a), (s)); \
63
	(a) += (b); \
64
	}
65
#define GG(a, b, c, d, x, s, ac) { \
66
	(a) += G ((b), (c), (d)) + (x) + (unsigned int)(ac); \
67
	(a) = ROTATE ((a), (s)); \
68
	(a) += (b); \
69
	}
70
#define HH(a, b, c, d, x, s, ac) { \
71
	(a) += H ((b), (c), (d)) + (x) + (unsigned int)(ac); \
72
	(a) = ROTATE ((a), (s)); \
73
	(a) += (b); \
74
	}
75
#define II(a, b, c, d, x, s, ac) { \
76
	(a) += I ((b), (c), (d)) + (x) + (unsigned int)(ac); \
77
	(a) = ROTATE ((a), (s)); \
78
	(a) += (b); \
79
	}
80
 
81
static void encode(unsigned char *output, const unsigned int *input, const unsigned len)
82
{
83
	unsigned i, j;
84
 
85
	for (i = 0, j = 0; j < len; i++, j += 4)
86
	{
87
		output[j] = (unsigned char)(input[i] & 0xff);
88
		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
89
		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
90
		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
91
	}
92
}
93
 
94
static void decode(unsigned int *output, const unsigned char *input, const unsigned len)
95
{
96
	unsigned i, j;
97
 
98
	for (i = 0, j = 0; j < len; i++, j += 4)
99
	{
100
		output[i] = ((unsigned int)input[j]) |
101
		(((unsigned int)input[j+1]) << 8) |
102
		(((unsigned int)input[j+2]) << 16) |
103
		(((unsigned int)input[j+3]) << 24);
104
	}
105
}
106
 
107
static void transform(unsigned int state[4], const unsigned char block[64])
108
{
109
	unsigned int a = state[0];
110
	unsigned int b = state[1];
111
	unsigned int c = state[2];
112
	unsigned int d = state[3];
113
	unsigned int x[16];
114
 
115
	decode(x, block, 64);
116
 
117
	/* Round 1 */
118
	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
119
	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
120
	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
121
	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
122
	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
123
	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
124
	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
125
	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
126
	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
127
	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
128
	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
129
	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
130
	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
131
	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
132
	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
133
	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
134
 
135
	/* Round 2 */
136
	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
137
	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
138
	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
139
	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
140
	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
141
	GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
142
	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
143
	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
144
	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
145
	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
146
	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
147
	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
148
	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
149
	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
150
	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
151
	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
152
 
153
	/* Round 3 */
154
	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
155
	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
156
	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
157
	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
158
	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
159
	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
160
	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
161
	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
162
	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
163
	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
164
	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
165
	HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
166
	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
167
	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
168
	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
169
	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
170
 
171
	/* Round 4 */
172
	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
173
	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
174
	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
175
	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
176
	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
177
	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
178
	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
179
	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
180
	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
181
	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
182
	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
183
	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
184
	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
185
	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
186
	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
187
	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
188
 
189
	state[0] += a;
190
	state[1] += b;
191
	state[2] += c;
192
	state[3] += d;
193
 
194
	/* Zeroize sensitive information */
195
	memset(x, 0, sizeof (x));
196
}
197
 
198
/* MD5 initialization. Begins an MD5 operation, writing a new context. */
199
void fz_md5_init(fz_md5 *context)
200
{
201
	context->count[0] = context->count[1] = 0;
202
 
203
	/* Load magic initialization constants */
204
	context->state[0] = 0x67452301;
205
	context->state[1] = 0xefcdab89;
206
	context->state[2] = 0x98badcfe;
207
	context->state[3] = 0x10325476;
208
}
209
 
210
/* MD5 block update operation. Continues an MD5 message-digest operation,
211
 * processing another message block, and updating the context.
212
 */
213
void fz_md5_update(fz_md5 *context, const unsigned char *input, const unsigned inlen)
214
{
215
	unsigned i, index, partlen;
216
 
217
	/* Compute number of bytes mod 64 */
218
	index = (unsigned)((context->count[0] >> 3) & 0x3F);
219
 
220
	/* Update number of bits */
221
	context->count[0] += (unsigned int) inlen << 3;
222
	if (context->count[0] < (unsigned int) inlen << 3)
223
		context->count[1] ++;
224
	context->count[1] += (unsigned int) inlen >> 29;
225
 
226
	partlen = 64 - index;
227
 
228
	/* Transform as many times as possible. */
229
	if (inlen >= partlen)
230
	{
231
		memcpy(context->buffer + index, input, partlen);
232
		transform(context->state, context->buffer);
233
 
234
		for (i = partlen; i + 63 < inlen; i += 64)
235
			transform(context->state, input + i);
236
 
237
		index = 0;
238
	}
239
	else
240
	{
241
		i = 0;
242
	}
243
 
244
	/* Buffer remaining input */
245
	memcpy(context->buffer + index, input + i, inlen - i);
246
}
247
 
248
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
249
 * the message digest and zeroizing the context.
250
 */
251
void fz_md5_final(fz_md5 *context, unsigned char digest[16])
252
{
253
	unsigned char bits[8];
254
	unsigned index, padlen;
255
 
256
	/* Save number of bits */
257
	encode(bits, context->count, 8);
258
 
259
	/* Pad out to 56 mod 64 */
260
	index = (unsigned)((context->count[0] >> 3) & 0x3f);
261
	padlen = index < 56 ? 56 - index : 120 - index;
262
	fz_md5_update(context, padding, padlen);
263
 
264
	/* Append length (before padding) */
265
	fz_md5_update(context, bits, 8);
266
 
267
	/* Store state in digest */
268
	encode(digest, context->state, 16);
269
 
270
	/* Zeroize sensitive information */
271
	memset(context, 0, sizeof(fz_md5));
272
}