Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / freebl / md5.c
blobfbcee7f46f328dc0c0f1c3fbedcd31c65cab43b7
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
14 * The Original Code is the Netscape security libraries.
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.
21 * Contributor(s):
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.
35 * ***** END LICENSE BLOCK ***** */
37 #include "prerr.h"
38 #include "secerr.h"
40 #include "prtypes.h"
41 #include "prlong.h"
43 #include "blapi.h"
45 #define MD5_HASH_LEN 16
46 #define MD5_BUFFER_SIZE 64
47 #define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
49 #define CV0_1 0x67452301
50 #define CV0_2 0xefcdab89
51 #define CV0_3 0x98badcfe
52 #define CV0_4 0x10325476
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
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
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
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
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
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
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
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
190 #define S1_0 7
191 #define S1_1 12
192 #define S1_2 17
193 #define S1_3 22
195 #define S2_0 5
196 #define S2_1 9
197 #define S2_2 14
198 #define S2_3 20
200 #define S3_0 4
201 #define S3_1 11
202 #define S3_2 16
203 #define S3_3 23
205 #define S4_0 6
206 #define S4_1 10
207 #define S4_2 15
208 #define S4_3 21
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;
220 #define inBuf u.b
222 SECStatus
223 MD5_Hash(unsigned char *dest, const char *src)
225 return MD5_HashBuf(dest, (unsigned char *)src, PL_strlen(src));
228 SECStatus
229 MD5_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
231 unsigned int len;
232 MD5Context cx;
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;
241 MD5Context *
242 MD5_NewContext(void)
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;
250 return cx;
253 void
254 MD5_DestroyContext(MD5Context *cx, PRBool freeit)
256 /* memset(cx, 0, sizeof *cx); */
257 if (freeit) {
258 PORT_Free(cx);
262 void
263 MD5_Begin(MD5Context *cx)
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;
274 #define cls(i32, s) (tmp = i32, tmp << s | tmp >> (32 - s))
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
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
293 #ifndef IS_LITTLE_ENDIAN
295 #define lebytes(b4) \
296 ((b4)[3] << 24 | (b4)[2] << 16 | (b4)[1] << 8 | (b4)[0])
298 static void
299 md5_prep_state_le(MD5Context *cx)
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]);
320 static void
321 md5_prep_buffer_le(MD5Context *cx, const PRUint8 *beBuf)
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]);
340 #endif
343 #define F(X, Y, Z) \
344 ((X & Y) | ((~X) & Z))
346 #define G(X, Y, Z) \
347 ((X & Z) | (Y & (~Z)))
349 #define H(X, Y, Z) \
350 (X ^ Y ^ Z)
352 #define I(X, Y, Z) \
353 (Y ^ (X | (~Z)))
355 #define FF(a, b, c, d, bufint, s, ti) \
356 a = b + cls(a + F(b, c, d) + bufint + ti, s)
358 #define GG(a, b, c, d, bufint, s, ti) \
359 a = b + cls(a + G(b, c, d) + bufint + ti, s)
361 #define HH(a, b, c, d, bufint, s, ti) \
362 a = b + cls(a + H(b, c, d) + bufint + ti, s)
364 #define II(a, b, c, d, bufint, s, ti) \
365 a = b + cls(a + I(b, c, d) + bufint + ti, s)
367 static void
368 md5_compress(MD5Context *cx, const PRUint32 *wBuf)
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;
446 void
447 MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen)
449 PRUint32 bytesToConsume;
450 PRUint32 inBufIndex = cx->lsbInput & 63;
451 const PRUint32 *wBuf;
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);
466 /* Remaining input. */
467 inputLen -= bytesToConsume;
468 input += bytesToConsume;
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;
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;
496 /* Tail of message (message bytes mod 64). */
497 if (inputLen)
498 memcpy(cx->inBuf, input, inputLen);
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
516 void
517 MD5_End(MD5Context *cx, unsigned char *digest,
518 unsigned int *digestLen, unsigned int maxDigestLen)
520 #ifndef IS_LITTLE_ENDIAN
521 PRUint32 tmp;
522 #endif
523 PRUint32 lowInput, highInput;
524 PRUint32 inBufIndex = cx->lsbInput & 63;
526 if (maxDigestLen < MD5_HASH_LEN) {
527 PORT_SetError(SEC_ERROR_INVALID_ARGS);
528 return;
531 /* Copy out the length of bits input before padding. */
532 lowInput = cx->lsbInput;
533 highInput = (cx->msbInput << 3) | (lowInput >> 29);
534 lowInput <<= 3;
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);
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);
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);
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);
564 unsigned int
565 MD5_FlattenSize(MD5Context *cx)
567 return sizeof(*cx);
570 SECStatus
571 MD5_Flatten(MD5Context *cx, unsigned char *space)
573 memcpy(space, cx, sizeof(*cx));
574 return SECSuccess;
577 MD5Context *
578 MD5_Resurrect(unsigned char *space, void *arg)
580 MD5Context *cx = MD5_NewContext();
581 if (cx)
582 memcpy(cx, space, sizeof(*cx));
583 return cx;
586 void MD5_Clone(MD5Context *dest, MD5Context *src)
588 memcpy(dest, src, sizeof *dest);
591 void
592 MD5_TraceState(MD5Context *cx)
594 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);