xref: /dragonfly/contrib/pam_passwdqc/md4.c (revision 7d3e9a5b)
1 /*
2  * This is an OpenSSL API compatible (but not ABI compatible) implementation
3  * of the RSA Data Security, Inc. MD4 Message-Digest Algorithm (RFC 1320).
4  *
5  * Homepage:
6  * https://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
7  *
8  * Author:
9  * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
10  *
11  * This software was written by Alexander Peslyak in 2001.  No copyright is
12  * claimed, and the software is hereby placed in the public domain.
13  * In case this attempt to disclaim copyright and place the software in the
14  * public domain is deemed null and void, then the software is
15  * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
16  * general public under the following terms:
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted.
20  *
21  * There's ABSOLUTELY NO WARRANTY, express or implied.
22  *
23  * (This is a heavily cut-down "BSD license".)
24  *
25  * This differs from Colin Plumb's older public domain implementation in that
26  * no exactly 32-bit integer data type is required (any 32-bit or wider
27  * unsigned integer data type will do), there's no compile-time endianness
28  * configuration, and the function prototypes match OpenSSL's.  No code from
29  * Colin Plumb's implementation has been reused; this comment merely compares
30  * the properties of the two independent implementations.
31  *
32  * The primary goals of this implementation are portability and ease of use.
33  * It is meant to be fast, but not as fast as possible.  Some known
34  * optimizations are not included to reduce source code size and avoid
35  * compile-time configuration.
36  */
37 
38 #ifndef HAVE_OPENSSL
39 
40 #include <string.h>
41 
42 #include "md4.h"
43 
44 /*
45  * The basic MD4 functions.
46  *
47  * F and G are optimized compared to their RFC 1320 definitions, with the
48  * optimization for F borrowed from Colin Plumb's MD5 implementation.
49  */
50 #define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
51 #define G(x, y, z)			(((x) & ((y) | (z))) | ((y) & (z)))
52 #define H(x, y, z)			((x) ^ (y) ^ (z))
53 
54 /*
55  * The MD4 transformation for all three rounds.
56  */
57 #define STEP(f, a, b, c, d, x, s) \
58 	(a) += f((b), (c), (d)) + (x); \
59 	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
60 
61 /*
62  * SET reads 4 input bytes in little-endian byte order and stores them in a
63  * properly aligned word in host byte order.
64  *
65  * The check for little-endian architectures that tolerate unaligned memory
66  * accesses is just an optimization.  Nothing will break if it fails to detect
67  * a suitable architecture.
68  *
69  * Unfortunately, this optimization may be a C strict aliasing rules violation
70  * if the caller's data buffer has effective type that cannot be aliased by
71  * MD4_u32plus.  In practice, this problem may occur if these MD4 routines are
72  * inlined into a calling function, or with future and dangerously advanced
73  * link-time optimizations.  For the time being, keeping these MD4 routines in
74  * their own translation unit avoids the problem.
75  */
76 #if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
77 #define SET(n) \
78 	(*(MD4_u32plus *)&ptr[(n) * 4])
79 #define GET(n) \
80 	SET(n)
81 #else
82 #define SET(n) \
83 	(ctx->block[(n)] = \
84 	(MD4_u32plus)ptr[(n) * 4] | \
85 	((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
86 	((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
87 	((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
88 #define GET(n) \
89 	(ctx->block[(n)])
90 #endif
91 
92 /*
93  * This processes one or more 64-byte data blocks, but does NOT update the bit
94  * counters.  There are no alignment requirements.
95  */
96 static const void *body(MD4_CTX *ctx, const void *data, size_t size)
97 {
98 	const unsigned char *ptr;
99 	MD4_u32plus a, b, c, d;
100 	MD4_u32plus saved_a, saved_b, saved_c, saved_d;
101 	const MD4_u32plus ac1 = 0x5a827999, ac2 = 0x6ed9eba1;
102 
103 	ptr = (const unsigned char *)data;
104 
105 	a = ctx->a;
106 	b = ctx->b;
107 	c = ctx->c;
108 	d = ctx->d;
109 
110 	do {
111 		saved_a = a;
112 		saved_b = b;
113 		saved_c = c;
114 		saved_d = d;
115 
116 /* Round 1 */
117 		STEP(F, a, b, c, d, SET(0), 3)
118 		STEP(F, d, a, b, c, SET(1), 7)
119 		STEP(F, c, d, a, b, SET(2), 11)
120 		STEP(F, b, c, d, a, SET(3), 19)
121 		STEP(F, a, b, c, d, SET(4), 3)
122 		STEP(F, d, a, b, c, SET(5), 7)
123 		STEP(F, c, d, a, b, SET(6), 11)
124 		STEP(F, b, c, d, a, SET(7), 19)
125 		STEP(F, a, b, c, d, SET(8), 3)
126 		STEP(F, d, a, b, c, SET(9), 7)
127 		STEP(F, c, d, a, b, SET(10), 11)
128 		STEP(F, b, c, d, a, SET(11), 19)
129 		STEP(F, a, b, c, d, SET(12), 3)
130 		STEP(F, d, a, b, c, SET(13), 7)
131 		STEP(F, c, d, a, b, SET(14), 11)
132 		STEP(F, b, c, d, a, SET(15), 19)
133 
134 /* Round 2 */
135 		STEP(G, a, b, c, d, GET(0) + ac1, 3)
136 		STEP(G, d, a, b, c, GET(4) + ac1, 5)
137 		STEP(G, c, d, a, b, GET(8) + ac1, 9)
138 		STEP(G, b, c, d, a, GET(12) + ac1, 13)
139 		STEP(G, a, b, c, d, GET(1) + ac1, 3)
140 		STEP(G, d, a, b, c, GET(5) + ac1, 5)
141 		STEP(G, c, d, a, b, GET(9) + ac1, 9)
142 		STEP(G, b, c, d, a, GET(13) + ac1, 13)
143 		STEP(G, a, b, c, d, GET(2) + ac1, 3)
144 		STEP(G, d, a, b, c, GET(6) + ac1, 5)
145 		STEP(G, c, d, a, b, GET(10) + ac1, 9)
146 		STEP(G, b, c, d, a, GET(14) + ac1, 13)
147 		STEP(G, a, b, c, d, GET(3) + ac1, 3)
148 		STEP(G, d, a, b, c, GET(7) + ac1, 5)
149 		STEP(G, c, d, a, b, GET(11) + ac1, 9)
150 		STEP(G, b, c, d, a, GET(15) + ac1, 13)
151 
152 /* Round 3 */
153 		STEP(H, a, b, c, d, GET(0) + ac2, 3)
154 		STEP(H, d, a, b, c, GET(8) + ac2, 9)
155 		STEP(H, c, d, a, b, GET(4) + ac2, 11)
156 		STEP(H, b, c, d, a, GET(12) + ac2, 15)
157 		STEP(H, a, b, c, d, GET(2) + ac2, 3)
158 		STEP(H, d, a, b, c, GET(10) + ac2, 9)
159 		STEP(H, c, d, a, b, GET(6) + ac2, 11)
160 		STEP(H, b, c, d, a, GET(14) + ac2, 15)
161 		STEP(H, a, b, c, d, GET(1) + ac2, 3)
162 		STEP(H, d, a, b, c, GET(9) + ac2, 9)
163 		STEP(H, c, d, a, b, GET(5) + ac2, 11)
164 		STEP(H, b, c, d, a, GET(13) + ac2, 15)
165 		STEP(H, a, b, c, d, GET(3) + ac2, 3)
166 		STEP(H, d, a, b, c, GET(11) + ac2, 9)
167 		STEP(H, c, d, a, b, GET(7) + ac2, 11)
168 		STEP(H, b, c, d, a, GET(15) + ac2, 15)
169 
170 		a += saved_a;
171 		b += saved_b;
172 		c += saved_c;
173 		d += saved_d;
174 
175 		ptr += 64;
176 	} while (size -= 64);
177 
178 	ctx->a = a;
179 	ctx->b = b;
180 	ctx->c = c;
181 	ctx->d = d;
182 
183 	return ptr;
184 }
185 
186 void MD4_Init(MD4_CTX *ctx)
187 {
188 	ctx->a = 0x67452301;
189 	ctx->b = 0xefcdab89;
190 	ctx->c = 0x98badcfe;
191 	ctx->d = 0x10325476;
192 
193 	ctx->lo = 0;
194 	ctx->hi = 0;
195 }
196 
197 void MD4_Update(MD4_CTX *ctx, const void *data, size_t size)
198 {
199 	MD4_u32plus saved_lo;
200 	size_t used, available;
201 
202 	saved_lo = ctx->lo;
203 	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
204 		ctx->hi++;
205 	ctx->hi += (MD4_u32plus)(size >> 29);
206 
207 	used = saved_lo & 0x3f;
208 
209 	if (used) {
210 		available = 64 - used;
211 
212 		if (size < available) {
213 			memcpy(&ctx->buffer[used], data, size);
214 			return;
215 		}
216 
217 		memcpy(&ctx->buffer[used], data, available);
218 		data = (const unsigned char *)data + available;
219 		size -= available;
220 		body(ctx, ctx->buffer, 64);
221 	}
222 
223 	if (size >= 64) {
224 		data = body(ctx, data, size & ~(size_t)0x3f);
225 		size &= 0x3f;
226 	}
227 
228 	memcpy(ctx->buffer, data, size);
229 }
230 
231 #define OUT(dst, src) \
232 	(dst)[0] = (unsigned char)(src); \
233 	(dst)[1] = (unsigned char)((src) >> 8); \
234 	(dst)[2] = (unsigned char)((src) >> 16); \
235 	(dst)[3] = (unsigned char)((src) >> 24);
236 
237 void MD4_Final(unsigned char *result, MD4_CTX *ctx)
238 {
239 	size_t used, available;
240 
241 	used = ctx->lo & 0x3f;
242 
243 	ctx->buffer[used++] = 0x80;
244 
245 	available = 64 - used;
246 
247 	if (available < 8) {
248 		memset(&ctx->buffer[used], 0, available);
249 		body(ctx, ctx->buffer, 64);
250 		used = 0;
251 		available = 64;
252 	}
253 
254 	memset(&ctx->buffer[used], 0, available - 8);
255 
256 	ctx->lo <<= 3;
257 	OUT(&ctx->buffer[56], ctx->lo)
258 	OUT(&ctx->buffer[60], ctx->hi)
259 
260 	body(ctx, ctx->buffer, 64);
261 
262 	OUT(&result[0], ctx->a)
263 	OUT(&result[4], ctx->b)
264 	OUT(&result[8], ctx->c)
265 	OUT(&result[12], ctx->d)
266 
267 #if 0
268 	memset(ctx, 0, sizeof(*ctx));
269 #endif
270 }
271 
272 #endif
273