1/*
2 * md4.c, copied from src/router/ppp/pppd to src/bcmcrypto for general use,
3 *	  with a few casts added to make it usable with a fussy compiler.
4 *
5 * ********************************************************************
6 * md4.c -- Implementation of MD4 Message Digest Algorithm           **
7 * Updated: 2/16/90 by Ronald L. Rivest                              **
8 * (C) 1990 RSA Data Security, Inc.                                  **
9 * ********************************************************************
10 *
11 * Copyright (C) 2015, Broadcom Corporation
12 * All Rights Reserved.
13 *
14 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
15 * the contents of this file may not be disclosed to third parties, copied
16 * or duplicated in any form, in whole or in part, without the prior
17 * written permission of Broadcom Corporation.
18 *
19 * $Id: md4.c 241182 2011-02-17 21:50:03Z $
20 */
21
22/*
23 * To use MD4:
24 *   -- Include md4.h in your program
25 *   -- Declare an MDstruct MD to hold the state of the digest
26 *          computation.
27 *   -- Initialize MD using MDbegin(&MD)
28 *   -- For each full block (64 bytes) X you wish to process, call
29 *          MD4Update(&MD,X,512)
30 *      (512 is the number of bits in a full block.)
31 *   -- For the last block (less than 64 bytes) you wish to process,
32 *          MD4Update(&MD,X,n)
33 *      where n is the number of bits in the partial block. A partial
34 *      block terminates the computation, so every MD computation
35 *      should terminate by processing a partial block, even if it
36 *      has n = 0.
37 *   -- The message digest is available in MD.buffer[0] ...
38 *      MD.buffer[3].  (Least-significant byte of each word
39 *      should be output first.)
40 *   -- You can print out the digest using MDprint(&MD)
41 */
42
43/* Implementation notes:
44 * This implementation assumes that ints are 32-bit quantities.
45 */
46
47#include <typedefs.h>
48
49#include <bcmcrypto/md4.h>
50
51#ifndef BCMDRIVER
52#include <stdio.h>
53#endif
54
55/* Compile-time declarations of MD4 "magic constants". */
56#define I0  0x67452301       /* Initial values for MD buffer */
57#define I1  0xefcdab89
58#define I2  0x98badcfe
59#define I3  0x10325476
60#define C2  013240474631     /* round 2 constant = sqrt(2) in octal */
61#define C3  015666365641     /* round 3 constant = sqrt(3) in octal */
62/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
63 * (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
64 * Table 2, page 660.
65 */
66
67#define fs1  3               /* round 1 shift amounts */
68#define fs2  7
69#define fs3 11
70#define fs4 19
71#define gs1  3               /* round 2 shift amounts */
72#define gs2  5
73#define gs3  9
74#define gs4 13
75#define hs1  3               /* round 3 shift amounts */
76#define hs2  9
77#define hs3 11
78#define hs4 15
79
80/* Compile-time macro declarations for MD4.
81 * Note: The "rot" operator uses the variable "tmp".
82 * It assumes tmp is declared as unsigned int, so that the >>
83 * operator will shift in zeros rather than extending the sign bit.
84 */
85#define f(X, Y, Z)		((X & Y) | ((~X) & Z))
86#define g(X, Y, Z)		((X & Y) | (X & Z) | (Y & Z))
87#define h(X, Y, Z)		(X ^ Y ^ Z)
88#define rot(X, S)		(tmp = X, (tmp << S) | (tmp >> (32 - S)))
89#define ff(A, B, C, D, i, s)	A = rot((A + f(B, C, D) + X[i]), s)
90#define gg(A, B, C, D, i, s)	A = rot((A + g(B, C, D) + X[i] + C2), s)
91#define hh(A, B, C, D, i, s)	A = rot((A + h(B, C, D) + X[i] + C3), s)
92
93
94/* MD4Init(MDp)
95 * Initialize message digest buffer MDp.
96 * This is a user-callable routine.
97 */
98void
99BCMROMFN(MD4Init)(MD4_CTX *MDp)
100{
101	int i;
102	MDp->buffer[0] = I0;
103	MDp->buffer[1] = I1;
104	MDp->buffer[2] = I2;
105	MDp->buffer[3] = I3;
106	for (i = 0; i < 8; i++)
107		MDp->count[i] = 0;
108	MDp->done = 0;
109}
110
111/* MDblock(MDp,X)
112 * Update message digest buffer MDp->buffer using 16-word data block X.
113 * Assumes all 16 words of X are full of data.
114 * Does not update MDp->count.
115 * This routine is not user-callable.
116 */
117static void
118MDblock(MD4_CTX *MDp, unsigned char *Xb)
119{
120	register unsigned int tmp, A, B, C, D;
121	unsigned int X[16];
122	int i;
123
124	for (i = 0; i < 16; ++i) {
125		X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24);
126		Xb += 4;
127	}
128
129	A = MDp->buffer[0];
130	B = MDp->buffer[1];
131	C = MDp->buffer[2];
132	D = MDp->buffer[3];
133	/* Update the message digest buffer */
134	ff(A, B, C, D,  0, fs1); /* Round 1 */
135	ff(D, A, B, C,  1, fs2);
136	ff(C, D, A, B,  2, fs3);
137	ff(B, C, D, A,  3, fs4);
138	ff(A, B, C, D,  4, fs1);
139	ff(D, A, B, C,  5, fs2);
140	ff(C, D, A, B,  6, fs3);
141	ff(B, C, D, A,  7, fs4);
142	ff(A, B, C, D,  8, fs1);
143	ff(D, A, B, C,  9, fs2);
144	ff(C, D, A, B, 10, fs3);
145	ff(B, C, D, A, 11, fs4);
146	ff(A, B, C, D, 12, fs1);
147	ff(D, A, B, C, 13, fs2);
148	ff(C, D, A, B, 14, fs3);
149	ff(B, C, D, A, 15, fs4);
150	gg(A, B, C, D,  0, gs1); /* Round 2 */
151	gg(D, A, B, C,  4, gs2);
152	gg(C, D, A, B,  8, gs3);
153	gg(B, C, D, A, 12, gs4);
154	gg(A, B, C, D,  1, gs1);
155	gg(D, A, B, C,  5, gs2);
156	gg(C, D, A, B,  9, gs3);
157	gg(B, C, D, A, 13, gs4);
158	gg(A, B, C, D,  2, gs1);
159	gg(D, A, B, C,  6, gs2);
160	gg(C, D, A, B, 10, gs3);
161	gg(B, C, D, A, 14, gs4);
162	gg(A, B, C, D,  3, gs1);
163	gg(D, A, B, C,  7, gs2);
164	gg(C, D, A, B, 11, gs3);
165	gg(B, C, D, A, 15, gs4);
166	hh(A, B, C, D,  0, hs1); /* Round 3 */
167	hh(D, A, B, C,  8, hs2);
168	hh(C, D, A, B,  4, hs3);
169	hh(B, C, D, A, 12, hs4);
170	hh(A, B, C, D,  2, hs1);
171	hh(D, A, B, C, 10, hs2);
172	hh(C, D, A, B,  6, hs3);
173	hh(B, C, D, A, 14, hs4);
174	hh(A, B, C, D,  1, hs1);
175	hh(D, A, B, C,  9, hs2);
176	hh(C, D, A, B,  5, hs3);
177	hh(B, C, D, A, 13, hs4);
178	hh(A, B, C, D,  3, hs1);
179	hh(D, A, B, C, 11, hs2);
180	hh(C, D, A, B,  7, hs3);
181	hh(B, C, D, A, 15, hs4);
182	MDp->buffer[0] += A;
183	MDp->buffer[1] += B;
184	MDp->buffer[2] += C;
185	MDp->buffer[3] += D;
186}
187
188/* MD4Update(MDp,X,count)
189 * Input: X -- a pointer to an array of unsigned characters.
190 *        count -- the number of bits of X to use.
191 *          (if not a multiple of 8, uses high bits of last byte.)
192 * Update MDp using the number of bits of X given by count.
193 * This is the basic input routine for an MD4 user.
194 * The routine completes the MD computation when count < 512, so
195 * every MD computation should end with one call to MD4Update with a
196 * count less than 512.  A call with count 0 will be ignored if the
197 * MD has already been terminated (done != 0), so an extra call with
198 * count 0 can be given as a "courtesy close" to force termination
199 * if desired.
200 */
201void
202BCMROMFN(MD4Update)(MD4_CTX *MDp, unsigned char *X, unsigned int count)
203{
204	unsigned int i, tmp, bit, byte, mask;
205	unsigned char XX[64];
206	unsigned char *p;
207
208	/* return with no error if this is a courtesy close with count
209	 * zero and MDp->done is true.
210	 */
211	if (count == 0 && MDp->done) return;
212	/* check to see if MD is already done and report error */
213	if (MDp->done) {
214		return;
215	}
216
217	/* Add count to MDp->count */
218	tmp = count;
219	p = MDp->count;
220	while (tmp) {
221		tmp += *p;
222		*p++ = (unsigned char) tmp;
223		tmp = tmp >> 8;
224	}
225
226	/* Process data */
227	if (count == 512) {
228		/* Full block of data to handle */
229		MDblock(MDp, X);
230	} else if (count > 512) {
231		/* Check for count too large */
232		return;
233	} else {
234		/* partial block -- must be last block so finish up */
235
236		/* Find out how many bytes and residual bits there are */
237		byte = count >> 3;
238		bit =  count & 7;
239		/* Copy X into XX since we need to modify it */
240		for (i = 0; i <= byte; i++)
241			XX[i] = X[i];
242		for (i = byte + 1; i < 64; i++)
243			XX[i] = 0;
244		/* Add padding '1' bit and low-order zeros in last byte */
245		mask = 1 << (7 - bit);
246		XX[byte] = (XX[byte] | mask) & ~(mask - 1);
247		/* If room for bit count, finish up with this block */
248		if (byte <= 55) {
249			for (i = 0; i < 8; i++)
250				XX[56 + i] = MDp->count[i];
251			MDblock(MDp, XX);
252		} else {
253			/* need to do two blocks to finish up */
254			MDblock(MDp, XX);
255			for (i = 0; i < 56; i++)
256				XX[i] = 0;
257			for (i = 0; i < 8; i++)
258				XX[56 + i] = MDp->count[i];
259			MDblock(MDp, XX);
260		}
261		/* Set flag saying we're done with MD computation */
262		MDp->done = 1;
263	}
264}
265
266/*
267 * Finish up MD4 computation and return message digest.
268 */
269void
270BCMROMFN(MD4Final)(unsigned char *buf, MD4_CTX *MD)
271{
272	int i, j;
273	unsigned int w;
274
275	MD4Update(MD, NULL, 0);
276	for (i = 0; i < 4; ++i) {
277		w = MD->buffer[i];
278		for (j = 0; j < 4; ++j) {
279			*buf++ = (unsigned char) w;
280			w >>= 8;
281		}
282	}
283}
284
285/*
286 * End of md4.c
287 */
288