2 * File imported from FreeBSD, original by Poul-Henning Kamp.
4 * $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $
6 * contrib/pgcrypto/crypt-md5.c
16 static const char _crypt_a64
[] =
17 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
20 _crypt_to64(char *s
, unsigned long v
, int n
)
24 *s
++ = _crypt_a64
[v
& 0x3f];
34 px_crypt_md5(const char *pw
, const char *salt
, char *passwd
, unsigned dstlen
)
36 static char *magic
= "$1$"; /* This string is magic for this algorithm.
37 * Having it this way, we can get better later
40 static const char *sp
,
42 unsigned char final
[MD5_SIZE
];
51 if (!passwd
|| dstlen
< 120)
54 /* Refine the Salt first */
57 /* If it starts with the magic string, then skip that */
58 if (strncmp(sp
, magic
, strlen(magic
)) == 0)
61 /* It stops at the first '$', max 8 chars */
62 for (ep
= sp
; *ep
&& *ep
!= '$' && ep
< (sp
+ 8); ep
++)
65 /* get the length of the true salt */
68 /* we need two PX_MD objects */
69 err
= px_find_digest("md5", &ctx
);
72 err
= px_find_digest("md5", &ctx1
);
75 /* this path is possible under low-memory circumstances */
80 /* The password first, since that is what is most unknown */
81 px_md_update(ctx
, (const uint8
*) pw
, strlen(pw
));
83 /* Then our magic string */
84 px_md_update(ctx
, (uint8
*) magic
, strlen(magic
));
86 /* Then the raw salt */
87 px_md_update(ctx
, (const uint8
*) sp
, sl
);
89 /* Then just as many characters of the MD5(pw,salt,pw) */
90 px_md_update(ctx1
, (const uint8
*) pw
, strlen(pw
));
91 px_md_update(ctx1
, (const uint8
*) sp
, sl
);
92 px_md_update(ctx1
, (const uint8
*) pw
, strlen(pw
));
93 px_md_finish(ctx1
, final
);
94 for (pl
= strlen(pw
); pl
> 0; pl
-= MD5_SIZE
)
95 px_md_update(ctx
, final
, pl
> MD5_SIZE
? MD5_SIZE
: pl
);
97 /* Don't leave anything around in vm they could use. */
98 px_memset(final
, 0, sizeof final
);
100 /* Then something really weird... */
101 for (i
= strlen(pw
); i
; i
>>= 1)
103 px_md_update(ctx
, final
, 1);
105 px_md_update(ctx
, (const uint8
*) pw
, 1);
107 /* Now make the output string */
108 strcpy(passwd
, magic
);
109 strncat(passwd
, sp
, sl
);
112 px_md_finish(ctx
, final
);
115 * and now, just to make sure things don't run too fast On a 60 Mhz
116 * Pentium this takes 34 msec, so you would need 30 seconds to build a
117 * 1000 entry dictionary...
119 for (i
= 0; i
< 1000; i
++)
123 px_md_update(ctx1
, (const uint8
*) pw
, strlen(pw
));
125 px_md_update(ctx1
, final
, MD5_SIZE
);
128 px_md_update(ctx1
, (const uint8
*) sp
, sl
);
131 px_md_update(ctx1
, (const uint8
*) pw
, strlen(pw
));
134 px_md_update(ctx1
, final
, MD5_SIZE
);
136 px_md_update(ctx1
, (const uint8
*) pw
, strlen(pw
));
137 px_md_finish(ctx1
, final
);
140 p
= passwd
+ strlen(passwd
);
142 l
= (final
[0] << 16) | (final
[6] << 8) | final
[12];
143 _crypt_to64(p
, l
, 4);
145 l
= (final
[1] << 16) | (final
[7] << 8) | final
[13];
146 _crypt_to64(p
, l
, 4);
148 l
= (final
[2] << 16) | (final
[8] << 8) | final
[14];
149 _crypt_to64(p
, l
, 4);
151 l
= (final
[3] << 16) | (final
[9] << 8) | final
[15];
152 _crypt_to64(p
, l
, 4);
154 l
= (final
[4] << 16) | (final
[10] << 8) | final
[5];
155 _crypt_to64(p
, l
, 4);
158 _crypt_to64(p
, l
, 2);
162 /* Don't leave anything around in vm they could use. */
163 px_memset(final
, 0, sizeof final
);