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