Update copyright notices with scripts/update-copyrights
[platform/upstream/glibc.git] / crypt / md5-crypt.c
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-2014 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6
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.
11
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.
16
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/>.  */
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/param.h>
26
27 #include "md5.h"
28
29
30 #ifdef USE_NSS
31 typedef int PRBool;
32 # include <hasht.h>
33 # include <nsslowhash.h>
34
35 # define md5_init_ctx(ctxp, nss_ctxp) \
36   do                                                                          \
37     {                                                                         \
38       if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgMD5))         \
39            == NULL))                                                          \
40         {                                                                     \
41           if (nss_ctx != NULL)                                                \
42             NSSLOWHASH_Destroy (nss_ctx);                                     \
43           if (nss_alt_ctx != NULL)                                            \
44             NSSLOWHASH_Destroy (nss_alt_ctx);                                 \
45           return NULL;                                                        \
46         }                                                                     \
47       NSSLOWHASH_Begin (nss_ctxp);                                            \
48     }                                                                         \
49   while (0)
50
51 # define md5_process_bytes(buf, len, ctxp, nss_ctxp) \
52   NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
53
54 # define md5_finish_ctx(ctxp, nss_ctxp, result) \
55   do                                                                          \
56     {                                                                         \
57       unsigned int ret;                                                       \
58       NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result));               \
59       assert (ret == sizeof (result));                                        \
60       NSSLOWHASH_Destroy (nss_ctxp);                                          \
61       nss_ctxp = NULL;                                                        \
62     }                                                                         \
63   while (0)
64 #else
65 # define md5_init_ctx(ctxp, nss_ctxp) \
66   __md5_init_ctx (ctxp)
67
68 # define md5_process_bytes(buf, len, ctxp, nss_ctxp) \
69   __md5_process_bytes(buf, len, ctxp)
70
71 # define md5_finish_ctx(ctxp, nss_ctxp, result) \
72   __md5_finish_ctx (ctxp, result)
73 #endif
74
75
76 /* Define our magic string to mark salt for MD5 "encryption"
77    replacement.  This is meant to be the same as for other MD5 based
78    encryption implementations.  */
79 static const char md5_salt_prefix[] = "$1$";
80
81 /* Table with characters for base64 transformation.  */
82 static const char b64t[64] =
83 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
84
85
86 /* Prototypes for local functions.  */
87 extern char *__md5_crypt_r (const char *key, const char *salt,
88                             char *buffer, int buflen);
89 extern char *__md5_crypt (const char *key, const char *salt);
90
91
92 /* This entry point is equivalent to the `crypt' function in Unix
93    libcs.  */
94 char *
95 __md5_crypt_r (key, salt, buffer, buflen)
96      const char *key;
97      const char *salt;
98      char *buffer;
99      int buflen;
100 {
101   unsigned char alt_result[16]
102     __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
103   size_t salt_len;
104   size_t key_len;
105   size_t cnt;
106   char *cp;
107   char *copied_key = NULL;
108   char *copied_salt = NULL;
109   char *free_key = NULL;
110   size_t alloca_used = 0;
111
112   /* Find beginning of salt string.  The prefix should normally always
113      be present.  Just in case it is not.  */
114   if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
115     /* Skip salt prefix.  */
116     salt += sizeof (md5_salt_prefix) - 1;
117
118   salt_len = MIN (strcspn (salt, "$"), 8);
119   key_len = strlen (key);
120
121   if ((key - (char *) 0) % __alignof__ (md5_uint32) != 0)
122     {
123       char *tmp;
124
125       if (__libc_use_alloca (alloca_used + key_len + __alignof__ (md5_uint32)))
126         tmp = (char *) alloca (key_len + __alignof__ (md5_uint32));
127       else
128         {
129           free_key = tmp = (char *) malloc (key_len + __alignof__ (md5_uint32));
130           if (tmp == NULL)
131             return NULL;
132         }
133
134       key = copied_key =
135         memcpy (tmp + __alignof__ (md5_uint32)
136                 - (tmp - (char *) 0) % __alignof__ (md5_uint32),
137                 key, key_len);
138       assert ((key - (char *) 0) % __alignof__ (md5_uint32) == 0);
139     }
140
141   if ((salt - (char *) 0) % __alignof__ (md5_uint32) != 0)
142     {
143       char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32));
144       salt = copied_salt =
145         memcpy (tmp + __alignof__ (md5_uint32)
146                 - (tmp - (char *) 0) % __alignof__ (md5_uint32),
147                 salt, salt_len);
148       assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0);
149     }
150
151 #ifdef USE_NSS
152   /* Initialize libfreebl3.  */
153   NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
154   if (nss_ictx == NULL)
155     {
156       free (free_key);
157       return NULL;
158     }
159   NSSLOWHASHContext *nss_ctx = NULL;
160   NSSLOWHASHContext *nss_alt_ctx = NULL;
161 #else
162   struct md5_ctx ctx;
163   struct md5_ctx alt_ctx;
164 #endif
165
166   /* Prepare for the real work.  */
167   md5_init_ctx (&ctx, nss_ctx);
168
169   /* Add the key string.  */
170   md5_process_bytes (key, key_len, &ctx, nss_ctx);
171
172   /* Because the SALT argument need not always have the salt prefix we
173      add it separately.  */
174   md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1,
175                      &ctx, nss_ctx);
176
177   /* The last part is the salt string.  This must be at most 8
178      characters and it ends at the first `$' character (for
179      compatibility with existing implementations).  */
180   md5_process_bytes (salt, salt_len, &ctx, nss_ctx);
181
182
183   /* Compute alternate MD5 sum with input KEY, SALT, and KEY.  The
184      final result will be added to the first context.  */
185   md5_init_ctx (&alt_ctx, nss_alt_ctx);
186
187   /* Add key.  */
188   md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
189
190   /* Add salt.  */
191   md5_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
192
193   /* Add key again.  */
194   md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
195
196   /* Now get result of this (16 bytes) and add it to the other
197      context.  */
198   md5_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
199
200   /* Add for any character in the key one byte of the alternate sum.  */
201   for (cnt = key_len; cnt > 16; cnt -= 16)
202     md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
203   md5_process_bytes (alt_result, cnt, &ctx, nss_ctx);
204
205   /* For the following code we need a NUL byte.  */
206   *alt_result = '\0';
207
208   /* The original implementation now does something weird: for every 1
209      bit in the key the first 0 is added to the buffer, for every 0
210      bit the first character of the key.  This does not seem to be
211      what was intended but we have to follow this to be compatible.  */
212   for (cnt = key_len; cnt > 0; cnt >>= 1)
213     md5_process_bytes ((cnt & 1) != 0
214                        ? (const void *) alt_result : (const void *) key, 1,
215                        &ctx, nss_ctx);
216
217   /* Create intermediate result.  */
218   md5_finish_ctx (&ctx, nss_ctx, alt_result);
219
220   /* Now comes another weirdness.  In fear of password crackers here
221      comes a quite long loop which just processes the output of the
222      previous round again.  We cannot ignore this here.  */
223   for (cnt = 0; cnt < 1000; ++cnt)
224     {
225       /* New context.  */
226       md5_init_ctx (&ctx, nss_ctx);
227
228       /* Add key or last result.  */
229       if ((cnt & 1) != 0)
230         md5_process_bytes (key, key_len, &ctx, nss_ctx);
231       else
232         md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
233
234       /* Add salt for numbers not divisible by 3.  */
235       if (cnt % 3 != 0)
236         md5_process_bytes (salt, salt_len, &ctx, nss_ctx);
237
238       /* Add key for numbers not divisible by 7.  */
239       if (cnt % 7 != 0)
240         md5_process_bytes (key, key_len, &ctx, nss_ctx);
241
242       /* Add key or last result.  */
243       if ((cnt & 1) != 0)
244         md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
245       else
246         md5_process_bytes (key, key_len, &ctx, nss_ctx);
247
248       /* Create intermediate result.  */
249       md5_finish_ctx (&ctx, nss_ctx, alt_result);
250     }
251
252 #ifdef USE_NSS
253   /* Free libfreebl3 resources. */
254   NSSLOW_Shutdown (nss_ictx);
255 #endif
256
257   /* Now we can construct the result string.  It consists of three
258      parts.  */
259   cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
260   buflen -= sizeof (md5_salt_prefix) - 1;
261
262   cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
263   buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
264
265   if (buflen > 0)
266     {
267       *cp++ = '$';
268       --buflen;
269     }
270
271   void b64_from_24bit (unsigned int b2, unsigned int b1, unsigned int b0,
272                        int n)
273   {
274     unsigned int w = (b2 << 16) | (b1 << 8) | b0;
275     while (n-- > 0 && buflen > 0)
276       {
277         *cp++ = b64t[w & 0x3f];
278         --buflen;
279         w >>= 6;
280       }
281   }
282
283   b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4);
284   b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4);
285   b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4);
286   b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4);
287   b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4);
288   b64_from_24bit (0, 0, alt_result[11], 2);
289   if (buflen <= 0)
290     {
291       __set_errno (ERANGE);
292       buffer = NULL;
293     }
294   else
295     *cp = '\0';         /* Terminate the string.  */
296
297   /* Clear the buffer for the intermediate result so that people
298      attaching to processes or reading core dumps cannot get any
299      information.  We do it in this way to clear correct_words[]
300      inside the MD5 implementation as well.  */
301 #ifndef USE_NSS
302   __md5_init_ctx (&ctx);
303   __md5_finish_ctx (&ctx, alt_result);
304   memset (&ctx, '\0', sizeof (ctx));
305   memset (&alt_ctx, '\0', sizeof (alt_ctx));
306 #endif
307   if (copied_key != NULL)
308     memset (copied_key, '\0', key_len);
309   if (copied_salt != NULL)
310     memset (copied_salt, '\0', salt_len);
311
312   free (free_key);
313   return buffer;
314 }
315
316 #ifndef _LIBC
317 # define libc_freeres_ptr(decl) decl
318 #endif
319 libc_freeres_ptr (static char *buffer);
320
321 char *
322 __md5_crypt (const char *key, const char *salt)
323 {
324   /* We don't want to have an arbitrary limit in the size of the
325      password.  We can compute the size of the result in advance and
326      so we can prepare the buffer we pass to `md5_crypt_r'.  */
327   static int buflen;
328   int needed = 3 + strlen (salt) + 1 + 26 + 1;
329
330   if (buflen < needed)
331     {
332       char *new_buffer = (char *) realloc (buffer, needed);
333       if (new_buffer == NULL)
334         return NULL;
335
336       buffer = new_buffer;
337       buflen = needed;
338     }
339
340   return __md5_crypt_r (key, salt, buffer, buflen);
341 }
342
343 #ifndef _LIBC
344 static void
345 __attribute__ ((__destructor__))
346 free_mem (void)
347 {
348   free (buffer);
349 }
350 #endif