Make build-many-glibcs.py track component versions requested and used.
[glibc.git] / crypt / md5-crypt.c
blob2243bc7aedb5b9c20a3ca4df4833766565dd3415
1 /* One way encryption based on MD5 sum.
2 Compatible with the behavior of MD5 crypt introduced in FreeBSD 2.0.
3 Copyright (C) 1996-2016 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <http://www.gnu.org/licenses/>. */
21 #include <assert.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/param.h>
27 #include "md5.h"
28 #include "crypt-private.h"
31 #ifdef USE_NSS
32 typedef int PRBool;
33 # include <hasht.h>
34 # include <nsslowhash.h>
36 # define md5_init_ctx(ctxp, nss_ctxp) \
37 do \
38 { \
39 if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgMD5)) \
40 == NULL)) \
41 { \
42 if (nss_ctx != NULL) \
43 NSSLOWHASH_Destroy (nss_ctx); \
44 if (nss_alt_ctx != NULL) \
45 NSSLOWHASH_Destroy (nss_alt_ctx); \
46 return NULL; \
47 } \
48 NSSLOWHASH_Begin (nss_ctxp); \
49 } \
50 while (0)
52 # define md5_process_bytes(buf, len, ctxp, nss_ctxp) \
53 NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
55 # define md5_finish_ctx(ctxp, nss_ctxp, result) \
56 do \
57 { \
58 unsigned int ret; \
59 NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \
60 assert (ret == sizeof (result)); \
61 NSSLOWHASH_Destroy (nss_ctxp); \
62 nss_ctxp = NULL; \
63 } \
64 while (0)
65 #else
66 # define md5_init_ctx(ctxp, nss_ctxp) \
67 __md5_init_ctx (ctxp)
69 # define md5_process_bytes(buf, len, ctxp, nss_ctxp) \
70 __md5_process_bytes(buf, len, ctxp)
72 # define md5_finish_ctx(ctxp, nss_ctxp, result) \
73 __md5_finish_ctx (ctxp, result)
74 #endif
77 /* Define our magic string to mark salt for MD5 "encryption"
78 replacement. This is meant to be the same as for other MD5 based
79 encryption implementations. */
80 static const char md5_salt_prefix[] = "$1$";
83 /* Prototypes for local functions. */
84 extern char *__md5_crypt_r (const char *key, const char *salt,
85 char *buffer, int buflen);
86 extern char *__md5_crypt (const char *key, const char *salt);
89 /* This entry point is equivalent to the `crypt' function in Unix
90 libcs. */
91 char *
92 __md5_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
94 unsigned char alt_result[16]
95 __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
96 size_t salt_len;
97 size_t key_len;
98 size_t cnt;
99 char *cp;
100 char *copied_key = NULL;
101 char *copied_salt = NULL;
102 char *free_key = NULL;
103 size_t alloca_used = 0;
105 /* Find beginning of salt string. The prefix should normally always
106 be present. Just in case it is not. */
107 if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
108 /* Skip salt prefix. */
109 salt += sizeof (md5_salt_prefix) - 1;
111 salt_len = MIN (strcspn (salt, "$"), 8);
112 key_len = strlen (key);
114 if ((key - (char *) 0) % __alignof__ (md5_uint32) != 0)
116 char *tmp;
118 if (__libc_use_alloca (alloca_used + key_len + __alignof__ (md5_uint32)))
119 tmp = (char *) alloca (key_len + __alignof__ (md5_uint32));
120 else
122 free_key = tmp = (char *) malloc (key_len + __alignof__ (md5_uint32));
123 if (tmp == NULL)
124 return NULL;
127 key = copied_key =
128 memcpy (tmp + __alignof__ (md5_uint32)
129 - (tmp - (char *) 0) % __alignof__ (md5_uint32),
130 key, key_len);
131 assert ((key - (char *) 0) % __alignof__ (md5_uint32) == 0);
134 if ((salt - (char *) 0) % __alignof__ (md5_uint32) != 0)
136 char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32));
137 salt = copied_salt =
138 memcpy (tmp + __alignof__ (md5_uint32)
139 - (tmp - (char *) 0) % __alignof__ (md5_uint32),
140 salt, salt_len);
141 assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0);
144 #ifdef USE_NSS
145 /* Initialize libfreebl3. */
146 NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
147 if (nss_ictx == NULL)
149 free (free_key);
150 return NULL;
152 NSSLOWHASHContext *nss_ctx = NULL;
153 NSSLOWHASHContext *nss_alt_ctx = NULL;
154 #else
155 struct md5_ctx ctx;
156 struct md5_ctx alt_ctx;
157 #endif
159 /* Prepare for the real work. */
160 md5_init_ctx (&ctx, nss_ctx);
162 /* Add the key string. */
163 md5_process_bytes (key, key_len, &ctx, nss_ctx);
165 /* Because the SALT argument need not always have the salt prefix we
166 add it separately. */
167 md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1,
168 &ctx, nss_ctx);
170 /* The last part is the salt string. This must be at most 8
171 characters and it ends at the first `$' character (for
172 compatibility with existing implementations). */
173 md5_process_bytes (salt, salt_len, &ctx, nss_ctx);
176 /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The
177 final result will be added to the first context. */
178 md5_init_ctx (&alt_ctx, nss_alt_ctx);
180 /* Add key. */
181 md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
183 /* Add salt. */
184 md5_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
186 /* Add key again. */
187 md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
189 /* Now get result of this (16 bytes) and add it to the other
190 context. */
191 md5_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
193 /* Add for any character in the key one byte of the alternate sum. */
194 for (cnt = key_len; cnt > 16; cnt -= 16)
195 md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
196 md5_process_bytes (alt_result, cnt, &ctx, nss_ctx);
198 /* For the following code we need a NUL byte. */
199 *alt_result = '\0';
201 /* The original implementation now does something weird: for every 1
202 bit in the key the first 0 is added to the buffer, for every 0
203 bit the first character of the key. This does not seem to be
204 what was intended but we have to follow this to be compatible. */
205 for (cnt = key_len; cnt > 0; cnt >>= 1)
206 md5_process_bytes ((cnt & 1) != 0
207 ? (const void *) alt_result : (const void *) key, 1,
208 &ctx, nss_ctx);
210 /* Create intermediate result. */
211 md5_finish_ctx (&ctx, nss_ctx, alt_result);
213 /* Now comes another weirdness. In fear of password crackers here
214 comes a quite long loop which just processes the output of the
215 previous round again. We cannot ignore this here. */
216 for (cnt = 0; cnt < 1000; ++cnt)
218 /* New context. */
219 md5_init_ctx (&ctx, nss_ctx);
221 /* Add key or last result. */
222 if ((cnt & 1) != 0)
223 md5_process_bytes (key, key_len, &ctx, nss_ctx);
224 else
225 md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
227 /* Add salt for numbers not divisible by 3. */
228 if (cnt % 3 != 0)
229 md5_process_bytes (salt, salt_len, &ctx, nss_ctx);
231 /* Add key for numbers not divisible by 7. */
232 if (cnt % 7 != 0)
233 md5_process_bytes (key, key_len, &ctx, nss_ctx);
235 /* Add key or last result. */
236 if ((cnt & 1) != 0)
237 md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
238 else
239 md5_process_bytes (key, key_len, &ctx, nss_ctx);
241 /* Create intermediate result. */
242 md5_finish_ctx (&ctx, nss_ctx, alt_result);
245 #ifdef USE_NSS
246 /* Free libfreebl3 resources. */
247 NSSLOW_Shutdown (nss_ictx);
248 #endif
250 /* Now we can construct the result string. It consists of three
251 parts. */
252 cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
253 buflen -= sizeof (md5_salt_prefix) - 1;
255 cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
256 buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
258 if (buflen > 0)
260 *cp++ = '$';
261 --buflen;
264 __b64_from_24bit (&cp, &buflen,
265 alt_result[0], alt_result[6], alt_result[12], 4);
266 __b64_from_24bit (&cp, &buflen,
267 alt_result[1], alt_result[7], alt_result[13], 4);
268 __b64_from_24bit (&cp, &buflen,
269 alt_result[2], alt_result[8], alt_result[14], 4);
270 __b64_from_24bit (&cp, &buflen,
271 alt_result[3], alt_result[9], alt_result[15], 4);
272 __b64_from_24bit (&cp, &buflen,
273 alt_result[4], alt_result[10], alt_result[5], 4);
274 __b64_from_24bit (&cp, &buflen,
275 0, 0, alt_result[11], 2);
276 if (buflen <= 0)
278 __set_errno (ERANGE);
279 buffer = NULL;
281 else
282 *cp = '\0'; /* Terminate the string. */
284 /* Clear the buffer for the intermediate result so that people
285 attaching to processes or reading core dumps cannot get any
286 information. We do it in this way to clear correct_words[]
287 inside the MD5 implementation as well. */
288 #ifndef USE_NSS
289 __md5_init_ctx (&ctx);
290 __md5_finish_ctx (&ctx, alt_result);
291 memset (&ctx, '\0', sizeof (ctx));
292 memset (&alt_ctx, '\0', sizeof (alt_ctx));
293 #endif
294 if (copied_key != NULL)
295 memset (copied_key, '\0', key_len);
296 if (copied_salt != NULL)
297 memset (copied_salt, '\0', salt_len);
299 free (free_key);
300 return buffer;
303 #ifndef _LIBC
304 # define libc_freeres_ptr(decl) decl
305 #endif
306 libc_freeres_ptr (static char *buffer);
308 char *
309 __md5_crypt (const char *key, const char *salt)
311 /* We don't want to have an arbitrary limit in the size of the
312 password. We can compute the size of the result in advance and
313 so we can prepare the buffer we pass to `md5_crypt_r'. */
314 static int buflen;
315 int needed = 3 + strlen (salt) + 1 + 26 + 1;
317 if (buflen < needed)
319 char *new_buffer = (char *) realloc (buffer, needed);
320 if (new_buffer == NULL)
321 return NULL;
323 buffer = new_buffer;
324 buflen = needed;
327 return __md5_crypt_r (key, salt, buffer, buflen);
330 #ifndef _LIBC
331 static void
332 __attribute__ ((__destructor__))
333 free_mem (void)
335 free (buffer);
337 #endif