blob: 37127d41e14008f1a6341a5fbb28c9632720ec40 [file] [log] [blame]
Steffen Jaeckel229bd512021-07-08 15:57:33 +02001/* 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 * Modified by Steffen Jaeckel <jaeckel-floss at eyet-services.de> in 2020.
8 * To the extent possible under law, the named authors have waived all
9 * copyright and related or neighboring rights to this work.
10 *
11 * See https://creativecommons.org/publicdomain/zero/1.0/ for further
12 * details.
13 *
14 * This file is a modified except from [2], lines 648 up to 909.
15 *
16 * [1] https://www.akkadia.org/drepper/sha-crypt.html
17 * [2] https://www.akkadia.org/drepper/SHA-crypt.txt
18 */
19
20#include "crypt-port.h"
21#include "alg-sha256.h"
22
23#include <errno.h>
24#include <stdio.h>
25#include <stdlib.h>
26
27#if INCLUDE_sha256crypt
28
29/* Define our magic string to mark salt for SHA256 "encryption"
30 replacement. */
31static const char sha256_salt_prefix[] = "$5$";
32
33/* Prefix for optional rounds specification. */
34static const char sha256_rounds_prefix[] = "rounds=";
35
36/* Maximum salt string length. */
37#define SALT_LEN_MAX 16
38/* Default number of rounds if not explicitly specified. */
39#define ROUNDS_DEFAULT 5000
40/* Minimum number of rounds. */
41#define ROUNDS_MIN 1000
42/* Maximum number of rounds. */
43#define ROUNDS_MAX 999999999
44
45/* The maximum possible length of a SHA256-hashed password string,
46 including the terminating NUL character. Prefix (including its NUL)
47 + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX)
48 + salt (up to SALT_LEN_MAX chars) + '$' + hash (43 chars). */
49
50#define LENGTH_OF_NUMBER(n) (sizeof #n - 1)
51
52#define SHA256_HASH_LENGTH \
53 (sizeof (sha256_salt_prefix) + sizeof (sha256_rounds_prefix) + \
54 LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 43)
55
56static_assert (SHA256_HASH_LENGTH <= CRYPT_OUTPUT_SIZE,
57 "CRYPT_OUTPUT_SIZE is too small for SHA256");
58
59/* A sha256_buffer holds all of the sensitive intermediate data. */
60struct sha256_buffer
61{
62 SHA256_CTX ctx;
63 uint8_t result[32];
64 uint8_t p_bytes[32];
65 uint8_t s_bytes[32];
66};
67
68static_assert (sizeof (struct sha256_buffer) <= ALG_SPECIFIC_SIZE,
69 "ALG_SPECIFIC_SIZE is too small for SHA256");
70
71
72/* Feed CTX with LEN bytes of a virtual byte sequence consisting of
73 BLOCK repeated over and over indefinitely. */
74static void
75SHA256_Update_recycled (SHA256_CTX *ctx,
76 unsigned char block[32], size_t len)
77{
78 size_t cnt;
79 for (cnt = len; cnt >= 32; cnt -= 32)
80 SHA256_Update (ctx, block, 32);
81 SHA256_Update (ctx, block, cnt);
82}
83
84void
85crypt_sha256crypt_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 < SHA256_HASH_LENGTH
92 || scr_size < sizeof (struct sha256_buffer))
93 {
94 errno = ERANGE;
95 return;
96 }
97
98 struct sha256_buffer *buf = scratch;
99 SHA256_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 (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
115 /* Skip salt prefix. */
116 salt += sizeof (sha256_salt_prefix) - 1;
117
118 if (strncmp (salt, sha256_rounds_prefix, sizeof (sha256_rounds_prefix) - 1)
119 == 0)
120 {
121 const char *num = salt + sizeof (sha256_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 SHA256 sum with input PHRASE, SALT, and PHRASE. The
161 final result will be added to the first context. */
162 SHA256_Init (ctx);
163
164 /* Add phrase. */
165 SHA256_Update (ctx, phrase, phr_size);
166
167 /* Add salt. */
168 SHA256_Update (ctx, salt, salt_size);
169
170 /* Add phrase again. */
171 SHA256_Update (ctx, phrase, phr_size);
172
173 /* Now get result of this (32 bytes). */
174 SHA256_Final (result, ctx);
175
176 /* Prepare for the real work. */
177 SHA256_Init (ctx);
178
179 /* Add the phrase string. */
180 SHA256_Update (ctx, phrase, phr_size);
181
182 /* The last part is the salt string. This must be at most 8
183 characters and it ends at the first `$' character (for
184 compatibility with existing implementations). */
185 SHA256_Update (ctx, salt, salt_size);
186
187 /* Add for any character in the phrase one byte of the alternate sum. */
188 for (cnt = phr_size; cnt > 32; cnt -= 32)
189 SHA256_Update (ctx, result, 32);
190 SHA256_Update (ctx, result, cnt);
191
192 /* Take the binary representation of the length of the phrase and for every
193 1 add the alternate sum, for every 0 the phrase. */
194 for (cnt = phr_size; cnt > 0; cnt >>= 1)
195 if ((cnt & 1) != 0)
196 SHA256_Update (ctx, result, 32);
197 else
198 SHA256_Update (ctx, phrase, phr_size);
199
200 /* Create intermediate result. */
201 SHA256_Final (result, ctx);
202
203 /* Start computation of P byte sequence. */
204 SHA256_Init (ctx);
205
206 /* For every character in the password add the entire password. */
207 for (cnt = 0; cnt < phr_size; ++cnt)
208 SHA256_Update (ctx, phrase, phr_size);
209
210 /* Finish the digest. */
211 SHA256_Final (p_bytes, ctx);
212
213 /* Start computation of S byte sequence. */
214 SHA256_Init (ctx);
215
216 /* For every character in the password add the entire password. */
217 for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt)
218 SHA256_Update (ctx, salt, salt_size);
219
220 /* Finish the digest. */
221 SHA256_Final (s_bytes, ctx);
222
223 /* Repeatedly run the collected hash value through SHA256 to burn
224 CPU cycles. */
225 for (cnt = 0; cnt < rounds; ++cnt)
226 {
227 /* New context. */
228 SHA256_Init (ctx);
229
230 /* Add phrase or last result. */
231 if ((cnt & 1) != 0)
232 SHA256_Update_recycled (ctx, p_bytes, phr_size);
233 else
234 SHA256_Update (ctx, result, 32);
235
236 /* Add salt for numbers not divisible by 3. */
237 if (cnt % 3 != 0)
238 SHA256_Update_recycled (ctx, s_bytes, salt_size);
239
240 /* Add phrase for numbers not divisible by 7. */
241 if (cnt % 7 != 0)
242 SHA256_Update_recycled (ctx, p_bytes, phr_size);
243
244 /* Add phrase or last result. */
245 if ((cnt & 1) != 0)
246 SHA256_Update (ctx, result, 32);
247 else
248 SHA256_Update_recycled (ctx, p_bytes, phr_size);
249
250 /* Create intermediate result. */
251 SHA256_Final (result, ctx);
252 }
253
254 /* Now we can construct the result string. It consists of four
255 parts, one of which is optional. We already know that there
256 is sufficient space at CP for the longest possible result string. */
257 memcpy (cp, sha256_salt_prefix, sizeof (sha256_salt_prefix) - 1);
258 cp += sizeof (sha256_salt_prefix) - 1;
259
260 if (rounds_custom)
261 {
262 int n = snprintf (cp,
263 SHA256_HASH_LENGTH - (sizeof (sha256_salt_prefix) - 1),
264 "%s%zu$", sha256_rounds_prefix, rounds);
265 cp += n;
266 }
267
268 memcpy (cp, salt, salt_size);
269 cp += salt_size;
270 *cp++ = '$';
271
272#define b64_from_24bit(B2, B1, B0, N) \
273 do { \
274 unsigned int w = ((((unsigned int)(B2)) << 16) | \
275 (((unsigned int)(B1)) << 8) | \
276 ((unsigned int)(B0))); \
277 int n = (N); \
278 while (n-- > 0) \
279 { \
280 *cp++ = b64t[w & 0x3f]; \
281 w >>= 6; \
282 } \
283 } while (0)
284
285 b64_from_24bit (result[0], result[10], result[20], 4);
286 b64_from_24bit (result[21], result[1], result[11], 4);
287 b64_from_24bit (result[12], result[22], result[2], 4);
288 b64_from_24bit (result[3], result[13], result[23], 4);
289 b64_from_24bit (result[24], result[4], result[14], 4);
290 b64_from_24bit (result[15], result[25], result[5], 4);
291 b64_from_24bit (result[6], result[16], result[26], 4);
292 b64_from_24bit (result[27], result[7], result[17], 4);
293 b64_from_24bit (result[18], result[28], result[8], 4);
294 b64_from_24bit (result[9], result[19], result[29], 4);
295 b64_from_24bit (0, result[31], result[30], 3);
296
297 *cp = '\0';
298}
299
300#ifndef NO_GENSALT
301
302void
303gensalt_sha256crypt_rn (unsigned long count,
304 const uint8_t *rbytes, size_t nrbytes,
305 uint8_t *output, size_t output_size)
306{
307 gensalt_sha_rn ('5', SALT_LEN_MAX, ROUNDS_DEFAULT, ROUNDS_MIN, ROUNDS_MAX,
308 count, rbytes, nrbytes, output, output_size);
309}
310
311#endif
312
313#endif