~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

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
}