Annotation of parser3/src/lib/md5/pa_md5c.c, revision 1.2
1.1 paf 1: /*
2: * This is work is derived from material Copyright RSA Data Security, Inc.
3: *
4: * The RSA copyright statement and Licence for that original material is
5: * included below. This is followed by the Apache copyright statement and
6: * licence for the modifications made to that material.
7: */
8:
9: /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
10: */
11:
12: /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
13: rights reserved.
14:
15: License to copy and use this software is granted provided that it
16: is identified as the "RSA Data Security, Inc. MD5 Message-Digest
17: Algorithm" in all material mentioning or referencing this software
18: or this function.
19:
20: License is also granted to make and use derivative works provided
21: that such works are identified as "derived from the RSA Data
22: Security, Inc. MD5 Message-Digest Algorithm" in all material
23: mentioning or referencing the derived work.
24:
25: RSA Data Security, Inc. makes no representations concerning either
26: the merchantability of this software or the suitability of this
27: software for any particular purpose. It is provided "as is"
28: without express or implied warranty of any kind.
29:
30: These notices must be retained in any copies of any part of this
31: documentation and/or software.
32: */
33:
34: /* ====================================================================
35: * Copyright (c) 1996-1999 The Apache Group. All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: *
41: * 1. Redistributions of source code must retain the above copyright
42: * notice, this list of conditions and the following disclaimer.
43: *
44: * 2. Redistributions in binary form must reproduce the above copyright
45: * notice, this list of conditions and the following disclaimer in
46: * the documentation and/or other materials provided with the
47: * distribution.
48: *
49: * 3. All advertising materials mentioning features or use of this
50: * software must display the following acknowledgment:
51: * "This product includes software developed by the Apache Group
52: * for use in the Apache HTTP server project (http://www.apache.org/)."
53: *
54: * 4. The names "Apache Server" and "Apache Group" must not be used to
55: * endorse or promote products derived from this software without
56: * prior written permission. For written permission, please contact
57: * apache@apache.org.
58: *
59: * 5. Products derived from this software may not be called "Apache"
60: * nor may "Apache" appear in their names without prior written
61: * permission of the Apache Group.
62: *
63: * 6. Redistributions of any form whatsoever must retain the following
64: * acknowledgment:
65: * "This product includes software developed by the Apache Group
66: * for use in the Apache HTTP server project (http://www.apache.org/)."
67: *
68: * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
69: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
70: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
71: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
72: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
73: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
74: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
75: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
77: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
78: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
79: * OF THE POSSIBILITY OF SUCH DAMAGE.
80: * ====================================================================
81: *
82: * This software consists of voluntary contributions made by many
83: * individuals on behalf of the Apache Group and was originally based
84: * on public domain software written at the National Center for
85: * Supercomputing Applications, University of Illinois, Urbana-Champaign.
86: * For more information on the Apache Group and the Apache HTTP server
87: * project, please see <http://www.apache.org/>.
88: *
89: */
90:
91: /*
92: * The pa_MD5Encode() routine uses much code obtained from the FreeBSD 3.0
93: * MD5 crypt() function, which is licenced as follows:
94: * ----------------------------------------------------------------------------
95: * "THE BEER-WARE LICENSE" (Revision 42):
96: * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
97: * can do whatever you want with this stuff. If we meet some day, and you think
98: * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
99: * ----------------------------------------------------------------------------
100: */
101:
1.2 ! paf 102: #include <strings.h>
! 103:
1.1 paf 104: #include "pa_md5.h"
105: //#include "ap.h"
106: //#ifdef CHARSET_EBCDIC
107: //#include "ebcdic.h"
108: //#endif /*CHARSET_EBCDIC*/
109: //#if HAVE_CRYPT_H
110: //#include <crypt.h>
111: //#endif
112:
113: #define pa_pa_cpystrn(strDest, strSource, count) strncpy(strDest, strSource, count)
114:
115: /* Constants for MD5Transform routine.
116: */
117:
118: #define S11 7
119: #define S12 12
120: #define S13 17
121: #define S14 22
122: #define S21 5
123: #define S22 9
124: #define S23 14
125: #define S24 20
126: #define S31 4
127: #define S32 11
128: #define S33 16
129: #define S34 23
130: #define S41 6
131: #define S42 10
132: #define S43 15
133: #define S44 21
134:
135: static void MD5Transform(UINT4 state[4], const unsigned char block[64]);
136: static void Encode(unsigned char *output, const UINT4 *input,
137: unsigned int len);
138: static void Decode(UINT4 *output, const unsigned char *input,
139: unsigned int len);
140:
141: static unsigned char PADDING[64] =
142: {
143: 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
145: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
146: };
147:
148: /* F, G, H and I are basic MD5 functions.
149: */
150: #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
151: #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
152: #define H(x, y, z) ((x) ^ (y) ^ (z))
153: #define I(x, y, z) ((y) ^ ((x) | (~z)))
154:
155: /* ROTATE_LEFT rotates x left n bits.
156: */
157: #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
158:
159: /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
160: Rotation is separate from addition to prevent recomputation.
161: */
162: #define FF(a, b, c, d, x, s, ac) { \
163: (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
164: (a) = ROTATE_LEFT ((a), (s)); \
165: (a) += (b); \
166: }
167: #define GG(a, b, c, d, x, s, ac) { \
168: (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
169: (a) = ROTATE_LEFT ((a), (s)); \
170: (a) += (b); \
171: }
172: #define HH(a, b, c, d, x, s, ac) { \
173: (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
174: (a) = ROTATE_LEFT ((a), (s)); \
175: (a) += (b); \
176: }
177: #define II(a, b, c, d, x, s, ac) { \
178: (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
179: (a) = ROTATE_LEFT ((a), (s)); \
180: (a) += (b); \
181: }
182:
183: /* MD5 initialization. Begins an MD5 operation, writing a new context.
184: */
185: PA_API_EXPORT(void) pa_MD5Init(PA_MD5_CTX *context)
186: {
187: context->count[0] = context->count[1] = 0;
188: /* Load magic initialization constants. */
189: context->state[0] = 0x67452301;
190: context->state[1] = 0xefcdab89;
191: context->state[2] = 0x98badcfe;
192: context->state[3] = 0x10325476;
193: }
194:
195: /* MD5 block update operation. Continues an MD5 message-digest
196: operation, processing another message block, and updating the
197: context.
198: */
199: PA_API_EXPORT(void) pa_MD5Update(PA_MD5_CTX *context, const unsigned char *input,
200: unsigned int inputLen)
201: {
202: unsigned int i, idx, partLen;
203:
204: /* Compute number of bytes mod 64 */
205: idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
206:
207: /* Update number of bits */
208: if ((context->count[0] += ((UINT4) inputLen << 3))
209: < ((UINT4) inputLen << 3)) {
210: context->count[1]++;
211: }
212: context->count[1] += (UINT4) inputLen >> 29;
213:
214: partLen = 64 - idx;
215:
216: /* Transform as many times as possible. */
217: #ifndef CHARSET_EBCDIC
218: if (inputLen >= partLen) {
219: memcpy(&context->buffer[idx], input, partLen);
220: MD5Transform(context->state, context->buffer);
221:
222: for (i = partLen; i + 63 < inputLen; i += 64) {
223: MD5Transform(context->state, &input[i]);
224: }
225:
226: idx = 0;
227: }
228: else {
229: i = 0;
230: }
231:
232: /* Buffer remaining input */
233: memcpy(&context->buffer[idx], &input[i], inputLen - i);
234: #else /*CHARSET_EBCDIC*/
235: if (inputLen >= partLen) {
236: ebcdic2ascii(&context->buffer[idx], input, partLen);
237: MD5Transform(context->state, context->buffer);
238:
239: for (i = partLen; i + 63 < inputLen; i += 64) {
240: unsigned char inp_tmp[64];
241: ebcdic2ascii(inp_tmp, &input[i], 64);
242: MD5Transform(context->state, inp_tmp);
243: }
244:
245: idx = 0;
246: }
247: else {
248: i = 0;
249: }
250:
251: /* Buffer remaining input */
252: ebcdic2ascii(&context->buffer[idx], &input[i], inputLen - i);
253: #endif /*CHARSET_EBCDIC*/
254: }
255:
256: /* MD5 finalization. Ends an MD5 message-digest operation, writing the
257: the message digest and zeroizing the context.
258: */
259: PA_API_EXPORT(void) pa_MD5Final(unsigned char digest[16], PA_MD5_CTX *context)
260: {
261: unsigned char bits[8];
262: unsigned int idx, padLen;
263:
264:
265: /* Save number of bits */
266: Encode(bits, context->count, 8);
267:
268: #ifdef CHARSET_EBCDIC
269: /* XXX: @@@: In order to make this no more complex than necessary,
270: * this kludge converts the bits[] array using the ascii-to-ebcdic
271: * table, because the following pa_MD5Update() re-translates
272: * its input (ebcdic-to-ascii).
273: * Otherwise, we would have to pass a "conversion" flag to pa_MD5Update()
274: */
275: ascii2ebcdic(bits,bits,8);
276:
277: /* Since everything is converted to ascii within pa_MD5Update(),
278: * the initial 0x80 (PADDING[0]) must be stored as 0x20
279: */
280: PADDING[0] = os_toebcdic[0x80];
281: #endif /*CHARSET_EBCDIC*/
282:
283: /* Pad out to 56 mod 64. */
284: idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
285: padLen = (idx < 56) ? (56 - idx) : (120 - idx);
286: pa_MD5Update(context, (const unsigned char *)PADDING, padLen);
287:
288: /* Append length (before padding) */
289: pa_MD5Update(context, (const unsigned char *)bits, 8);
290:
291: /* Store state in digest */
292: Encode(digest, context->state, 16);
293:
294: /* Zeroize sensitive information. */
295: memset(context, 0, sizeof(*context));
296: }
297:
298: /* MD5 basic transformation. Transforms state based on block. */
299: static void MD5Transform(UINT4 state[4], const unsigned char block[64])
300: {
301: UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
302:
303: Decode(x, block, 64);
304:
305: /* Round 1 */
306: FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
307: FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
308: FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
309: FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
310: FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
311: FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
312: FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
313: FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
314: FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
315: FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
316: FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
317: FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
318: FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
319: FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
320: FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
321: FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
322:
323: /* Round 2 */
324: GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
325: GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
326: GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
327: GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
328: GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
329: GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
330: GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
331: GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
332: GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
333: GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
334: GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
335: GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
336: GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
337: GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
338: GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
339: GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
340:
341: /* Round 3 */
342: HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
343: HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
344: HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
345: HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
346: HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
347: HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
348: HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
349: HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
350: HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
351: HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
352: HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
353: HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
354: HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
355: HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
356: HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
357: HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
358:
359: /* Round 4 */
360: II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
361: II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
362: II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
363: II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
364: II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
365: II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
366: II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
367: II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
368: II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
369: II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
370: II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
371: II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
372: II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
373: II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
374: II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
375: II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
376:
377: state[0] += a;
378: state[1] += b;
379: state[2] += c;
380: state[3] += d;
381:
382: /* Zeroize sensitive information. */
383: memset(x, 0, sizeof(x));
384: }
385:
386: /* Encodes input (UINT4) into output (unsigned char). Assumes len is
387: a multiple of 4.
388: */
389: static void Encode(unsigned char *output, const UINT4 *input, unsigned int len)
390: {
391: unsigned int i, j;
392: UINT4 k;
393:
394: for (i = 0, j = 0; j < len; i++, j += 4) {
395: k = input[i];
396: output[j] = (unsigned char) (k & 0xff);
397: output[j + 1] = (unsigned char) ((k >> 8) & 0xff);
398: output[j + 2] = (unsigned char) ((k >> 16) & 0xff);
399: output[j + 3] = (unsigned char) ((k >> 24) & 0xff);
400: }
401: }
402:
403: /* Decodes input (unsigned char) into output (UINT4). Assumes len is
404: * a multiple of 4.
405: */
406: static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
407: {
408: unsigned int i, j;
409:
410: for (i = 0, j = 0; j < len; i++, j += 4)
411: output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) |
412: (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24);
413: }
414:
415: /*
416: * The following MD5 password encryption code was largely borrowed from
417: * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
418: * licenced as stated at the top of this file.
419: */
420: PA_API_EXPORT(void) pa_to64(char *s, unsigned long v, int n)
421: {
422: static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */
423: "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
424:
425: while (--n >= 0) {
426: *s++ = itoa64[v&0x3f];
427: v >>= 6;
428: }
429: }
430:
431: PA_API_EXPORT(void) pa_MD5Encode(const unsigned char *pw,
432: const unsigned char *salt,
433: char *result, size_t nbytes)
434: {
435: /*
436: * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
437: * plus 4 for the '$' separators, plus the password hash itself.
438: * Let's leave a goodly amount of leeway.
439: */
440:
441: char passwd[120], *p;
442: const unsigned char *sp, *ep;
443: unsigned char final[16];
444: int i;
445: unsigned int sl;
446: int pl;
447: unsigned int pwlen;
448: PA_MD5_CTX ctx, ctx1;
449: unsigned long l;
450:
451: /*
452: * Refine the salt first. It's possible we were given an already-hashed
453: * string as the salt argument, so extract the actual salt value from it
454: * if so. Otherwise just use the string up to the first '$' as the salt.
455: */
456: sp = salt;
457:
458: /*
459: * If it starts with the magic string, then skip that.
460: */
461: if (strncmp((char *)sp, PA_MD5PW_ID, PA_MD5PW_IDLEN) == 0) {
462: sp += PA_MD5PW_IDLEN;
463: }
464:
465: /*
466: * It stops at the first '$' or 8 chars, whichever comes first
467: */
468: for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
469: continue;
470: }
471:
472: /*
473: * Get the length of the true salt
474: */
475: sl = ep - sp;
476:
477: /*
478: * 'Time to make the doughnuts..'
479: */
480: pa_MD5Init(&ctx);
481:
482: pwlen = strlen((char *)pw);
483: /*
484: * The password first, since that is what is most unknown
485: */
486: pa_MD5Update(&ctx, pw, pwlen);
487:
488: /*
489: * Then our magic string
490: */
491: pa_MD5Update(&ctx, (const unsigned char *) PA_MD5PW_ID, PA_MD5PW_IDLEN);
492:
493: /*
494: * Then the raw salt
495: */
496: pa_MD5Update(&ctx, sp, sl);
497:
498: /*
499: * Then just as many characters of the MD5(pw, salt, pw)
500: */
501: pa_MD5Init(&ctx1);
502: pa_MD5Update(&ctx1, pw, pwlen);
503: pa_MD5Update(&ctx1, sp, sl);
504: pa_MD5Update(&ctx1, pw, pwlen);
505: pa_MD5Final(final, &ctx1);
506: for(pl = pwlen; pl > 0; pl -= 16) {
507: pa_MD5Update(&ctx, final, (pl > 16) ? 16 : (unsigned int) pl);
508: }
509:
510: /*
511: * Don't leave anything around in vm they could use.
512: */
513: memset(final, 0, sizeof(final));
514:
515: /*
516: * Then something really weird...
517: */
518: for (i = pwlen; i != 0; i >>= 1) {
519: if (i & 1) {
520: pa_MD5Update(&ctx, final, 1);
521: }
522: else {
523: pa_MD5Update(&ctx, pw, 1);
524: }
525: }
526:
527: /*
528: * Now make the output string. We know our limitations, so we
529: * can use the string routines without bounds checking.
530: */
531: pa_pa_cpystrn(passwd, PA_MD5PW_ID, PA_MD5PW_IDLEN + 1);
532: pa_pa_cpystrn(passwd + PA_MD5PW_IDLEN, (char *)sp, sl + 1);
533: passwd[PA_MD5PW_IDLEN + sl] = '$';
534: passwd[PA_MD5PW_IDLEN + sl + 1] = '\0';
535:
536: pa_MD5Final(final, &ctx);
537:
538: /*
539: * And now, just to make sure things don't run too fast..
540: * On a 60 Mhz Pentium this takes 34 msec, so you would
541: * need 30 seconds to build a 1000 entry dictionary...
542: */
543: for (i = 0; i < 1000; i++) {
544: pa_MD5Init(&ctx1);
545: if (i & 1) {
546: pa_MD5Update(&ctx1, pw, pwlen);
547: }
548: else {
549: pa_MD5Update(&ctx1, final, 16);
550: }
551: if (i % 3) {
552: pa_MD5Update(&ctx1, sp, sl);
553: }
554:
555: if (i % 7) {
556: pa_MD5Update(&ctx1, pw, pwlen);
557: }
558:
559: if (i & 1) {
560: pa_MD5Update(&ctx1, final, 16);
561: }
562: else {
563: pa_MD5Update(&ctx1, pw, pwlen);
564: }
565: pa_MD5Final(final,&ctx1);
566: }
567:
568: p = passwd + strlen(passwd);
569:
570: l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; pa_to64(p, l, 4); p += 4;
571: l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; pa_to64(p, l, 4); p += 4;
572: l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; pa_to64(p, l, 4); p += 4;
573: l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; pa_to64(p, l, 4); p += 4;
574: l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; pa_to64(p, l, 4); p += 4;
575: l = final[11] ; pa_to64(p, l, 2); p += 2;
576: *p = '\0';
577:
578: /*
579: * Don't leave anything around in vm they could use.
580: */
581: memset(final, 0, sizeof(final));
582:
583: pa_pa_cpystrn(result, passwd, nbytes - 1);
584: }
E-mail: