1 /* One way encryption based on SHA256 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 "sha256.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 sha256_init_ctx(ctxp, nss_ctxp) \
37   do									      \
38     {									      \
39       if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgSHA256))      \
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 sha256_process_bytes(buf, len, ctxp, nss_ctxp) \
53   NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
54 
55 # define sha256_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 sha256_init_ctx(ctxp, nss_ctxp) \
67   __sha256_init_ctx (ctxp)
68 
69 # define sha256_process_bytes(buf, len, ctxp, nss_ctxp) \
70   __sha256_process_bytes(buf, len, ctxp)
71 
72 # define sha256_finish_ctx(ctxp, nss_ctxp, result) \
73   __sha256_finish_ctx (ctxp, result)
74 #endif
75 
76 
77 /* Define our magic string to mark salt for SHA256 "encryption"
78    replacement.  */
79 static const char sha256_salt_prefix[] = "$5$";
80 
81 /* Prefix for optional rounds specification.  */
82 static const char sha256_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 *__sha256_crypt_r (const char *key, const char *salt,
96 			       char *buffer, int buflen);
97 extern char *__sha256_crypt (const char *key, const char *salt);
98 
99 
100 char *
__sha256_crypt_r(const char * key,const char * salt,char * buffer,int buflen)101 __sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
102 {
103   unsigned char alt_result[32]
104     __attribute__ ((__aligned__ (__alignof__ (uint32_t))));
105   unsigned char temp_result[32]
106     __attribute__ ((__aligned__ (__alignof__ (uint32_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 (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
125     /* Skip salt prefix.  */
126     salt += sizeof (sha256_salt_prefix) - 1;
127 
128   if (strncmp (salt, sha256_rounds_prefix, sizeof (sha256_rounds_prefix) - 1)
129       == 0)
130     {
131       const char *num = salt + sizeof (sha256_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__ (uint32_t) != 0)
146     {
147       char *tmp;
148 
149       if (__libc_use_alloca (alloca_used + key_len + __alignof__ (uint32_t)))
150 	tmp = alloca_account (key_len + __alignof__ (uint32_t), alloca_used);
151       else
152 	{
153 	  free_key = tmp = (char *) malloc (key_len + __alignof__ (uint32_t));
154 	  if (tmp == NULL)
155 	    return NULL;
156 	}
157 
158       key = copied_key =
159 	memcpy (tmp + __alignof__ (uint32_t)
160 		- (tmp - (char *) 0) % __alignof__ (uint32_t),
161 		key, key_len);
162       assert ((key - (char *) 0) % __alignof__ (uint32_t) == 0);
163     }
164 
165   if ((salt - (char *) 0) % __alignof__ (uint32_t) != 0)
166     {
167       char *tmp = (char *) alloca (salt_len + __alignof__ (uint32_t));
168       alloca_used += salt_len + __alignof__ (uint32_t);
169       salt = copied_salt =
170 	memcpy (tmp + __alignof__ (uint32_t)
171 		- (tmp - (char *) 0) % __alignof__ (uint32_t),
172 		salt, salt_len);
173       assert ((salt - (char *) 0) % __alignof__ (uint32_t) == 0);
174     }
175 
176 #ifdef USE_NSS
177   /* Initialize libfreebl3.  */
178   NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
179   if (nss_ictx == NULL)
180     {
181       free (free_key);
182       return NULL;
183     }
184   NSSLOWHASHContext *nss_ctx = NULL;
185   NSSLOWHASHContext *nss_alt_ctx = NULL;
186 #else
187   struct sha256_ctx ctx;
188   struct sha256_ctx alt_ctx;
189 #endif
190 
191   /* Prepare for the real work.  */
192   sha256_init_ctx (&ctx, nss_ctx);
193 
194   /* Add the key string.  */
195   sha256_process_bytes (key, key_len, &ctx, nss_ctx);
196 
197   /* The last part is the salt string.  This must be at most 16
198      characters and it ends at the first `$' character.  */
199   sha256_process_bytes (salt, salt_len, &ctx, nss_ctx);
200 
201 
202   /* Compute alternate SHA256 sum with input KEY, SALT, and KEY.  The
203      final result will be added to the first context.  */
204   sha256_init_ctx (&alt_ctx, nss_alt_ctx);
205 
206   /* Add key.  */
207   sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
208 
209   /* Add salt.  */
210   sha256_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
211 
212   /* Add key again.  */
213   sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
214 
215   /* Now get result of this (32 bytes) and add it to the other
216      context.  */
217   sha256_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
218 
219   /* Add for any character in the key one byte of the alternate sum.  */
220   for (cnt = key_len; cnt > 32; cnt -= 32)
221     sha256_process_bytes (alt_result, 32, &ctx, nss_ctx);
222   sha256_process_bytes (alt_result, cnt, &ctx, nss_ctx);
223 
224   /* Take the binary representation of the length of the key and for every
225      1 add the alternate sum, for every 0 the key.  */
226   for (cnt = key_len; cnt > 0; cnt >>= 1)
227     if ((cnt & 1) != 0)
228       sha256_process_bytes (alt_result, 32, &ctx, nss_ctx);
229     else
230       sha256_process_bytes (key, key_len, &ctx, nss_ctx);
231 
232   /* Create intermediate result.  */
233   sha256_finish_ctx (&ctx, nss_ctx, alt_result);
234 
235   /* Start computation of P byte sequence.  */
236   sha256_init_ctx (&alt_ctx, nss_alt_ctx);
237 
238   /* For every character in the password add the entire password.  */
239   for (cnt = 0; cnt < key_len; ++cnt)
240     sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
241 
242   /* Finish the digest.  */
243   sha256_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
244 
245   /* Create byte sequence P.  */
246   if (__libc_use_alloca (alloca_used + key_len))
247     cp = p_bytes = (char *) alloca (key_len);
248   else
249     {
250       free_pbytes = cp = p_bytes = (char *)malloc (key_len);
251       if (free_pbytes == NULL)
252 	{
253 	  free (free_key);
254 	  return NULL;
255 	}
256     }
257 
258   for (cnt = key_len; cnt >= 32; cnt -= 32)
259     cp = mempcpy (cp, temp_result, 32);
260   memcpy (cp, temp_result, cnt);
261 
262   /* Start computation of S byte sequence.  */
263   sha256_init_ctx (&alt_ctx, nss_alt_ctx);
264 
265   /* For every character in the password add the entire password.  */
266   for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
267     sha256_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
268 
269   /* Finish the digest.  */
270   sha256_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
271 
272   /* Create byte sequence S.  */
273   cp = s_bytes = alloca (salt_len);
274   for (cnt = salt_len; cnt >= 32; cnt -= 32)
275     cp = mempcpy (cp, temp_result, 32);
276   memcpy (cp, temp_result, cnt);
277 
278   /* Repeatedly run the collected hash value through SHA256 to burn
279      CPU cycles.  */
280   for (cnt = 0; cnt < rounds; ++cnt)
281     {
282       /* New context.  */
283       sha256_init_ctx (&ctx, nss_ctx);
284 
285       /* Add key or last result.  */
286       if ((cnt & 1) != 0)
287 	sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
288       else
289 	sha256_process_bytes (alt_result, 32, &ctx, nss_ctx);
290 
291       /* Add salt for numbers not divisible by 3.  */
292       if (cnt % 3 != 0)
293 	sha256_process_bytes (s_bytes, salt_len, &ctx, nss_ctx);
294 
295       /* Add key for numbers not divisible by 7.  */
296       if (cnt % 7 != 0)
297 	sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
298 
299       /* Add key or last result.  */
300       if ((cnt & 1) != 0)
301 	sha256_process_bytes (alt_result, 32, &ctx, nss_ctx);
302       else
303 	sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
304 
305       /* Create intermediate result.  */
306       sha256_finish_ctx (&ctx, nss_ctx, alt_result);
307     }
308 
309 #ifdef USE_NSS
310   /* Free libfreebl3 resources. */
311   NSSLOW_Shutdown (nss_ictx);
312 #endif
313 
314   /* Now we can construct the result string.  It consists of three
315      parts.  */
316   cp = __stpncpy (buffer, sha256_salt_prefix, MAX (0, buflen));
317   buflen -= sizeof (sha256_salt_prefix) - 1;
318 
319   if (rounds_custom)
320     {
321       int n = __snprintf (cp, MAX (0, buflen), "%s%zu$",
322 			  sha256_rounds_prefix, rounds);
323       cp += n;
324       buflen -= n;
325     }
326 
327   cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
328   buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
329 
330   if (buflen > 0)
331     {
332       *cp++ = '$';
333       --buflen;
334     }
335 
336   __b64_from_24bit (&cp, &buflen,
337 		    alt_result[0], alt_result[10], alt_result[20], 4);
338   __b64_from_24bit (&cp, &buflen,
339 		    alt_result[21], alt_result[1], alt_result[11], 4);
340   __b64_from_24bit (&cp, &buflen,
341 		    alt_result[12], alt_result[22], alt_result[2], 4);
342   __b64_from_24bit (&cp, &buflen,
343 		    alt_result[3], alt_result[13], alt_result[23], 4);
344   __b64_from_24bit (&cp, &buflen,
345 		    alt_result[24], alt_result[4], alt_result[14], 4);
346   __b64_from_24bit (&cp, &buflen,
347 		    alt_result[15], alt_result[25], alt_result[5], 4);
348   __b64_from_24bit (&cp, &buflen,
349 		    alt_result[6], alt_result[16], alt_result[26], 4);
350   __b64_from_24bit (&cp, &buflen,
351 		    alt_result[27], alt_result[7], alt_result[17], 4);
352   __b64_from_24bit (&cp, &buflen,
353 		    alt_result[18], alt_result[28], alt_result[8], 4);
354   __b64_from_24bit (&cp, &buflen,
355 		    alt_result[9], alt_result[19], alt_result[29], 4);
356   __b64_from_24bit (&cp, &buflen,
357 		    0, alt_result[31], alt_result[30], 3);
358   if (buflen <= 0)
359     {
360       __set_errno (ERANGE);
361       buffer = NULL;
362     }
363   else
364     *cp = '\0';		/* Terminate the string.  */
365 
366   /* Clear the buffer for the intermediate result so that people
367      attaching to processes or reading core dumps cannot get any
368      information.  We do it in this way to clear correct_words[]
369      inside the SHA256 implementation as well.  */
370 #ifndef USE_NSS
371   __sha256_init_ctx (&ctx);
372   __sha256_finish_ctx (&ctx, alt_result);
373   explicit_bzero (&ctx, sizeof (ctx));
374   explicit_bzero (&alt_ctx, sizeof (alt_ctx));
375 #endif
376   explicit_bzero (temp_result, sizeof (temp_result));
377   explicit_bzero (p_bytes, key_len);
378   explicit_bzero (s_bytes, salt_len);
379   if (copied_key != NULL)
380     explicit_bzero (copied_key, key_len);
381   if (copied_salt != NULL)
382     explicit_bzero (copied_salt, salt_len);
383 
384   free (free_key);
385   free (free_pbytes);
386   return buffer;
387 }
388 
389 #ifndef _LIBC
390 # define libc_freeres_ptr(decl) decl
391 #endif
392 libc_freeres_ptr (static char *buffer);
393 
394 /* This entry point is equivalent to the `crypt' function in Unix
395    libcs.  */
396 char *
__sha256_crypt(const char * key,const char * salt)397 __sha256_crypt (const char *key, const char *salt)
398 {
399   /* We don't want to have an arbitrary limit in the size of the
400      password.  We can compute an upper bound for the size of the
401      result in advance and so we can prepare the buffer we pass to
402      `sha256_crypt_r'.  */
403   static int buflen;
404   int needed = (sizeof (sha256_salt_prefix) - 1
405 		+ sizeof (sha256_rounds_prefix) + 9 + 1
406 		+ strlen (salt) + 1 + 43 + 1);
407 
408   if (buflen < needed)
409     {
410       char *new_buffer = (char *) realloc (buffer, needed);
411       if (new_buffer == NULL)
412 	return NULL;
413 
414       buffer = new_buffer;
415       buflen = needed;
416     }
417 
418   return __sha256_crypt_r (key, salt, buffer, buflen);
419 }
420 
421 #ifndef _LIBC
422 static void
423 __attribute__ ((__destructor__))
free_mem(void)424 free_mem (void)
425 {
426   free (buffer);
427 }
428 #endif
429