1 /*
2 *
3 */
4
5 #include "beecrypt/md4.h"
6 #include "beecrypt/endianness.h"
7
8 /*@unchecked@*/ /*@observer@*/
9 static uint32_t md4hinit[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 };
10
11 /*@-sizeoftype@*/
12 /*@unchecked@*/ /*@observer@*/
13 const hashFunction md4 = {
14 .name = "MD4",
15 .paramsize = sizeof(md4Param),
16 .blocksize = 64,
17 .digestsize = 16,
18 .reset = (hashFunctionReset) md4Reset,
19 .update = (hashFunctionUpdate) md4Update,
20 .digest = (hashFunctionDigest) md4Digest,
21 };
22 /*@=sizeoftype@*/
23
md4Reset(md4Param * mp)24 int md4Reset(md4Param* mp)
25 {
26 /*@-sizeoftype@*/
27 memcpy(mp->h, md4hinit, 4 * sizeof(uint32_t));
28 memset(mp->data, 0, 16 * sizeof(uint32_t));
29 /*@=sizeoftype@*/
30 #if (MP_WBITS == 64)
31 mpzero(1, mp->length);
32 #elif (MP_WBITS == 32)
33 mpzero(2, mp->length);
34 #else
35 # error
36 #endif
37 mp->offset = 0;
38 return 0;
39 }
40
41 #define F(x, y, z) (z ^ (x & (y ^ z)))
42 #define G(x, y, z) ((x & y) | (z & (x | y)))
43 #define H(x, y, z) ((x) ^ (y) ^ (z))
44
45 #define FF(a, b, c, d, w, s) \
46 a = ROTL32((d^(b&(c^d))) + a + w, s);
47
48 #define GG(a, b, c, d, w, s) \
49 a = ROTL32(((b&c)|(d&(b|c))) + a + w + 0x5a827999U, s);
50
51 #define HH(a, b, c, d, w, s) \
52 a = ROTL32((b^c^d) + a + w + 0x6ed9eba1U, s);
53
54 #ifndef ASM_MD4PROCESS
md4Process(md4Param * mp)55 void md4Process(md4Param *mp)
56 /*@modifies mp @*/
57 {
58 uint32_t a, b, c, d;
59
60 register uint32_t* w;
61 #ifdef WORDS_BIGENDIAN
62 register byte t;
63 #endif
64
65 w = mp->data;
66 #ifdef WORDS_BIGENDIAN
67 t = 16;
68 while (t--)
69 {
70 register uint32_t temp = swapu32(*w);
71 *(w++) = temp;
72 }
73 w = mp->data;
74 #endif
75
76 a = mp->h[0]; b = mp->h[1]; c = mp->h[2]; d = mp->h[3];
77
78 FF (a, b, c, d, w[ 0], 3);
79 FF (d, a, b, c, w[ 1], 7);
80 FF (c, d, a, b, w[ 2], 11);
81 FF (b, c, d, a, w[ 3], 19);
82 FF (a, b, c, d, w[ 4], 3);
83 FF (d, a, b, c, w[ 5], 7);
84 FF (c, d, a, b, w[ 6], 11);
85 FF (b, c, d, a, w[ 7], 19);
86 FF (a, b, c, d, w[ 8], 3);
87 FF (d, a, b, c, w[ 9], 7);
88 FF (c, d, a, b, w[10], 11);
89 FF (b, c, d, a, w[11], 19);
90 FF (a, b, c, d, w[12], 3);
91 FF (d, a, b, c, w[13], 7);
92 FF (c, d, a, b, w[14], 11);
93 FF (b, c, d, a, w[15], 19);
94
95 GG (a, b, c, d, w[ 0], 3);
96 GG (d, a, b, c, w[ 4], 5);
97 GG (c, d, a, b, w[ 8], 9);
98 GG (b, c, d, a, w[12], 13);
99 GG (a, b, c, d, w[ 1], 3);
100 GG (d, a, b, c, w[ 5], 5);
101 GG (c, d, a, b, w[ 9], 9);
102 GG (b, c, d, a, w[13], 13);
103 GG (a, b, c, d, w[ 2], 3);
104 GG (d, a, b, c, w[ 6], 5);
105 GG (c, d, a, b, w[10], 9);
106 GG (b, c, d, a, w[14], 13);
107 GG (a, b, c, d, w[ 3], 3);
108 GG (d, a, b, c, w[ 7], 5);
109 GG (c, d, a, b, w[11], 9);
110 GG (b, c, d, a, w[15], 13);
111
112 HH (a, b, c, d, w[ 0], 3);
113 HH (d, a, b, c, w[ 8], 9);
114 HH (c, d, a, b, w[ 4], 11);
115 HH (b, c, d, a, w[12], 15);
116 HH (a, b, c, d, w[ 2], 3);
117 HH (d, a, b, c, w[10], 9);
118 HH (c, d, a, b, w[ 6], 11);
119 HH (b, c, d, a, w[14], 15);
120 HH (a, b, c, d, w[ 1], 3);
121 HH (d, a, b, c, w[ 9], 9);
122 HH (c, d, a, b, w[ 5], 11);
123 HH (b, c, d, a, w[13], 15);
124 HH (a, b, c, d, w[ 3], 3);
125 HH (d, a, b, c, w[11], 9);
126 HH (c, d, a, b, w[ 7], 11);
127 HH (b, c, d, a, w[15], 15);
128
129 mp->h[0] += a;
130 mp->h[1] += b;
131 mp->h[2] += c;
132 mp->h[3] += d;
133 }
134 #endif
135
md4Update(md4Param * mp,const byte * data,size_t size)136 int md4Update(md4Param* mp, const byte* data, size_t size)
137 {
138 register uint32_t proclength;
139
140 #if (MP_WBITS == 64)
141 mpw add[1];
142 mpsetw(1, add, size);
143 mplshift(1, add, 3);
144 (void) mpadd(1, mp->length, add);
145 #elif (MP_WBITS == 32)
146 mpw add[2];
147 mpsetw(2, add, size);
148 mplshift(2, add, 3);
149 (void) mpadd(2, mp->length, add);
150 #else
151 # error
152 #endif
153
154 while (size > 0)
155 {
156 proclength = ((mp->offset + size) > 64U) ? (64U - mp->offset) : size;
157 /*@-mayaliasunique@*/
158 memcpy(((byte *) mp->data) + mp->offset, data, proclength);
159 /*@=mayaliasunique@*/
160 size -= proclength;
161 data += proclength;
162 mp->offset += proclength;
163
164 if (mp->offset == 64U)
165 {
166 md4Process(mp);
167 mp->offset = 0;
168 }
169 }
170 return 0;
171 }
172
md4Finish(md4Param * mp)173 static void md4Finish(md4Param* mp)
174 /*@modifies mp @*/
175 {
176 register byte *ptr = ((byte *) mp->data) + mp->offset++;
177
178 *(ptr++) = 0x80;
179
180 if (mp->offset > 56)
181 {
182 while (mp->offset++ < 64)
183 *(ptr++) = 0;
184
185 md4Process(mp);
186 mp->offset = 0;
187 }
188
189 ptr = ((byte *) mp->data) + mp->offset;
190 while (mp->offset++ < 56)
191 *(ptr++) = 0;
192
193 #if (MP_WBITS == 64)
194 ptr[0] = (byte)(mp->length[0] );
195 ptr[1] = (byte)(mp->length[0] >> 8);
196 ptr[2] = (byte)(mp->length[0] >> 16);
197 ptr[3] = (byte)(mp->length[0] >> 24);
198 ptr[4] = (byte)(mp->length[0] >> 32);
199 ptr[5] = (byte)(mp->length[0] >> 40);
200 ptr[6] = (byte)(mp->length[0] >> 48);
201 ptr[7] = (byte)(mp->length[0] >> 56);
202 #elif (MP_WBITS == 32)
203 ptr[0] = (byte)(mp->length[1] );
204 ptr[1] = (byte)(mp->length[1] >> 8);
205 ptr[2] = (byte)(mp->length[1] >> 16);
206 ptr[3] = (byte)(mp->length[1] >> 24);
207 ptr[4] = (byte)(mp->length[0] );
208 ptr[5] = (byte)(mp->length[0] >> 8);
209 ptr[6] = (byte)(mp->length[0] >> 16);
210 ptr[7] = (byte)(mp->length[0] >> 24);
211 #else
212 # error
213 #endif
214
215 md4Process(mp);
216
217 mp->offset = 0;
218 }
219
220 /*@-protoparammatch@*/
md4Digest(md4Param * mp,byte * data)221 int md4Digest(md4Param* mp, byte* data)
222 {
223 md4Finish(mp);
224
225 /* encode 4 integers little-endian style */
226 data[ 0] = (byte)(mp->h[0] );
227 data[ 1] = (byte)(mp->h[0] >> 8);
228 data[ 2] = (byte)(mp->h[0] >> 16);
229 data[ 3] = (byte)(mp->h[0] >> 24);
230 data[ 4] = (byte)(mp->h[1] );
231 data[ 5] = (byte)(mp->h[1] >> 8);
232 data[ 6] = (byte)(mp->h[1] >> 16);
233 data[ 7] = (byte)(mp->h[1] >> 24);
234 data[ 8] = (byte)(mp->h[2] );
235 data[ 9] = (byte)(mp->h[2] >> 8);
236 data[10] = (byte)(mp->h[2] >> 16);
237 data[11] = (byte)(mp->h[2] >> 24);
238 data[12] = (byte)(mp->h[3] );
239 data[13] = (byte)(mp->h[3] >> 8);
240 data[14] = (byte)(mp->h[3] >> 16);
241 data[15] = (byte)(mp->h[3] >> 24);
242
243 (void) md4Reset(mp);
244 return 0;
245 }
246 /*@=protoparammatch@*/
247