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