/src/nss/lib/freebl/md5.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifdef FREEBL_NO_DEPEND |
6 | | #include "stubs.h" |
7 | | #endif |
8 | | |
9 | | #include "prerr.h" |
10 | | #include "secerr.h" |
11 | | |
12 | | #include "prtypes.h" |
13 | | #include "prlong.h" |
14 | | |
15 | | #include "blapi.h" |
16 | | #include "blapii.h" |
17 | | |
18 | 0 | #define MD5_HASH_LEN 16 |
19 | 0 | #define MD5_BUFFER_SIZE 64 |
20 | 0 | #define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8) |
21 | | |
22 | 0 | #define CV0_1 0x67452301 |
23 | 0 | #define CV0_2 0xefcdab89 |
24 | 0 | #define CV0_3 0x98badcfe |
25 | 0 | #define CV0_4 0x10325476 |
26 | | |
27 | | #define T1_0 0xd76aa478 |
28 | | #define T1_1 0xe8c7b756 |
29 | | #define T1_2 0x242070db |
30 | | #define T1_3 0xc1bdceee |
31 | | #define T1_4 0xf57c0faf |
32 | | #define T1_5 0x4787c62a |
33 | | #define T1_6 0xa8304613 |
34 | | #define T1_7 0xfd469501 |
35 | | #define T1_8 0x698098d8 |
36 | | #define T1_9 0x8b44f7af |
37 | | #define T1_10 0xffff5bb1 |
38 | | #define T1_11 0x895cd7be |
39 | | #define T1_12 0x6b901122 |
40 | | #define T1_13 0xfd987193 |
41 | | #define T1_14 0xa679438e |
42 | | #define T1_15 0x49b40821 |
43 | | |
44 | | #define T2_0 0xf61e2562 |
45 | | #define T2_1 0xc040b340 |
46 | | #define T2_2 0x265e5a51 |
47 | | #define T2_3 0xe9b6c7aa |
48 | | #define T2_4 0xd62f105d |
49 | | #define T2_5 0x02441453 |
50 | | #define T2_6 0xd8a1e681 |
51 | | #define T2_7 0xe7d3fbc8 |
52 | | #define T2_8 0x21e1cde6 |
53 | | #define T2_9 0xc33707d6 |
54 | | #define T2_10 0xf4d50d87 |
55 | | #define T2_11 0x455a14ed |
56 | | #define T2_12 0xa9e3e905 |
57 | | #define T2_13 0xfcefa3f8 |
58 | | #define T2_14 0x676f02d9 |
59 | | #define T2_15 0x8d2a4c8a |
60 | | |
61 | | #define T3_0 0xfffa3942 |
62 | | #define T3_1 0x8771f681 |
63 | | #define T3_2 0x6d9d6122 |
64 | | #define T3_3 0xfde5380c |
65 | | #define T3_4 0xa4beea44 |
66 | | #define T3_5 0x4bdecfa9 |
67 | | #define T3_6 0xf6bb4b60 |
68 | | #define T3_7 0xbebfbc70 |
69 | | #define T3_8 0x289b7ec6 |
70 | | #define T3_9 0xeaa127fa |
71 | | #define T3_10 0xd4ef3085 |
72 | | #define T3_11 0x04881d05 |
73 | | #define T3_12 0xd9d4d039 |
74 | | #define T3_13 0xe6db99e5 |
75 | | #define T3_14 0x1fa27cf8 |
76 | | #define T3_15 0xc4ac5665 |
77 | | |
78 | | #define T4_0 0xf4292244 |
79 | | #define T4_1 0x432aff97 |
80 | | #define T4_2 0xab9423a7 |
81 | | #define T4_3 0xfc93a039 |
82 | | #define T4_4 0x655b59c3 |
83 | | #define T4_5 0x8f0ccc92 |
84 | | #define T4_6 0xffeff47d |
85 | | #define T4_7 0x85845dd1 |
86 | | #define T4_8 0x6fa87e4f |
87 | | #define T4_9 0xfe2ce6e0 |
88 | | #define T4_10 0xa3014314 |
89 | | #define T4_11 0x4e0811a1 |
90 | | #define T4_12 0xf7537e82 |
91 | | #define T4_13 0xbd3af235 |
92 | | #define T4_14 0x2ad7d2bb |
93 | | #define T4_15 0xeb86d391 |
94 | | |
95 | | #define R1B0 0 |
96 | | #define R1B1 1 |
97 | | #define R1B2 2 |
98 | | #define R1B3 3 |
99 | | #define R1B4 4 |
100 | | #define R1B5 5 |
101 | | #define R1B6 6 |
102 | | #define R1B7 7 |
103 | | #define R1B8 8 |
104 | | #define R1B9 9 |
105 | | #define R1B10 10 |
106 | | #define R1B11 11 |
107 | | #define R1B12 12 |
108 | | #define R1B13 13 |
109 | | #define R1B14 14 |
110 | | #define R1B15 15 |
111 | | |
112 | | #define R2B0 1 |
113 | | #define R2B1 6 |
114 | | #define R2B2 11 |
115 | | #define R2B3 0 |
116 | | #define R2B4 5 |
117 | | #define R2B5 10 |
118 | | #define R2B6 15 |
119 | | #define R2B7 4 |
120 | | #define R2B8 9 |
121 | | #define R2B9 14 |
122 | | #define R2B10 3 |
123 | | #define R2B11 8 |
124 | | #define R2B12 13 |
125 | | #define R2B13 2 |
126 | | #define R2B14 7 |
127 | | #define R2B15 12 |
128 | | |
129 | | #define R3B0 5 |
130 | | #define R3B1 8 |
131 | | #define R3B2 11 |
132 | | #define R3B3 14 |
133 | | #define R3B4 1 |
134 | | #define R3B5 4 |
135 | | #define R3B6 7 |
136 | | #define R3B7 10 |
137 | | #define R3B8 13 |
138 | | #define R3B9 0 |
139 | | #define R3B10 3 |
140 | | #define R3B11 6 |
141 | | #define R3B12 9 |
142 | | #define R3B13 12 |
143 | | #define R3B14 15 |
144 | | #define R3B15 2 |
145 | | |
146 | | #define R4B0 0 |
147 | | #define R4B1 7 |
148 | | #define R4B2 14 |
149 | | #define R4B3 5 |
150 | | #define R4B4 12 |
151 | | #define R4B5 3 |
152 | | #define R4B6 10 |
153 | | #define R4B7 1 |
154 | | #define R4B8 8 |
155 | | #define R4B9 15 |
156 | | #define R4B10 6 |
157 | | #define R4B11 13 |
158 | | #define R4B12 4 |
159 | | #define R4B13 11 |
160 | | #define R4B14 2 |
161 | | #define R4B15 9 |
162 | | |
163 | | #define S1_0 7 |
164 | | #define S1_1 12 |
165 | | #define S1_2 17 |
166 | | #define S1_3 22 |
167 | | |
168 | | #define S2_0 5 |
169 | | #define S2_1 9 |
170 | | #define S2_2 14 |
171 | | #define S2_3 20 |
172 | | |
173 | | #define S3_0 4 |
174 | | #define S3_1 11 |
175 | | #define S3_2 16 |
176 | | #define S3_3 23 |
177 | | |
178 | | #define S4_0 6 |
179 | | #define S4_1 10 |
180 | | #define S4_2 15 |
181 | | #define S4_3 21 |
182 | | |
183 | | struct MD5ContextStr { |
184 | | PRUint32 lsbInput; |
185 | | PRUint32 msbInput; |
186 | | PRUint32 cv[4]; |
187 | | union { |
188 | | PRUint8 b[64]; |
189 | | PRUint32 w[16]; |
190 | | } u; |
191 | | }; |
192 | | |
193 | 0 | #define inBuf u.b |
194 | | |
195 | | SECStatus |
196 | | MD5_Hash(unsigned char *dest, const char *src) |
197 | 0 | { |
198 | 0 | return MD5_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); |
199 | 0 | } |
200 | | |
201 | | SECStatus |
202 | | MD5_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length) |
203 | 0 | { |
204 | 0 | unsigned int len; |
205 | 0 | MD5Context cx; |
206 | |
|
207 | 0 | MD5_Begin(&cx); |
208 | 0 | MD5_Update(&cx, src, src_length); |
209 | 0 | MD5_End(&cx, dest, &len, MD5_HASH_LEN); |
210 | 0 | memset(&cx, 0, sizeof cx); |
211 | 0 | return SECSuccess; |
212 | 0 | } |
213 | | |
214 | | MD5Context * |
215 | | MD5_NewContext(void) |
216 | 0 | { |
217 | | /* no need to ZAlloc, MD5_Begin will init the context */ |
218 | 0 | MD5Context *cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context)); |
219 | 0 | if (cx == NULL) { |
220 | 0 | PORT_SetError(PR_OUT_OF_MEMORY_ERROR); |
221 | 0 | return NULL; |
222 | 0 | } |
223 | 0 | return cx; |
224 | 0 | } |
225 | | |
226 | | void |
227 | | MD5_DestroyContext(MD5Context *cx, PRBool freeit) |
228 | 0 | { |
229 | 0 | memset(cx, 0, sizeof *cx); |
230 | 0 | if (freeit) { |
231 | 0 | PORT_Free(cx); |
232 | 0 | } |
233 | 0 | } |
234 | | |
235 | | void |
236 | | MD5_Begin(MD5Context *cx) |
237 | 0 | { |
238 | 0 | cx->lsbInput = 0; |
239 | 0 | cx->msbInput = 0; |
240 | | /* memset(cx->inBuf, 0, sizeof(cx->inBuf)); */ |
241 | 0 | cx->cv[0] = CV0_1; |
242 | 0 | cx->cv[1] = CV0_2; |
243 | 0 | cx->cv[2] = CV0_3; |
244 | 0 | cx->cv[3] = CV0_4; |
245 | 0 | } |
246 | | |
247 | 0 | #define cls(i32, s) (tmp = i32, tmp << s | tmp >> (32 - s)) |
248 | | |
249 | | #if defined(SOLARIS) || defined(HPUX) |
250 | | #define addto64(sumhigh, sumlow, addend) \ |
251 | | sumlow += addend; \ |
252 | | sumhigh += (sumlow < addend); |
253 | | #else |
254 | | #define addto64(sumhigh, sumlow, addend) \ |
255 | 0 | sumlow += addend; \ |
256 | 0 | if (sumlow < addend) \ |
257 | 0 | ++sumhigh; |
258 | | #endif |
259 | | |
260 | | #define MASK 0x00ff00ff |
261 | | #ifdef IS_LITTLE_ENDIAN |
262 | | #define lendian(i32) \ |
263 | 0 | (i32) |
264 | | #else |
265 | | #define lendian(i32) \ |
266 | | (tmp = (i32 >> 16) | (i32 << 16), ((tmp & MASK) << 8) | ((tmp >> 8) & MASK)) |
267 | | #endif |
268 | | |
269 | | #ifndef IS_LITTLE_ENDIAN |
270 | | |
271 | | #define lebytes(b4) \ |
272 | | ((b4)[3] << 24 | (b4)[2] << 16 | (b4)[1] << 8 | (b4)[0]) |
273 | | |
274 | | static void |
275 | | md5_prep_state_le(MD5Context *cx) |
276 | | { |
277 | | PRUint32 tmp; |
278 | | cx->u.w[0] = lendian(cx->u.w[0]); |
279 | | cx->u.w[1] = lendian(cx->u.w[1]); |
280 | | cx->u.w[2] = lendian(cx->u.w[2]); |
281 | | cx->u.w[3] = lendian(cx->u.w[3]); |
282 | | cx->u.w[4] = lendian(cx->u.w[4]); |
283 | | cx->u.w[5] = lendian(cx->u.w[5]); |
284 | | cx->u.w[6] = lendian(cx->u.w[6]); |
285 | | cx->u.w[7] = lendian(cx->u.w[7]); |
286 | | cx->u.w[8] = lendian(cx->u.w[8]); |
287 | | cx->u.w[9] = lendian(cx->u.w[9]); |
288 | | cx->u.w[10] = lendian(cx->u.w[10]); |
289 | | cx->u.w[11] = lendian(cx->u.w[11]); |
290 | | cx->u.w[12] = lendian(cx->u.w[12]); |
291 | | cx->u.w[13] = lendian(cx->u.w[13]); |
292 | | cx->u.w[14] = lendian(cx->u.w[14]); |
293 | | cx->u.w[15] = lendian(cx->u.w[15]); |
294 | | } |
295 | | |
296 | | static void |
297 | | md5_prep_buffer_le(MD5Context *cx, const PRUint8 *beBuf) |
298 | | { |
299 | | cx->u.w[0] = lebytes(&beBuf[0]); |
300 | | cx->u.w[1] = lebytes(&beBuf[4]); |
301 | | cx->u.w[2] = lebytes(&beBuf[8]); |
302 | | cx->u.w[3] = lebytes(&beBuf[12]); |
303 | | cx->u.w[4] = lebytes(&beBuf[16]); |
304 | | cx->u.w[5] = lebytes(&beBuf[20]); |
305 | | cx->u.w[6] = lebytes(&beBuf[24]); |
306 | | cx->u.w[7] = lebytes(&beBuf[28]); |
307 | | cx->u.w[8] = lebytes(&beBuf[32]); |
308 | | cx->u.w[9] = lebytes(&beBuf[36]); |
309 | | cx->u.w[10] = lebytes(&beBuf[40]); |
310 | | cx->u.w[11] = lebytes(&beBuf[44]); |
311 | | cx->u.w[12] = lebytes(&beBuf[48]); |
312 | | cx->u.w[13] = lebytes(&beBuf[52]); |
313 | | cx->u.w[14] = lebytes(&beBuf[56]); |
314 | | cx->u.w[15] = lebytes(&beBuf[60]); |
315 | | } |
316 | | #endif |
317 | | |
318 | | #define F(X, Y, Z) \ |
319 | | ((X & Y) | ((~X) & Z)) |
320 | | |
321 | | #define G(X, Y, Z) \ |
322 | | ((X & Z) | (Y & (~Z))) |
323 | | |
324 | | #define H(X, Y, Z) \ |
325 | | (X ^ Y ^ Z) |
326 | | |
327 | | #define I(X, Y, Z) \ |
328 | | (Y ^ (X | (~Z))) |
329 | | |
330 | | #define FF(a, b, c, d, bufint, s, ti) \ |
331 | 0 | a = b + cls(a + F(b, c, d) + bufint + ti, s) |
332 | | |
333 | | #define GG(a, b, c, d, bufint, s, ti) \ |
334 | 0 | a = b + cls(a + G(b, c, d) + bufint + ti, s) |
335 | | |
336 | | #define HH(a, b, c, d, bufint, s, ti) \ |
337 | 0 | a = b + cls(a + H(b, c, d) + bufint + ti, s) |
338 | | |
339 | | #define II(a, b, c, d, bufint, s, ti) \ |
340 | 0 | a = b + cls(a + I(b, c, d) + bufint + ti, s) |
341 | | |
342 | | static void NO_SANITIZE_ALIGNMENT |
343 | | md5_compress(MD5Context *cx, const PRUint32 *wBuf) |
344 | 0 | { |
345 | 0 | PRUint32 a, b, c, d; |
346 | 0 | PRUint32 tmp; |
347 | 0 | a = cx->cv[0]; |
348 | 0 | b = cx->cv[1]; |
349 | 0 | c = cx->cv[2]; |
350 | 0 | d = cx->cv[3]; |
351 | 0 | FF(a, b, c, d, wBuf[R1B0], S1_0, T1_0); |
352 | 0 | FF(d, a, b, c, wBuf[R1B1], S1_1, T1_1); |
353 | 0 | FF(c, d, a, b, wBuf[R1B2], S1_2, T1_2); |
354 | 0 | FF(b, c, d, a, wBuf[R1B3], S1_3, T1_3); |
355 | 0 | FF(a, b, c, d, wBuf[R1B4], S1_0, T1_4); |
356 | 0 | FF(d, a, b, c, wBuf[R1B5], S1_1, T1_5); |
357 | 0 | FF(c, d, a, b, wBuf[R1B6], S1_2, T1_6); |
358 | 0 | FF(b, c, d, a, wBuf[R1B7], S1_3, T1_7); |
359 | 0 | FF(a, b, c, d, wBuf[R1B8], S1_0, T1_8); |
360 | 0 | FF(d, a, b, c, wBuf[R1B9], S1_1, T1_9); |
361 | 0 | FF(c, d, a, b, wBuf[R1B10], S1_2, T1_10); |
362 | 0 | FF(b, c, d, a, wBuf[R1B11], S1_3, T1_11); |
363 | 0 | FF(a, b, c, d, wBuf[R1B12], S1_0, T1_12); |
364 | 0 | FF(d, a, b, c, wBuf[R1B13], S1_1, T1_13); |
365 | 0 | FF(c, d, a, b, wBuf[R1B14], S1_2, T1_14); |
366 | 0 | FF(b, c, d, a, wBuf[R1B15], S1_3, T1_15); |
367 | 0 | GG(a, b, c, d, wBuf[R2B0], S2_0, T2_0); |
368 | 0 | GG(d, a, b, c, wBuf[R2B1], S2_1, T2_1); |
369 | 0 | GG(c, d, a, b, wBuf[R2B2], S2_2, T2_2); |
370 | 0 | GG(b, c, d, a, wBuf[R2B3], S2_3, T2_3); |
371 | 0 | GG(a, b, c, d, wBuf[R2B4], S2_0, T2_4); |
372 | 0 | GG(d, a, b, c, wBuf[R2B5], S2_1, T2_5); |
373 | 0 | GG(c, d, a, b, wBuf[R2B6], S2_2, T2_6); |
374 | 0 | GG(b, c, d, a, wBuf[R2B7], S2_3, T2_7); |
375 | 0 | GG(a, b, c, d, wBuf[R2B8], S2_0, T2_8); |
376 | 0 | GG(d, a, b, c, wBuf[R2B9], S2_1, T2_9); |
377 | 0 | GG(c, d, a, b, wBuf[R2B10], S2_2, T2_10); |
378 | 0 | GG(b, c, d, a, wBuf[R2B11], S2_3, T2_11); |
379 | 0 | GG(a, b, c, d, wBuf[R2B12], S2_0, T2_12); |
380 | 0 | GG(d, a, b, c, wBuf[R2B13], S2_1, T2_13); |
381 | 0 | GG(c, d, a, b, wBuf[R2B14], S2_2, T2_14); |
382 | 0 | GG(b, c, d, a, wBuf[R2B15], S2_3, T2_15); |
383 | 0 | HH(a, b, c, d, wBuf[R3B0], S3_0, T3_0); |
384 | 0 | HH(d, a, b, c, wBuf[R3B1], S3_1, T3_1); |
385 | 0 | HH(c, d, a, b, wBuf[R3B2], S3_2, T3_2); |
386 | 0 | HH(b, c, d, a, wBuf[R3B3], S3_3, T3_3); |
387 | 0 | HH(a, b, c, d, wBuf[R3B4], S3_0, T3_4); |
388 | 0 | HH(d, a, b, c, wBuf[R3B5], S3_1, T3_5); |
389 | 0 | HH(c, d, a, b, wBuf[R3B6], S3_2, T3_6); |
390 | 0 | HH(b, c, d, a, wBuf[R3B7], S3_3, T3_7); |
391 | 0 | HH(a, b, c, d, wBuf[R3B8], S3_0, T3_8); |
392 | 0 | HH(d, a, b, c, wBuf[R3B9], S3_1, T3_9); |
393 | 0 | HH(c, d, a, b, wBuf[R3B10], S3_2, T3_10); |
394 | 0 | HH(b, c, d, a, wBuf[R3B11], S3_3, T3_11); |
395 | 0 | HH(a, b, c, d, wBuf[R3B12], S3_0, T3_12); |
396 | 0 | HH(d, a, b, c, wBuf[R3B13], S3_1, T3_13); |
397 | 0 | HH(c, d, a, b, wBuf[R3B14], S3_2, T3_14); |
398 | 0 | HH(b, c, d, a, wBuf[R3B15], S3_3, T3_15); |
399 | 0 | II(a, b, c, d, wBuf[R4B0], S4_0, T4_0); |
400 | 0 | II(d, a, b, c, wBuf[R4B1], S4_1, T4_1); |
401 | 0 | II(c, d, a, b, wBuf[R4B2], S4_2, T4_2); |
402 | 0 | II(b, c, d, a, wBuf[R4B3], S4_3, T4_3); |
403 | 0 | II(a, b, c, d, wBuf[R4B4], S4_0, T4_4); |
404 | 0 | II(d, a, b, c, wBuf[R4B5], S4_1, T4_5); |
405 | 0 | II(c, d, a, b, wBuf[R4B6], S4_2, T4_6); |
406 | 0 | II(b, c, d, a, wBuf[R4B7], S4_3, T4_7); |
407 | 0 | II(a, b, c, d, wBuf[R4B8], S4_0, T4_8); |
408 | 0 | II(d, a, b, c, wBuf[R4B9], S4_1, T4_9); |
409 | 0 | II(c, d, a, b, wBuf[R4B10], S4_2, T4_10); |
410 | 0 | II(b, c, d, a, wBuf[R4B11], S4_3, T4_11); |
411 | 0 | II(a, b, c, d, wBuf[R4B12], S4_0, T4_12); |
412 | 0 | II(d, a, b, c, wBuf[R4B13], S4_1, T4_13); |
413 | 0 | II(c, d, a, b, wBuf[R4B14], S4_2, T4_14); |
414 | 0 | II(b, c, d, a, wBuf[R4B15], S4_3, T4_15); |
415 | 0 | cx->cv[0] += a; |
416 | 0 | cx->cv[1] += b; |
417 | 0 | cx->cv[2] += c; |
418 | 0 | cx->cv[3] += d; |
419 | 0 | } |
420 | | |
421 | | void |
422 | | MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen) |
423 | 0 | { |
424 | 0 | PRUint32 bytesToConsume; |
425 | 0 | PRUint32 inBufIndex = cx->lsbInput & 63; |
426 | 0 | const PRUint32 *wBuf; |
427 | | |
428 | | /* Add the number of input bytes to the 64-bit input counter. */ |
429 | 0 | addto64(cx->msbInput, cx->lsbInput, inputLen); |
430 | 0 | if (inBufIndex) { |
431 | | /* There is already data in the buffer. Fill with input. */ |
432 | 0 | bytesToConsume = PR_MIN(inputLen, MD5_BUFFER_SIZE - inBufIndex); |
433 | 0 | memcpy(&cx->inBuf[inBufIndex], input, bytesToConsume); |
434 | 0 | if (inBufIndex + bytesToConsume >= MD5_BUFFER_SIZE) { |
435 | | /* The buffer is filled. Run the compression function. */ |
436 | | #ifndef IS_LITTLE_ENDIAN |
437 | | md5_prep_state_le(cx); |
438 | | #endif |
439 | 0 | md5_compress(cx, cx->u.w); |
440 | 0 | } |
441 | | /* Remaining input. */ |
442 | 0 | inputLen -= bytesToConsume; |
443 | 0 | input += bytesToConsume; |
444 | 0 | } |
445 | | |
446 | | /* Iterate over 64-byte chunks of the message. */ |
447 | 0 | while (inputLen >= MD5_BUFFER_SIZE) { |
448 | 0 | #ifdef IS_LITTLE_ENDIAN |
449 | 0 | #ifdef HAVE_UNALIGNED_ACCESS |
450 | | /* x86 can handle arithmetic on non-word-aligned buffers */ |
451 | 0 | wBuf = (PRUint32 *)input; |
452 | | #else |
453 | | if ((ptrdiff_t)input & 0x3) { |
454 | | /* buffer not aligned, copy it to force alignment */ |
455 | | memcpy(cx->inBuf, input, MD5_BUFFER_SIZE); |
456 | | wBuf = cx->u.w; |
457 | | } else { |
458 | | /* buffer is aligned */ |
459 | | wBuf = (PRUint32 *)input; |
460 | | } |
461 | | #endif |
462 | | #else |
463 | | md5_prep_buffer_le(cx, input); |
464 | | wBuf = cx->u.w; |
465 | | #endif |
466 | 0 | md5_compress(cx, wBuf); |
467 | 0 | inputLen -= MD5_BUFFER_SIZE; |
468 | 0 | input += MD5_BUFFER_SIZE; |
469 | 0 | } |
470 | | |
471 | | /* Tail of message (message bytes mod 64). */ |
472 | 0 | if (inputLen) |
473 | 0 | memcpy(cx->inBuf, input, inputLen); |
474 | 0 | } |
475 | | |
476 | | static const unsigned char padbytes[] = { |
477 | | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
478 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
479 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
480 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
481 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
482 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
483 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
484 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
485 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
486 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
487 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
488 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
489 | | }; |
490 | | |
491 | | void |
492 | | MD5_End(MD5Context *cx, unsigned char *digest, |
493 | | unsigned int *digestLen, unsigned int maxDigestLen) |
494 | 0 | { |
495 | | #ifndef IS_LITTLE_ENDIAN |
496 | | PRUint32 tmp; |
497 | | #endif |
498 | 0 | PRUint32 lowInput, highInput; |
499 | 0 | PRUint32 inBufIndex = cx->lsbInput & 63; |
500 | |
|
501 | 0 | if (maxDigestLen < MD5_HASH_LEN) { |
502 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
503 | 0 | return; |
504 | 0 | } |
505 | | |
506 | | /* Copy out the length of bits input before padding. */ |
507 | 0 | lowInput = cx->lsbInput; |
508 | 0 | highInput = (cx->msbInput << 3) | (lowInput >> 29); |
509 | 0 | lowInput <<= 3; |
510 | |
|
511 | 0 | if (inBufIndex < MD5_END_BUFFER) { |
512 | 0 | MD5_Update(cx, padbytes, MD5_END_BUFFER - inBufIndex); |
513 | 0 | } else { |
514 | 0 | MD5_Update(cx, padbytes, |
515 | 0 | MD5_END_BUFFER + MD5_BUFFER_SIZE - inBufIndex); |
516 | 0 | } |
517 | | |
518 | | /* Store the number of bytes input (before padding) in final 64 bits. */ |
519 | 0 | cx->u.w[14] = lendian(lowInput); |
520 | 0 | cx->u.w[15] = lendian(highInput); |
521 | | |
522 | | /* Final call to compress. */ |
523 | | #ifndef IS_LITTLE_ENDIAN |
524 | | md5_prep_state_le(cx); |
525 | | #endif |
526 | 0 | md5_compress(cx, cx->u.w); |
527 | | |
528 | | /* Copy the resulting values out of the chain variables into return buf. */ |
529 | 0 | if (digestLen) |
530 | 0 | *digestLen = MD5_HASH_LEN; |
531 | | #ifndef IS_LITTLE_ENDIAN |
532 | | cx->cv[0] = lendian(cx->cv[0]); |
533 | | cx->cv[1] = lendian(cx->cv[1]); |
534 | | cx->cv[2] = lendian(cx->cv[2]); |
535 | | cx->cv[3] = lendian(cx->cv[3]); |
536 | | #endif |
537 | 0 | memcpy(digest, cx->cv, MD5_HASH_LEN); |
538 | 0 | } |
539 | | |
540 | | void |
541 | | MD5_EndRaw(MD5Context *cx, unsigned char *digest, |
542 | | unsigned int *digestLen, unsigned int maxDigestLen) |
543 | 0 | { |
544 | | #ifndef IS_LITTLE_ENDIAN |
545 | | PRUint32 tmp; |
546 | | #endif |
547 | 0 | PRUint32 cv[4]; |
548 | |
|
549 | 0 | if (maxDigestLen < MD5_HASH_LEN) { |
550 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
551 | 0 | return; |
552 | 0 | } |
553 | | |
554 | 0 | memcpy(cv, cx->cv, sizeof(cv)); |
555 | | #ifndef IS_LITTLE_ENDIAN |
556 | | cv[0] = lendian(cv[0]); |
557 | | cv[1] = lendian(cv[1]); |
558 | | cv[2] = lendian(cv[2]); |
559 | | cv[3] = lendian(cv[3]); |
560 | | #endif |
561 | 0 | memcpy(digest, cv, MD5_HASH_LEN); |
562 | 0 | if (digestLen) |
563 | 0 | *digestLen = MD5_HASH_LEN; |
564 | 0 | } |
565 | | |
566 | | unsigned int |
567 | | MD5_FlattenSize(MD5Context *cx) |
568 | 0 | { |
569 | 0 | return sizeof(*cx); |
570 | 0 | } |
571 | | |
572 | | SECStatus |
573 | | MD5_Flatten(MD5Context *cx, unsigned char *space) |
574 | 0 | { |
575 | 0 | memcpy(space, cx, sizeof(*cx)); |
576 | 0 | return SECSuccess; |
577 | 0 | } |
578 | | |
579 | | MD5Context * |
580 | | MD5_Resurrect(unsigned char *space, void *arg) |
581 | 0 | { |
582 | 0 | MD5Context *cx = MD5_NewContext(); |
583 | 0 | if (cx) |
584 | 0 | memcpy(cx, space, sizeof(*cx)); |
585 | 0 | return cx; |
586 | 0 | } |
587 | | |
588 | | void |
589 | | MD5_Clone(MD5Context *dest, MD5Context *src) |
590 | 0 | { |
591 | 0 | memcpy(dest, src, sizeof *dest); |
592 | 0 | } |
593 | | |
594 | | void |
595 | | MD5_TraceState(MD5Context *cx) |
596 | 0 | { |
597 | 0 | PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
598 | 0 | } |