1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "crypt-port.h"
25#include "alg-sha256.h"
26
27#include <linux/errno.h>
28#include <stdio.h>
29#include <stdlib.h>
30
31#if INCLUDE_sha256crypt
32
33
34
35static const char sha256_salt_prefix[] = "$5$";
36
37
38static const char sha256_rounds_prefix[] = "rounds=";
39
40
41#define SALT_LEN_MAX 16
42
43#define ROUNDS_DEFAULT 5000
44
45#define ROUNDS_MIN 1000
46
47#define ROUNDS_MAX 999999999
48
49
50
51
52
53
54#define LENGTH_OF_NUMBER(n) (sizeof #n - 1)
55
56#define SHA256_HASH_LENGTH \
57 (sizeof (sha256_salt_prefix) + sizeof (sha256_rounds_prefix) + \
58 LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 43)
59
60static_assert (SHA256_HASH_LENGTH <= CRYPT_OUTPUT_SIZE,
61 "CRYPT_OUTPUT_SIZE is too small for SHA256");
62
63
64struct sha256_buffer
65{
66 SHA256_CTX ctx;
67 uint8_t result[32];
68 uint8_t p_bytes[32];
69 uint8_t s_bytes[32];
70};
71
72static_assert (sizeof (struct sha256_buffer) <= ALG_SPECIFIC_SIZE,
73 "ALG_SPECIFIC_SIZE is too small for SHA256");
74
75
76
77static int errno;
78
79void crypt_sha256crypt_rn(const char *phrase, size_t phr_size,
80 const char *setting, size_t ARG_UNUSED(set_size),
81 uint8_t *output, size_t out_size, void *scratch,
82 size_t scr_size);
83
84int crypt_sha256crypt_rn_wrapped(const char *phrase, size_t phr_size,
85 const char *setting, size_t set_size,
86 u8 *output, size_t out_size, void *scratch,
87 size_t scr_size)
88{
89 errno = 0;
90 crypt_sha256crypt_rn(phrase, phr_size, setting, set_size, output,
91 out_size, scratch, scr_size);
92 return -errno;
93}
94
95
96
97static void
98SHA256_Update_recycled (SHA256_CTX *ctx,
99 unsigned char block[32], size_t len)
100{
101 size_t cnt;
102 for (cnt = len; cnt >= 32; cnt -= 32)
103 SHA256_Update (ctx, block, 32);
104 SHA256_Update (ctx, block, cnt);
105}
106
107void
108crypt_sha256crypt_rn (const char *phrase, size_t phr_size,
109 const char *setting, size_t ARG_UNUSED (set_size),
110 uint8_t *output, size_t out_size,
111 void *scratch, size_t scr_size)
112{
113
114 if (out_size < SHA256_HASH_LENGTH
115 || scr_size < sizeof (struct sha256_buffer))
116 {
117 errno = ERANGE;
118 return;
119 }
120
121 struct sha256_buffer *buf = scratch;
122 SHA256_CTX *ctx = &buf->ctx;
123 uint8_t *result = buf->result;
124 uint8_t *p_bytes = buf->p_bytes;
125 uint8_t *s_bytes = buf->s_bytes;
126 char *cp = (char *)output;
127 const char *salt = setting;
128
129 size_t salt_size;
130 size_t cnt;
131
132 size_t rounds = ROUNDS_DEFAULT;
133 bool rounds_custom = false;
134
135
136
137 if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
138
139 salt += sizeof (sha256_salt_prefix) - 1;
140
141 if (strncmp (salt, sha256_rounds_prefix, sizeof (sha256_rounds_prefix) - 1)
142 == 0)
143 {
144 const char *num = salt + sizeof (sha256_rounds_prefix) - 1;
145
146
147 if (!(*num >= '1' && *num <= '9'))
148 {
149 errno = EINVAL;
150 return;
151 }
152
153 errno = 0;
154 char *endp;
155 rounds = strtoul (num, &endp, 10);
156 if (endp == num || *endp != '$'
157 || rounds < ROUNDS_MIN
158 || rounds > ROUNDS_MAX
159 || errno)
160 {
161 errno = EINVAL;
162 return;
163 }
164 salt = endp + 1;
165 rounds_custom = true;
166 }
167
168
169
170
171
172 salt_size = strcspn (salt, "$:\n");
173 if (!(salt[salt_size] == '$' || !salt[salt_size]))
174 {
175 errno = EINVAL;
176 return;
177 }
178
179
180 if (salt_size > SALT_LEN_MAX)
181 salt_size = SALT_LEN_MAX;
182
183
184
185 SHA256_Init (ctx);
186
187
188 SHA256_Update (ctx, phrase, phr_size);
189
190
191 SHA256_Update (ctx, salt, salt_size);
192
193
194 SHA256_Update (ctx, phrase, phr_size);
195
196
197 SHA256_Final (result, ctx);
198
199
200 SHA256_Init (ctx);
201
202
203 SHA256_Update (ctx, phrase, phr_size);
204
205
206
207
208 SHA256_Update (ctx, salt, salt_size);
209
210
211 for (cnt = phr_size; cnt > 32; cnt -= 32)
212 SHA256_Update (ctx, result, 32);
213 SHA256_Update (ctx, result, cnt);
214
215
216
217 for (cnt = phr_size; cnt > 0; cnt >>= 1)
218 if ((cnt & 1) != 0)
219 SHA256_Update (ctx, result, 32);
220 else
221 SHA256_Update (ctx, phrase, phr_size);
222
223
224 SHA256_Final (result, ctx);
225
226
227 SHA256_Init (ctx);
228
229
230 for (cnt = 0; cnt < phr_size; ++cnt)
231 SHA256_Update (ctx, phrase, phr_size);
232
233
234 SHA256_Final (p_bytes, ctx);
235
236
237 SHA256_Init (ctx);
238
239
240 for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt)
241 SHA256_Update (ctx, salt, salt_size);
242
243
244 SHA256_Final (s_bytes, ctx);
245
246
247
248 for (cnt = 0; cnt < rounds; ++cnt)
249 {
250
251 SHA256_Init (ctx);
252
253
254 if ((cnt & 1) != 0)
255 SHA256_Update_recycled (ctx, p_bytes, phr_size);
256 else
257 SHA256_Update (ctx, result, 32);
258
259
260 if (cnt % 3 != 0)
261 SHA256_Update_recycled (ctx, s_bytes, salt_size);
262
263
264 if (cnt % 7 != 0)
265 SHA256_Update_recycled (ctx, p_bytes, phr_size);
266
267
268 if ((cnt & 1) != 0)
269 SHA256_Update (ctx, result, 32);
270 else
271 SHA256_Update_recycled (ctx, p_bytes, phr_size);
272
273
274 SHA256_Final (result, ctx);
275 }
276
277
278
279
280 memcpy (cp, sha256_salt_prefix, sizeof (sha256_salt_prefix) - 1);
281 cp += sizeof (sha256_salt_prefix) - 1;
282
283 if (rounds_custom)
284 {
285 int n = snprintf (cp,
286 SHA256_HASH_LENGTH - (sizeof (sha256_salt_prefix) - 1),
287 "%s%zu$", sha256_rounds_prefix, rounds);
288 cp += n;
289 }
290
291 memcpy (cp, salt, salt_size);
292 cp += salt_size;
293 *cp++ = '$';
294
295#define b64_from_24bit(B2, B1, B0, N) \
296 do { \
297 unsigned int w = ((((unsigned int)(B2)) << 16) | \
298 (((unsigned int)(B1)) << 8) | \
299 ((unsigned int)(B0))); \
300 int n = (N); \
301 while (n-- > 0) \
302 { \
303 *cp++ = b64t[w & 0x3f]; \
304 w >>= 6; \
305 } \
306 } while (0)
307
308 b64_from_24bit (result[0], result[10], result[20], 4);
309 b64_from_24bit (result[21], result[1], result[11], 4);
310 b64_from_24bit (result[12], result[22], result[2], 4);
311 b64_from_24bit (result[3], result[13], result[23], 4);
312 b64_from_24bit (result[24], result[4], result[14], 4);
313 b64_from_24bit (result[15], result[25], result[5], 4);
314 b64_from_24bit (result[6], result[16], result[26], 4);
315 b64_from_24bit (result[27], result[7], result[17], 4);
316 b64_from_24bit (result[18], result[28], result[8], 4);
317 b64_from_24bit (result[9], result[19], result[29], 4);
318 b64_from_24bit (0, result[31], result[30], 3);
319
320 *cp = '\0';
321}
322
323#ifndef NO_GENSALT
324
325void
326gensalt_sha256crypt_rn (unsigned long count,
327 const uint8_t *rbytes, size_t nrbytes,
328 uint8_t *output, size_t output_size)
329{
330 gensalt_sha_rn ('5', SALT_LEN_MAX, ROUNDS_DEFAULT, ROUNDS_MIN, ROUNDS_MAX,
331 count, rbytes, nrbytes, output, output_size);
332}
333
334#endif
335
336#endif
337