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