1 /* One way encryption based on the SHA256-based Unix crypt implementation.
2 *
3 * Written by Ulrich Drepper <drepper at redhat.com> in 2007 [1].
4 * Modified by Zack Weinberg <zackw at panix.com> in 2017, 2018.
5 * Composed by Björn Esser <besser82 at fedoraproject.org> in 2018.
6 * Modified by Björn Esser <besser82 at fedoraproject.org> in 2020.
7 * To the extent possible under law, the named authors have waived all
8 * copyright and related or neighboring rights to this work.
9 *
10 * See https://creativecommons.org/publicdomain/zero/1.0/ for further
11 * details.
12 *
13 * This file is a modified except from [2], lines 648 up to 909.
14 *
15 * [1] https://www.akkadia.org/drepper/sha-crypt.html
16 * [2] https://www.akkadia.org/drepper/SHA-crypt.txt
17 */
18
19 #include "crypt-port.h"
20 #include "alg-sha256.h"
21
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #if INCLUDE_sha256crypt
27
28 /* Define our magic string to mark salt for SHA256 "encryption"
29 replacement. */
30 static const char sha256_salt_prefix[] = "$5$";
31
32 /* Prefix for optional rounds specification. */
33 static const char sha256_rounds_prefix[] = "rounds=";
34
35 /* Maximum salt string length. */
36 #define SALT_LEN_MAX 16
37 /* Default number of rounds if not explicitly specified. */
38 #define ROUNDS_DEFAULT 5000
39 /* Minimum number of rounds. */
40 #define ROUNDS_MIN 1000
41 /* Maximum number of rounds. */
42 #define ROUNDS_MAX 999999999
43
44 /* The maximum possible length of a SHA256-hashed password string,
45 including the terminating NUL character. Prefix (including its NUL)
46 + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX)
47 + salt (up to SALT_LEN_MAX chars) + '$' + hash (43 chars). */
48
49 #define LENGTH_OF_NUMBER(n) (sizeof #n - 1)
50
51 #define SHA256_HASH_LENGTH \
52 (sizeof (sha256_salt_prefix) + sizeof (sha256_rounds_prefix) + \
53 LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 43)
54
55 static_assert (SHA256_HASH_LENGTH <= CRYPT_OUTPUT_SIZE,
56 "CRYPT_OUTPUT_SIZE is too small for SHA256");
57
58 /* A sha256_buffer holds all of the sensitive intermediate data. */
59 struct sha256_buffer
60 {
61 SHA256_CTX ctx;
62 uint8_t result[32];
63 uint8_t p_bytes[32];
64 uint8_t s_bytes[32];
65 };
66
67 static_assert (sizeof (struct sha256_buffer) <= ALG_SPECIFIC_SIZE,
68 "ALG_SPECIFIC_SIZE is too small for SHA256");
69
70
71 /* Feed CTX with LEN bytes of a virtual byte sequence consisting of
72 BLOCK repeated over and over indefinitely. */
73 static void
74 SHA256_Update_recycled (SHA256_CTX *ctx,
75 unsigned char block[32], size_t len)
76 {
77 size_t cnt;
78 for (cnt = len; cnt >= 32; cnt -= 32)
79 SHA256_Update (ctx, block, 32);
80 SHA256_Update (ctx, block, cnt);
81 }
82
83 void
84 crypt_sha256crypt_rn (const char *phrase, size_t phr_size,
85 const char *setting, size_t ARG_UNUSED (set_size),
86 uint8_t *output, size_t out_size,
87 void *scratch, size_t scr_size)
88 {
89 /* This shouldn't ever happen, but... */
90 if (out_size < SHA256_HASH_LENGTH
91 || scr_size < sizeof (struct sha256_buffer))
92 {
93 errno = ERANGE;
94 return;
95 }
96
97 struct sha256_buffer *buf = scratch;
98 SHA256_CTX *ctx = &buf->ctx;
99 uint8_t *result = buf->result;
100 uint8_t *p_bytes = buf->p_bytes;
101 uint8_t *s_bytes = buf->s_bytes;
102 char *cp = (char *)output;
103 const char *salt = setting;
104
105 size_t salt_size;
106 size_t cnt;
107 /* Default number of rounds. */
108 size_t rounds = ROUNDS_DEFAULT;
109 bool rounds_custom = false;
110
111 /* Find beginning of salt string. The prefix should normally always
112 be present. Just in case it is not. */
113 if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
114 /* Skip salt prefix. */
115 salt += sizeof (sha256_salt_prefix) - 1;
116
117 if (strncmp (salt, sha256_rounds_prefix, sizeof (sha256_rounds_prefix) - 1)
118 == 0)
119 {
120 const char *num = salt + sizeof (sha256_rounds_prefix) - 1;
121 /* Do not allow an explicit setting of zero rounds, nor of the
122 default number of rounds, nor leading zeroes on the rounds. */
123 if (!(*num >= '1' && *num <= '9'))
124 {
125 errno = EINVAL;
126 return;
127 }
128
129 errno = 0;
130 char *endp;
131 rounds = strtoul (num, &endp, 10);
132 if (endp == num || *endp != '$'
133 || rounds < ROUNDS_MIN
134 || rounds > ROUNDS_MAX
135 || errno)
136 {
137 errno = EINVAL;
138 return;
139 }
140 salt = endp + 1;
141 rounds_custom = true;
142 }
143
144 /* The salt ends at the next '$' or the end of the string.
145 Ensure ':' does not appear in the salt (it is used as a separator in /etc/passwd).
146 Also check for '\n', as in /etc/passwd the whole parameters of the user data must
147 be on a single line. */
148 salt_size = strcspn (salt, "$:\n");
149 if (!(salt[salt_size] == '$' || !salt[salt_size]))
150 {
151 errno = EINVAL;
152 return;
153 }
154
155 /* Ensure we do not use more salt than SALT_LEN_MAX. */
156 if (salt_size > SALT_LEN_MAX)
157 salt_size = SALT_LEN_MAX;
158
159 /* Compute alternate SHA256 sum with input PHRASE, SALT, and PHRASE. The
160 final result will be added to the first context. */
161 SHA256_Init (ctx);
162
163 /* Add phrase. */
164 SHA256_Update (ctx, phrase, phr_size);
165
166 /* Add salt. */
167 SHA256_Update (ctx, salt, salt_size);
168
169 /* Add phrase again. */
170 SHA256_Update (ctx, phrase, phr_size);
171
172 /* Now get result of this (32 bytes). */
173 SHA256_Final (result, ctx);
174
175 /* Prepare for the real work. */
176 SHA256_Init (ctx);
177
178 /* Add the phrase string. */
179 SHA256_Update (ctx, phrase, phr_size);
180
181 /* The last part is the salt string. This must be at most 8
182 characters and it ends at the first `$' character (for
183 compatibility with existing implementations). */
184 SHA256_Update (ctx, salt, salt_size);
185
186 /* Add for any character in the phrase one byte of the alternate sum. */
187 for (cnt = phr_size; cnt > 32; cnt -= 32)
188 SHA256_Update (ctx, result, 32);
189 SHA256_Update (ctx, result, cnt);
190
191 /* Take the binary representation of the length of the phrase and for every
192 1 add the alternate sum, for every 0 the phrase. */
193 for (cnt = phr_size; cnt > 0; cnt >>= 1)
194 if ((cnt & 1) != 0)
195 SHA256_Update (ctx, result, 32);
196 else
197 SHA256_Update (ctx, phrase, phr_size);
198
199 /* Create intermediate result. */
200 SHA256_Final (result, ctx);
201
202 /* Start computation of P byte sequence. */
203 SHA256_Init (ctx);
204
205 /* For every character in the password add the entire password. */
206 for (cnt = 0; cnt < phr_size; ++cnt)
207 SHA256_Update (ctx, phrase, phr_size);
208
209 /* Finish the digest. */
210 SHA256_Final (p_bytes, ctx);
211
212 /* Start computation of S byte sequence. */
213 SHA256_Init (ctx);
214
215 /* For every character in the password add the entire password. */
216 for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt)
217 SHA256_Update (ctx, salt, salt_size);
218
219 /* Finish the digest. */
220 SHA256_Final (s_bytes, ctx);
221
222 /* Repeatedly run the collected hash value through SHA256 to burn
223 CPU cycles. */
224 for (cnt = 0; cnt < rounds; ++cnt)
225 {
226 /* New context. */
227 SHA256_Init (ctx);
228
229 /* Add phrase or last result. */
230 if ((cnt & 1) != 0)
231 SHA256_Update_recycled (ctx, p_bytes, phr_size);
232 else
233 SHA256_Update (ctx, result, 32);
234
235 /* Add salt for numbers not divisible by 3. */
236 if (cnt % 3 != 0)
237 SHA256_Update_recycled (ctx, s_bytes, salt_size);
238
239 /* Add phrase for numbers not divisible by 7. */
240 if (cnt % 7 != 0)
241 SHA256_Update_recycled (ctx, p_bytes, phr_size);
242
243 /* Add phrase or last result. */
244 if ((cnt & 1) != 0)
245 SHA256_Update (ctx, result, 32);
246 else
247 SHA256_Update_recycled (ctx, p_bytes, phr_size);
248
249 /* Create intermediate result. */
250 SHA256_Final (result, ctx);
251 }
252
253 /* Now we can construct the result string. It consists of four
254 parts, one of which is optional. We already know that there
255 is sufficient space at CP for the longest possible result string. */
256 memcpy (cp, sha256_salt_prefix, sizeof (sha256_salt_prefix) - 1);
257 cp += sizeof (sha256_salt_prefix) - 1;
258
259 if (rounds_custom)
260 {
261 int n = snprintf (cp,
262 SHA256_HASH_LENGTH - (sizeof (sha256_salt_prefix) - 1),
263 "%s%zu$", sha256_rounds_prefix, rounds);
264 cp += n;
265 }
266
267 memcpy (cp, salt, salt_size);
268 cp += salt_size;
269 *cp++ = '$';
270
271 #define b64_from_24bit(B2, B1, B0, N) \
272 do { \
273 unsigned int w = ((((unsigned int)(B2)) << 16) | \
274 (((unsigned int)(B1)) << 8) | \
275 ((unsigned int)(B0))); \
276 int n = (N); \
277 while (n-- > 0) \
278 { \
279 *cp++ = b64t[w & 0x3f]; \
280 w >>= 6; \
281 } \
282 } while (0)
283
284 b64_from_24bit (result[0], result[10], result[20], 4);
285 b64_from_24bit (result[21], result[1], result[11], 4);
286 b64_from_24bit (result[12], result[22], result[2], 4);
287 b64_from_24bit (result[3], result[13], result[23], 4);
288 b64_from_24bit (result[24], result[4], result[14], 4);
289 b64_from_24bit (result[15], result[25], result[5], 4);
290 b64_from_24bit (result[6], result[16], result[26], 4);
291 b64_from_24bit (result[27], result[7], result[17], 4);
292 b64_from_24bit (result[18], result[28], result[8], 4);
293 b64_from_24bit (result[9], result[19], result[29], 4);
294 b64_from_24bit (0, result[31], result[30], 3);
295
296 *cp = '\0';
297 }
298
299 void
300 gensalt_sha256crypt_rn (unsigned long count,
301 const uint8_t *rbytes, size_t nrbytes,
302 uint8_t *output, size_t output_size)
303 {
304 gensalt_sha_rn ('5', SALT_LEN_MAX, ROUNDS_DEFAULT, ROUNDS_MIN, ROUNDS_MAX,
305 count, rbytes, nrbytes, output, output_size);
306 }
307
308 #endif