Browse Source

Taken from Linux's md5.c. This implementation is not very

size-efficient, and will probably be rewritten.

The md5.c from MatrixSSL is too ugly to consider importing.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
48bdde5d7b
1 changed files with 222 additions and 0 deletions
  1. 222
    0
      src/crypto/md5.c

+ 222
- 0
src/crypto/md5.c View File

@@ -0,0 +1,222 @@
1
+/* 
2
+ * Cryptographic API.
3
+ *
4
+ * MD5 Message Digest Algorithm (RFC1321).
5
+ *
6
+ * Derived from cryptoapi implementation, originally based on the
7
+ * public domain implementation written by Colin Plumb in 1993.
8
+ *
9
+ * Copyright (c) Cryptoapi developers.
10
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
11
+ * 
12
+ * This program is free software; you can redistribute it and/or modify it
13
+ * under the terms of the GNU General Public License as published by the Free
14
+ * Software Foundation; either version 2 of the License, or (at your option) 
15
+ * any later version.
16
+ *
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <string.h>
21
+#include <byteswap.h>
22
+#include <gpxe/crypto.h>
23
+
24
+#define MD5_DIGEST_SIZE		16
25
+#define MD5_HMAC_BLOCK_SIZE	64
26
+#define MD5_BLOCK_WORDS		16
27
+#define MD5_HASH_WORDS		4
28
+
29
+#define F1(x, y, z)	(z ^ (x & (y ^ z)))
30
+#define F2(x, y, z)	F1(z, x, y)
31
+#define F3(x, y, z)	(x ^ y ^ z)
32
+#define F4(x, y, z)	(y ^ (x | ~z))
33
+
34
+#define MD5STEP(f, w, x, y, z, in, s) \
35
+	(w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
36
+
37
+struct md5_ctx {
38
+	u32 hash[MD5_HASH_WORDS];
39
+	u32 block[MD5_BLOCK_WORDS];
40
+	u64 byte_count;
41
+};
42
+
43
+static void md5_transform(u32 *hash, u32 const *in)
44
+{
45
+	u32 a, b, c, d;
46
+
47
+	a = hash[0];
48
+	b = hash[1];
49
+	c = hash[2];
50
+	d = hash[3];
51
+
52
+	MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
53
+	MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
54
+	MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
55
+	MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
56
+	MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
57
+	MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
58
+	MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
59
+	MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
60
+	MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
61
+	MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
62
+	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
63
+	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
64
+	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
65
+	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
66
+	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
67
+	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
68
+
69
+	MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
70
+	MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
71
+	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
72
+	MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
73
+	MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
74
+	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
75
+	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
76
+	MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
77
+	MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
78
+	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
79
+	MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
80
+	MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
81
+	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
82
+	MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
83
+	MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
84
+	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
85
+
86
+	MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
87
+	MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
88
+	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
89
+	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
90
+	MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
91
+	MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
92
+	MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
93
+	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
94
+	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
95
+	MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
96
+	MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
97
+	MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
98
+	MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
99
+	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
100
+	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
101
+	MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
102
+
103
+	MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
104
+	MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
105
+	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
106
+	MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
107
+	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
108
+	MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
109
+	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
110
+	MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
111
+	MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
112
+	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
113
+	MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
114
+	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
115
+	MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
116
+	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
117
+	MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
118
+	MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
119
+
120
+	hash[0] += a;
121
+	hash[1] += b;
122
+	hash[2] += c;
123
+	hash[3] += d;
124
+}
125
+
126
+/* XXX: this stuff can be optimized */
127
+static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
128
+{
129
+	while (words--) {
130
+		//		__le32_to_cpus(buf);
131
+		buf++;
132
+	}
133
+}
134
+
135
+static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
136
+{
137
+	while (words--) {
138
+		//		__cpu_to_le32s(buf);
139
+		buf++;
140
+	}
141
+}
142
+
143
+static inline void md5_transform_helper(struct md5_ctx *ctx)
144
+{
145
+	le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32));
146
+	md5_transform(ctx->hash, ctx->block);
147
+}
148
+
149
+static void md5_init(void *context)
150
+{
151
+	struct md5_ctx *mctx = context;
152
+
153
+	mctx->hash[0] = 0x67452301;
154
+	mctx->hash[1] = 0xefcdab89;
155
+	mctx->hash[2] = 0x98badcfe;
156
+	mctx->hash[3] = 0x10325476;
157
+	mctx->byte_count = 0;
158
+}
159
+
160
+static void md5_update(void *context, const void *data, size_t len)
161
+{
162
+	struct md5_ctx *mctx = context;
163
+	const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
164
+
165
+	mctx->byte_count += len;
166
+
167
+	if (avail > len) {
168
+		memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
169
+		       data, len);
170
+		return;
171
+	}
172
+
173
+	memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
174
+	       data, avail);
175
+
176
+	md5_transform_helper(mctx);
177
+	data += avail;
178
+	len -= avail;
179
+
180
+	while (len >= sizeof(mctx->block)) {
181
+		memcpy(mctx->block, data, sizeof(mctx->block));
182
+		md5_transform_helper(mctx);
183
+		data += sizeof(mctx->block);
184
+		len -= sizeof(mctx->block);
185
+	}
186
+
187
+	memcpy(mctx->block, data, len);
188
+}
189
+
190
+static void md5_finish(void *context, void *out)
191
+{
192
+	struct md5_ctx *mctx = context;
193
+	const unsigned int offset = mctx->byte_count & 0x3f;
194
+	char *p = (char *)mctx->block + offset;
195
+	int padding = 56 - (offset + 1);
196
+
197
+	*p++ = 0x80;
198
+	if (padding < 0) {
199
+		memset(p, 0x00, padding + sizeof (u64));
200
+		md5_transform_helper(mctx);
201
+		p = (char *)mctx->block;
202
+		padding = 56;
203
+	}
204
+
205
+	memset(p, 0, padding);
206
+	mctx->block[14] = mctx->byte_count << 3;
207
+	mctx->block[15] = mctx->byte_count >> 29;
208
+	le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
209
+	                  sizeof(u64)) / sizeof(u32));
210
+	md5_transform(mctx->hash, mctx->block);
211
+	cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
212
+	memcpy(out, mctx->hash, sizeof(mctx->hash));
213
+	memset(mctx, 0, sizeof(*mctx));
214
+}
215
+
216
+struct digest_algorithm md5_algorithm = {
217
+	.context_len	= sizeof ( struct md5_ctx ),
218
+	.digest_len	= MD5_DIGEST_SIZE,
219
+	.init		= md5_init,
220
+	.update		= md5_update,
221
+	.finish		= md5_finish,
222
+};

Loading…
Cancel
Save