1 /*
2  * UFC-crypt: ultra fast crypt(3) implementation
3  *
4  * Copyright (C) 1991-2022 Free Software Foundation, Inc.
5  *
6  * The GNU C Library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * The GNU C Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with the GNU C Library; if not, see
18  * <https://www.gnu.org/licenses/>.
19  *
20  * crypt entry points
21  *
22  * @(#)crypt-entry.c	1.2 12/20/96
23  *
24  */
25 
26 #ifdef DEBUG
27 #include <stdio.h>
28 #endif
29 #include <string.h>
30 #include <errno.h>
31 #include <fips-private.h>
32 
33 #ifndef STATIC
34 #define STATIC static
35 #endif
36 
37 #include "crypt-private.h"
38 #include <shlib-compat.h>
39 
40 /* Prototypes for local functions.  */
41 #ifndef __GNU_LIBRARY__
42 void _ufc_clearmem (char *start, int cnt);
43 #else
44 #define _ufc_clearmem(start, cnt)   memset(start, 0, cnt)
45 #endif
46 extern char *__md5_crypt_r (const char *key, const char *salt, char *buffer,
47 			    int buflen);
48 extern char *__md5_crypt (const char *key, const char *salt);
49 extern char *__sha256_crypt_r (const char *key, const char *salt,
50 			       char *buffer, int buflen);
51 extern char *__sha256_crypt (const char *key, const char *salt);
52 extern char *__sha512_crypt_r (const char *key, const char *salt,
53 			       char *buffer, int buflen);
54 extern char *__sha512_crypt (const char *key, const char *salt);
55 
56 /* Define our magic string to mark salt for MD5 encryption
57    replacement.  This is meant to be the same as for other MD5 based
58    encryption implementations.  */
59 static const char md5_salt_prefix[] = "$1$";
60 
61 /* Magic string for SHA256 encryption.  */
62 static const char sha256_salt_prefix[] = "$5$";
63 
64 /* Magic string for SHA512 encryption.  */
65 static const char sha512_salt_prefix[] = "$6$";
66 
67 /* For use by the old, non-reentrant routines (crypt/encrypt/setkey)  */
68 extern struct crypt_data _ufc_foobar;
69 
70 /*
71  * UNIX crypt function
72  */
73 
74 char *
__crypt_r(const char * key,const char * salt,struct crypt_data * __restrict data)75 __crypt_r (const char *key, const char *salt,
76 	   struct crypt_data * __restrict data)
77 {
78   ufc_long res[4];
79   char ktab[9];
80   ufc_long xx = 25; /* to cope with GCC long long compiler bugs */
81 
82 #ifdef _LIBC
83   /* Try to find out whether we have to use MD5 encryption replacement.  */
84   if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
85     {
86       /* FIPS rules out MD5 password encryption.  */
87       if (fips_enabled_p ())
88 	{
89 	  __set_errno (EPERM);
90 	  return NULL;
91 	}
92       return __md5_crypt_r (key, salt, (char *) data,
93 			    sizeof (struct crypt_data));
94     }
95 
96   /* Try to find out whether we have to use SHA256 encryption replacement.  */
97   if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
98     return __sha256_crypt_r (key, salt, (char *) data,
99 			     sizeof (struct crypt_data));
100 
101   /* Try to find out whether we have to use SHA512 encryption replacement.  */
102   if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
103     return __sha512_crypt_r (key, salt, (char *) data,
104 			     sizeof (struct crypt_data));
105 #endif
106 
107   /*
108    * Hack DES tables according to salt
109    */
110   if (!_ufc_setup_salt_r (salt, data))
111     {
112       __set_errno (EINVAL);
113       return NULL;
114     }
115 
116   /* FIPS rules out DES password encryption.  */
117   if (fips_enabled_p ())
118     {
119       __set_errno (EPERM);
120       return NULL;
121     }
122 
123   /*
124    * Setup key schedule
125    */
126   _ufc_clearmem (ktab, (int) sizeof (ktab));
127   (void) strncpy (ktab, key, 8);
128   _ufc_mk_keytab_r (ktab, data);
129 
130   /*
131    * Go for the 25 DES encryptions
132    */
133   _ufc_clearmem ((char*) res, (int) sizeof (res));
134   _ufc_doit_r (xx,  data, &res[0]);
135 
136   /*
137    * Do final permutations
138    */
139   _ufc_dofinalperm_r (res, data);
140 
141   /*
142    * And convert back to 6 bit ASCII
143    */
144   _ufc_output_conversion_r (res[0], res[1], salt, data);
145 
146   /*
147    * Erase key-dependent intermediate data.  Data dependent only on
148    * the salt is not considered sensitive.
149    */
150   explicit_bzero (ktab, sizeof (ktab));
151   explicit_bzero (data->keysched, sizeof (data->keysched));
152   explicit_bzero (res, sizeof (res));
153 
154   return data->crypt_3_buf;
155 }
weak_alias(__crypt_r,crypt_r)156 weak_alias (__crypt_r, crypt_r)
157 
158 char *
159 crypt (const char *key, const char *salt)
160 {
161 #ifdef _LIBC
162   /* Try to find out whether we have to use MD5 encryption replacement.  */
163   if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0
164       /* Let __crypt_r deal with the error code if FIPS is enabled.  */
165       && !fips_enabled_p ())
166     return __md5_crypt (key, salt);
167 
168   /* Try to find out whether we have to use SHA256 encryption replacement.  */
169   if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
170     return __sha256_crypt (key, salt);
171 
172   /* Try to find out whether we have to use SHA512 encryption replacement.  */
173   if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
174     return __sha512_crypt (key, salt);
175 #endif
176 
177   return __crypt_r (key, salt, &_ufc_foobar);
178 }
179 
180 #if SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
181 weak_alias (crypt, fcrypt)
182 compat_symbol (libcrypt, fcrypt, fcrypt, GLIBC_2_0);
183 #endif
184