1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include <assert.h>
24: #include <errno.h>
25: #include <stdlib.h>
26: #include <string.h>
27: #include <sys/param.h>
28:
29: #include "md5.h"
30:
31:
32:
33:
34:
35: static const char md5_salt_prefix[] = "$1$";
36:
37:
38: static const char b64t[64] =
39: "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
40:
41:
42:
43: extern char *__md5_crypt_r (const char *key, const char *salt,
44: char *buffer, int buflen);
45: extern char *__md5_crypt (const char *key, const char *salt);
46:
47:
48:
49:
50: char *
51: __md5_crypt_r (key, salt, buffer, buflen)
52: const char *key;
53: const char *salt;
54: char *buffer;
55: int buflen;
56: {
57: unsigned char alt_result[16]
58: __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
59: struct md5_ctx ctx;
60: struct md5_ctx alt_ctx;
61: size_t salt_len;
62: size_t key_len;
63: size_t cnt;
64: char *cp;
65: char *copied_key = NULL;
66: char *copied_salt = NULL;
67:
68:
69:
70: if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
71:
72: salt += sizeof (md5_salt_prefix) - 1;
73:
74: salt_len = MIN (strcspn (salt, "$"), 8);
75: key_len = strlen (key);
76:
77: if ((key - (char *) 0) % __alignof__ (md5_uint32) != 0)
78: {
79: char *tmp = (char *) alloca (key_len + __alignof__ (md5_uint32));
80: key = copied_key =
81: memcpy (tmp + __alignof__ (md5_uint32)
82: - (tmp - (char *) 0) % __alignof__ (md5_uint32),
83: key, key_len);
84: assert ((key - (char *) 0) % __alignof__ (md5_uint32) == 0);
85: }
86:
87: if ((salt - (char *) 0) % __alignof__ (md5_uint32) != 0)
88: {
89: char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32));
90: salt = copied_salt =
91: memcpy (tmp + __alignof__ (md5_uint32)
92: - (tmp - (char *) 0) % __alignof__ (md5_uint32),
93: salt, salt_len);
94: assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0);
95: }
96:
97:
98: __md5_init_ctx (&ctx);
99:
100:
101: __md5_process_bytes (key, key_len, &ctx);
102:
103:
104:
105: __md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx);
106:
107:
108:
109:
110: __md5_process_bytes (salt, salt_len, &ctx);
111:
112:
113:
114:
115: __md5_init_ctx (&alt_ctx);
116:
117:
118: __md5_process_bytes (key, key_len, &alt_ctx);
119:
120:
121: __md5_process_bytes (salt, salt_len, &alt_ctx);
122:
123:
124: __md5_process_bytes (key, key_len, &alt_ctx);
125:
126:
127:
128: __md5_finish_ctx (&alt_ctx, alt_result);
129:
130:
131: for (cnt = key_len; cnt > 16; cnt -= 16)
132: __md5_process_bytes (alt_result, 16, &ctx);
133: __md5_process_bytes (alt_result, cnt, &ctx);
134:
135:
136: *alt_result = '\0';
137:
138:
139:
140:
141:
142: for (cnt = key_len; cnt > 0; cnt >>= 1)
143: __md5_process_bytes ((cnt & 1) != 0 ? (const char *) alt_result : key, 1,
144: &ctx);
145:
146:
147: __md5_finish_ctx (&ctx, alt_result);
148:
149:
150:
151:
152: for (cnt = 0; cnt < 1000; ++cnt)
153: {
154:
155: __md5_init_ctx (&ctx);
156:
157:
158: if ((cnt & 1) != 0)
159: __md5_process_bytes (key, key_len, &ctx);
160: else
161: __md5_process_bytes (alt_result, 16, &ctx);
162:
163:
164: if (cnt % 3 != 0)
165: __md5_process_bytes (salt, salt_len, &ctx);
166:
167:
168: if (cnt % 7 != 0)
169: __md5_process_bytes (key, key_len, &ctx);
170:
171:
172: if ((cnt & 1) != 0)
173: __md5_process_bytes (alt_result, 16, &ctx);
174: else
175: __md5_process_bytes (key, key_len, &ctx);
176:
177:
178: __md5_finish_ctx (&ctx, alt_result);
179: }
180:
181:
182:
183: cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
184: buflen -= sizeof (md5_salt_prefix) - 1;
185:
186: cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
187: buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
188:
189: if (buflen > 0)
190: {
191: *cp++ = '$';
192: --buflen;
193: }
194:
195: #define b64_from_24bit(B2, B1, B0, N) \
196: do { \
197: unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
198: int n = (N); \
199: while (n-- > 0 && buflen > 0) \
200: { \
201: *cp++ = b64t[w & 0x3f]; \
202: --buflen; \
203: w >>= 6; \
204: } \
205: } while (0)
206:
207:
208: b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4);
209: b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4);
210: b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4);
211: b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4);
212: b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4);
213: b64_from_24bit (0, 0, alt_result[11], 2);
214: if (buflen <= 0)
215: {
216: __set_errno (ERANGE);
217: buffer = NULL;
218: }
219: else
220: *cp = '\0';
221:
222:
223:
224:
225:
226: __md5_init_ctx (&ctx);
227: __md5_finish_ctx (&ctx, alt_result);
228: memset (&ctx, '\0', sizeof (ctx));
229: memset (&alt_ctx, '\0', sizeof (alt_ctx));
230: if (copied_key != NULL)
231: memset (copied_key, '\0', key_len);
232: if (copied_salt != NULL)
233: memset (copied_salt, '\0', salt_len);
234:
235: return buffer;
236: }
237:
238: #ifndef _LIBC
239: # define libc_freeres_ptr(decl) decl
240: #endif
241: libc_freeres_ptr (static char *buffer);
242:
243: char *
244: __md5_crypt (const char *key, const char *salt)
245: {
246:
247:
248:
249: static int buflen;
250: int needed = 3 + strlen (salt) + 1 + 26 + 1;
251:
252: if (buflen < needed)
253: {
254: char *new_buffer = (char *) realloc (buffer, needed);
255: if (new_buffer == NULL)
256: return NULL;
257:
258: buffer = new_buffer;
259: buflen = needed;
260: }
261:
262: return __md5_crypt_r (key, salt, buffer, buflen);
263: }
264:
265: #ifndef _LIBC
266: static void
267: __attribute__ ((__destructor__))
268: free_mem (void)
269: {
270: free (buffer);
271: }
272: #endif