Resync with broadcom drivers 5.100.138.20 and utilities.
[tomato.git] / release / src-rt / bcmcrypto / md4.c
blob8934ca07e02c7f5e47b8ee67885b5c4e9c6842db
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.
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 * ********************************************************************
11 * Copyright (C) 2010, Broadcom Corporation
12 * All Rights Reserved.
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.
19 * $Id: md4.c,v 1.5 2006-06-14 21:07:54 Exp $
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)
43 /* Implementation notes:
44 * This implementation assumes that ints are 32-bit quantities.
47 #include <typedefs.h>
49 #include <bcmcrypto/md4.h>
51 #ifndef BCMDRIVER
52 #include <stdio.h>
53 #endif
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.
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
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.
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)
94 /* MD4Init(MDp)
95 * Initialize message digest buffer MDp.
96 * This is a user-callable routine.
98 void
99 BCMROMFN(MD4Init)(MD4_CTX *MDp)
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;
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.
117 static void
118 MDblock(MD4_CTX *MDp, unsigned char *Xb)
120 register unsigned int tmp, A, B, C, D;
121 unsigned int X[16];
122 int i;
124 for (i = 0; i < 16; ++i) {
125 X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24);
126 Xb += 4;
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;
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.
201 void
202 BCMROMFN(MD4Update)(MD4_CTX *MDp, unsigned char *X, unsigned int count)
204 unsigned int i, tmp, bit, byte, mask;
205 unsigned char XX[64];
206 unsigned char *p;
208 /* return with no error if this is a courtesy close with count
209 * zero and MDp->done is true.
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;
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;
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 */
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);
261 /* Set flag saying we're done with MD computation */
262 MDp->done = 1;
267 * Finish up MD4 computation and return message digest.
269 void
270 BCMROMFN(MD4Final)(unsigned char *buf, MD4_CTX *MD)
272 int i, j;
273 unsigned int w;
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;
286 * End of md4.c