1 /* One way encryption based on SHA512 sum.
2    Copyright (C) 2007-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <assert.h>
20 #include <errno.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdint.h>
25 #include <sys/param.h>
26 
27 #include "sha512.h"
28 #include "crypt-private.h"
29 
30 
31 #ifdef USE_NSS
32 typedef int PRBool;
33 # include <hasht.h>
34 # include <nsslowhash.h>
35 
36 # define sha512_init_ctx(ctxp, nss_ctxp) \
37   do									      \
38     {									      \
39       if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgSHA512))      \
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)
51 
52 # define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \
53   NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
54 
55 # define sha512_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 sha512_init_ctx(ctxp, nss_ctxp) \
67   __sha512_init_ctx (ctxp)
68 
69 # define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \
70   __sha512_process_bytes(buf, len, ctxp)
71 
72 # define sha512_finish_ctx(ctxp, nss_ctxp, result) \
73   __sha512_finish_ctx (ctxp, result)
74 #endif
75 
76 
77 /* Define our magic string to mark salt for SHA512 "encryption"
78    replacement.  */
79 static const char sha512_salt_prefix[] = "$6$";
80 
81 /* Prefix for optional rounds specification.  */
82 static const char sha512_rounds_prefix[] = "rounds=";
83 
84 /* Maximum salt string length.  */
85 #define SALT_LEN_MAX 16
86 /* Default number of rounds if not explicitly specified.  */
87 #define ROUNDS_DEFAULT 5000
88 /* Minimum number of rounds.  */
89 #define ROUNDS_MIN 1000
90 /* Maximum number of rounds.  */
91 #define ROUNDS_MAX 999999999
92 
93 
94 /* Prototypes for local functions.  */
95 extern char *__sha512_crypt_r (const char *key, const char *salt,
96 			       char *buffer, int buflen);
97 extern char *__sha512_crypt (const char *key, const char *salt);
98 
99 
100 char *
__sha512_crypt_r(const char * key,const char * salt,char * buffer,int buflen)101 __sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
102 {
103   unsigned char alt_result[64]
104     __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
105   unsigned char temp_result[64]
106     __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
107   size_t salt_len;
108   size_t key_len;
109   size_t cnt;
110   char *cp;
111   char *copied_key = NULL;
112   char *copied_salt = NULL;
113   char *p_bytes;
114   char *s_bytes;
115   /* Default number of rounds.  */
116   size_t rounds = ROUNDS_DEFAULT;
117   bool rounds_custom = false;
118   size_t alloca_used = 0;
119   char *free_key = NULL;
120   char *free_pbytes = NULL;
121 
122   /* Find beginning of salt string.  The prefix should normally always
123      be present.  Just in case it is not.  */
124   if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
125     /* Skip salt prefix.  */
126     salt += sizeof (sha512_salt_prefix) - 1;
127 
128   if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
129       == 0)
130     {
131       const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
132       char *endp;
133       unsigned long int srounds = strtoul (num, &endp, 10);
134       if (*endp == '$')
135 	{
136 	  salt = endp + 1;
137 	  rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
138 	  rounds_custom = true;
139 	}
140     }
141 
142   salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
143   key_len = strlen (key);
144 
145   if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
146     {
147       char *tmp;
148 
149       if (__libc_use_alloca (alloca_used + key_len + __alignof__ (uint64_t)))
150 	tmp = alloca_account (key_len + __alignof__ (uint64_t), alloca_used);
151       else
152 	{
153 	  free_key = tmp = (char *) malloc (key_len + __alignof__ (uint64_t));
154 	  if (tmp == NULL)
155 	    return NULL;
156 	}
157 
158       key = copied_key =
159 	memcpy (tmp + __alignof__ (uint64_t)
160 		- (tmp - (char *) 0) % __alignof__ (uint64_t),
161 		key, key_len);
162       assert ((key - (char *) 0) % __alignof__ (uint64_t) == 0);
163     }
164 
165   if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0)
166     {
167       char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
168       salt = copied_salt =
169 	memcpy (tmp + __alignof__ (uint64_t)
170 		- (tmp - (char *) 0) % __alignof__ (uint64_t),
171 		salt, salt_len);
172       assert ((salt - (char *) 0) % __alignof__ (uint64_t) == 0);
173     }
174 
175 #ifdef USE_NSS
176   /* Initialize libfreebl3.  */
177   NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
178   if (nss_ictx == NULL)
179     {
180       free (free_key);
181       return NULL;
182     }
183   NSSLOWHASHContext *nss_ctx = NULL;
184   NSSLOWHASHContext *nss_alt_ctx = NULL;
185 #else
186   struct sha512_ctx ctx;
187   struct sha512_ctx alt_ctx;
188 #endif
189 
190   /* Prepare for the real work.  */
191   sha512_init_ctx (&ctx, nss_ctx);
192 
193   /* Add the key string.  */
194   sha512_process_bytes (key, key_len, &ctx, nss_ctx);
195 
196   /* The last part is the salt string.  This must be at most 16
197      characters and it ends at the first `$' character.  */
198   sha512_process_bytes (salt, salt_len, &ctx, nss_ctx);
199 
200 
201   /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.  The
202      final result will be added to the first context.  */
203   sha512_init_ctx (&alt_ctx, nss_alt_ctx);
204 
205   /* Add key.  */
206   sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
207 
208   /* Add salt.  */
209   sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
210 
211   /* Add key again.  */
212   sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
213 
214   /* Now get result of this (64 bytes) and add it to the other
215      context.  */
216   sha512_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
217 
218   /* Add for any character in the key one byte of the alternate sum.  */
219   for (cnt = key_len; cnt > 64; cnt -= 64)
220     sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
221   sha512_process_bytes (alt_result, cnt, &ctx, nss_ctx);
222 
223   /* Take the binary representation of the length of the key and for every
224      1 add the alternate sum, for every 0 the key.  */
225   for (cnt = key_len; cnt > 0; cnt >>= 1)
226     if ((cnt & 1) != 0)
227       sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
228     else
229       sha512_process_bytes (key, key_len, &ctx, nss_ctx);
230 
231   /* Create intermediate result.  */
232   sha512_finish_ctx (&ctx, nss_ctx, alt_result);
233 
234   /* Start computation of P byte sequence.  */
235   sha512_init_ctx (&alt_ctx, nss_alt_ctx);
236 
237   /* For every character in the password add the entire password.  */
238   for (cnt = 0; cnt < key_len; ++cnt)
239     sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
240 
241   /* Finish the digest.  */
242   sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
243 
244   /* Create byte sequence P.  */
245   if (__libc_use_alloca (alloca_used + key_len))
246     cp = p_bytes = (char *) alloca (key_len);
247   else
248     {
249       free_pbytes = cp = p_bytes = (char *)malloc (key_len);
250       if (free_pbytes == NULL)
251 	{
252 	  free (free_key);
253 	  return NULL;
254 	}
255     }
256 
257   for (cnt = key_len; cnt >= 64; cnt -= 64)
258     cp = mempcpy (cp, temp_result, 64);
259   memcpy (cp, temp_result, cnt);
260 
261   /* Start computation of S byte sequence.  */
262   sha512_init_ctx (&alt_ctx, nss_alt_ctx);
263 
264   /* For every character in the password add the entire password.  */
265   for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
266     sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
267 
268   /* Finish the digest.  */
269   sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
270 
271   /* Create byte sequence S.  */
272   cp = s_bytes = alloca (salt_len);
273   for (cnt = salt_len; cnt >= 64; cnt -= 64)
274     cp = mempcpy (cp, temp_result, 64);
275   memcpy (cp, temp_result, cnt);
276 
277   /* Repeatedly run the collected hash value through SHA512 to burn
278      CPU cycles.  */
279   for (cnt = 0; cnt < rounds; ++cnt)
280     {
281       /* New context.  */
282       sha512_init_ctx (&ctx, nss_ctx);
283 
284       /* Add key or last result.  */
285       if ((cnt & 1) != 0)
286 	sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
287       else
288 	sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
289 
290       /* Add salt for numbers not divisible by 3.  */
291       if (cnt % 3 != 0)
292 	sha512_process_bytes (s_bytes, salt_len, &ctx, nss_ctx);
293 
294       /* Add key for numbers not divisible by 7.  */
295       if (cnt % 7 != 0)
296 	sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
297 
298       /* Add key or last result.  */
299       if ((cnt & 1) != 0)
300 	sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
301       else
302 	sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
303 
304       /* Create intermediate result.  */
305       sha512_finish_ctx (&ctx, nss_ctx, alt_result);
306     }
307 
308 #ifdef USE_NSS
309   /* Free libfreebl3 resources. */
310   NSSLOW_Shutdown (nss_ictx);
311 #endif
312 
313   /* Now we can construct the result string.  It consists of three
314      parts.  */
315   cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen));
316   buflen -= sizeof (sha512_salt_prefix) - 1;
317 
318   if (rounds_custom)
319     {
320       int n = __snprintf (cp, MAX (0, buflen), "%s%zu$",
321 			  sha512_rounds_prefix, rounds);
322       cp += n;
323       buflen -= n;
324     }
325 
326   cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
327   buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
328 
329   if (buflen > 0)
330     {
331       *cp++ = '$';
332       --buflen;
333     }
334 
335   __b64_from_24bit (&cp, &buflen,
336 		    alt_result[0], alt_result[21], alt_result[42], 4);
337   __b64_from_24bit (&cp, &buflen,
338 		    alt_result[22], alt_result[43], alt_result[1], 4);
339   __b64_from_24bit (&cp, &buflen,
340 		    alt_result[44], alt_result[2], alt_result[23], 4);
341   __b64_from_24bit (&cp, &buflen,
342 		    alt_result[3], alt_result[24], alt_result[45], 4);
343   __b64_from_24bit (&cp, &buflen,
344 		    alt_result[25], alt_result[46], alt_result[4], 4);
345   __b64_from_24bit (&cp, &buflen,
346 		    alt_result[47], alt_result[5], alt_result[26], 4);
347   __b64_from_24bit (&cp, &buflen,
348 		    alt_result[6], alt_result[27], alt_result[48], 4);
349   __b64_from_24bit (&cp, &buflen,
350 		    alt_result[28], alt_result[49], alt_result[7], 4);
351   __b64_from_24bit (&cp, &buflen,
352 		    alt_result[50], alt_result[8], alt_result[29], 4);
353   __b64_from_24bit (&cp, &buflen,
354 		    alt_result[9], alt_result[30], alt_result[51], 4);
355   __b64_from_24bit (&cp, &buflen,
356 		    alt_result[31], alt_result[52], alt_result[10], 4);
357   __b64_from_24bit (&cp, &buflen,
358 		    alt_result[53], alt_result[11], alt_result[32], 4);
359   __b64_from_24bit (&cp, &buflen,
360 		    alt_result[12], alt_result[33], alt_result[54], 4);
361   __b64_from_24bit (&cp, &buflen,
362 		    alt_result[34], alt_result[55], alt_result[13], 4);
363   __b64_from_24bit (&cp, &buflen,
364 		    alt_result[56], alt_result[14], alt_result[35], 4);
365   __b64_from_24bit (&cp, &buflen,
366 		    alt_result[15], alt_result[36], alt_result[57], 4);
367   __b64_from_24bit (&cp, &buflen,
368 		    alt_result[37], alt_result[58], alt_result[16], 4);
369   __b64_from_24bit (&cp, &buflen,
370 		    alt_result[59], alt_result[17], alt_result[38], 4);
371   __b64_from_24bit (&cp, &buflen,
372 		    alt_result[18], alt_result[39], alt_result[60], 4);
373   __b64_from_24bit (&cp, &buflen,
374 		    alt_result[40], alt_result[61], alt_result[19], 4);
375   __b64_from_24bit (&cp, &buflen,
376 		    alt_result[62], alt_result[20], alt_result[41], 4);
377   __b64_from_24bit (&cp, &buflen,
378 		    0, 0, alt_result[63], 2);
379 
380   if (buflen <= 0)
381     {
382       __set_errno (ERANGE);
383       buffer = NULL;
384     }
385   else
386     *cp = '\0';		/* Terminate the string.  */
387 
388   /* Clear the buffer for the intermediate result so that people
389      attaching to processes or reading core dumps cannot get any
390      information.  We do it in this way to clear correct_words[]
391      inside the SHA512 implementation as well.  */
392 #ifndef USE_NSS
393   __sha512_init_ctx (&ctx);
394   __sha512_finish_ctx (&ctx, alt_result);
395   explicit_bzero (&ctx, sizeof (ctx));
396   explicit_bzero (&alt_ctx, sizeof (alt_ctx));
397 #endif
398   explicit_bzero (temp_result, sizeof (temp_result));
399   explicit_bzero (p_bytes, key_len);
400   explicit_bzero (s_bytes, salt_len);
401   if (copied_key != NULL)
402     explicit_bzero (copied_key, key_len);
403   if (copied_salt != NULL)
404     explicit_bzero (copied_salt, salt_len);
405 
406   free (free_key);
407   free (free_pbytes);
408   return buffer;
409 }
410 
411 #ifndef _LIBC
412 # define libc_freeres_ptr(decl) decl
413 #endif
414 libc_freeres_ptr (static char *buffer);
415 
416 /* This entry point is equivalent to the `crypt' function in Unix
417    libcs.  */
418 char *
__sha512_crypt(const char * key,const char * salt)419 __sha512_crypt (const char *key, const char *salt)
420 {
421   /* We don't want to have an arbitrary limit in the size of the
422      password.  We can compute an upper bound for the size of the
423      result in advance and so we can prepare the buffer we pass to
424      `sha512_crypt_r'.  */
425   static int buflen;
426   int needed = (sizeof (sha512_salt_prefix) - 1
427 		+ sizeof (sha512_rounds_prefix) + 9 + 1
428 		+ strlen (salt) + 1 + 86 + 1);
429 
430   if (buflen < needed)
431     {
432       char *new_buffer = (char *) realloc (buffer, needed);
433       if (new_buffer == NULL)
434 	return NULL;
435 
436       buffer = new_buffer;
437       buflen = needed;
438     }
439 
440   return __sha512_crypt_r (key, salt, buffer, buflen);
441 }
442 
443 #ifndef _LIBC
444 static void
445 __attribute__ ((__destructor__))
free_mem(void)446 free_mem (void)
447 {
448   free (buffer);
449 }
450 #endif
451