1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <assert.h>
22: #include <errno.h>
23: #include <stdbool.h>
24: #include <stdlib.h>
25: #include <string.h>
26: #include <sys/param.h>
27:
28: #include "sha512.h"
29:
30:
31:
32:
33: static const char sha512_salt_prefix[] = "$6$";
34:
35:
36: static const char sha512_rounds_prefix[] = "rounds=";
37:
38:
39: #define SALT_LEN_MAX 16
40:
41: #define ROUNDS_DEFAULT 5000
42:
43: #define ROUNDS_MIN 1000
44:
45: #define ROUNDS_MAX 999999999
46:
47:
48: static const char b64t[64] =
49: "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
50:
51:
52:
53: extern char *__sha512_crypt_r (const char *key, const char *salt,
54: char *buffer, int buflen);
55: extern char *__sha512_crypt (const char *key, const char *salt);
56:
57:
58: char *
59: __sha512_crypt_r (key, salt, buffer, buflen)
60: const char *key;
61: const char *salt;
62: char *buffer;
63: int buflen;
64: {
65: unsigned char alt_result[64]
66: __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
67: unsigned char temp_result[64]
68: __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
69: struct sha512_ctx ctx;
70: struct sha512_ctx alt_ctx;
71: size_t salt_len;
72: size_t key_len;
73: size_t cnt;
74: char *cp;
75: char *copied_key = NULL;
76: char *copied_salt = NULL;
77: char *p_bytes;
78: char *s_bytes;
79:
80: size_t rounds = ROUNDS_DEFAULT;
81: bool rounds_custom = false;
82:
83:
84:
85: if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
86:
87: salt += sizeof (sha512_salt_prefix) - 1;
88:
89: if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
90: == 0)
91: {
92: const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
93: char *endp;
94: unsigned long int srounds = strtoul (num, &endp, 10);
95: if (*endp == '$')
96: {
97: salt = endp + 1;
98: rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
99: rounds_custom = true;
100: }
101: }
102:
103: salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
104: key_len = strlen (key);
105:
106: if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
107: {
108: char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
109: key = copied_key =
110: memcpy (tmp + __alignof__ (uint64_t)
111: - (tmp - (char *) 0) % __alignof__ (uint64_t),
112: key, key_len);
113: assert ((key - (char *) 0) % __alignof__ (uint64_t) == 0);
114: }
115:
116: if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0)
117: {
118: char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
119: salt = copied_salt =
120: memcpy (tmp + __alignof__ (uint64_t)
121: - (tmp - (char *) 0) % __alignof__ (uint64_t),
122: salt, salt_len);
123: assert ((salt - (char *) 0) % __alignof__ (uint64_t) == 0);
124: }
125:
126:
127: __sha512_init_ctx (&ctx);
128:
129:
130: __sha512_process_bytes (key, key_len, &ctx);
131:
132:
133:
134:
135: __sha512_process_bytes (salt, salt_len, &ctx);
136:
137:
138:
139:
140: __sha512_init_ctx (&alt_ctx);
141:
142:
143: __sha512_process_bytes (key, key_len, &alt_ctx);
144:
145:
146: __sha512_process_bytes (salt, salt_len, &alt_ctx);
147:
148:
149: __sha512_process_bytes (key, key_len, &alt_ctx);
150:
151:
152:
153: __sha512_finish_ctx (&alt_ctx, alt_result);
154:
155:
156: for (cnt = key_len; cnt > 64; cnt -= 64)
157: __sha512_process_bytes (alt_result, 64, &ctx);
158: __sha512_process_bytes (alt_result, cnt, &ctx);
159:
160:
161:
162: for (cnt = key_len; cnt > 0; cnt >>= 1)
163: if ((cnt & 1) != 0)
164: __sha512_process_bytes (alt_result, 64, &ctx);
165: else
166: __sha512_process_bytes (key, key_len, &ctx);
167:
168:
169: __sha512_finish_ctx (&ctx, alt_result);
170:
171:
172: __sha512_init_ctx (&alt_ctx);
173:
174:
175: for (cnt = 0; cnt < key_len; ++cnt)
176: __sha512_process_bytes (key, key_len, &alt_ctx);
177:
178:
179: __sha512_finish_ctx (&alt_ctx, temp_result);
180:
181:
182: cp = p_bytes = alloca (key_len);
183: for (cnt = key_len; cnt >= 64; cnt -= 64)
184: cp = mempcpy (cp, temp_result, 64);
185: memcpy (cp, temp_result, cnt);
186:
187:
188: __sha512_init_ctx (&alt_ctx);
189:
190:
191: for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
192: __sha512_process_bytes (salt, salt_len, &alt_ctx);
193:
194:
195: __sha512_finish_ctx (&alt_ctx, temp_result);
196:
197:
198: cp = s_bytes = alloca (salt_len);
199: for (cnt = salt_len; cnt >= 64; cnt -= 64)
200: cp = mempcpy (cp, temp_result, 64);
201: memcpy (cp, temp_result, cnt);
202:
203:
204:
205: for (cnt = 0; cnt < rounds; ++cnt)
206: {
207:
208: __sha512_init_ctx (&ctx);
209:
210:
211: if ((cnt & 1) != 0)
212: __sha512_process_bytes (p_bytes, key_len, &ctx);
213: else
214: __sha512_process_bytes (alt_result, 64, &ctx);
215:
216:
217: if (cnt % 3 != 0)
218: __sha512_process_bytes (s_bytes, salt_len, &ctx);
219:
220:
221: if (cnt % 7 != 0)
222: __sha512_process_bytes (p_bytes, key_len, &ctx);
223:
224:
225: if ((cnt & 1) != 0)
226: __sha512_process_bytes (alt_result, 64, &ctx);
227: else
228: __sha512_process_bytes (p_bytes, key_len, &ctx);
229:
230:
231: __sha512_finish_ctx (&ctx, alt_result);
232: }
233:
234:
235:
236: cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen));
237: buflen -= sizeof (sha512_salt_prefix) - 1;
238:
239: if (rounds_custom)
240: {
241: int n = snprintf (cp, MAX (0, buflen), "%s%zu$",
242: sha512_rounds_prefix, rounds);
243: cp += n;
244: buflen -= n;
245: }
246:
247: cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
248: buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
249:
250: if (buflen > 0)
251: {
252: *cp++ = '$';
253: --buflen;
254: }
255:
256: #define b64_from_24bit(B2, B1, B0, N) \
257: do { \
258: unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
259: int n = (N); \
260: while (n-- > 0 && buflen > 0) \
261: { \
262: *cp++ = b64t[w & 0x3f]; \
263: --buflen; \
264: w >>= 6; \
265: } \
266: } while (0)
267:
268: b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4);
269: b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4);
270: b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4);
271: b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4);
272: b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4);
273: b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4);
274: b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4);
275: b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4);
276: b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4);
277: b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4);
278: b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4);
279: b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4);
280: b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4);
281: b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4);
282: b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4);
283: b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4);
284: b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4);
285: b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4);
286: b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4);
287: b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4);
288: b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4);
289: b64_from_24bit (0, 0, alt_result[63], 2);
290:
291: if (buflen <= 0)
292: {
293: __set_errno (ERANGE);
294: buffer = NULL;
295: }
296: else
297: *cp = '\0';
298:
299:
300:
301:
302:
303: __sha512_init_ctx (&ctx);
304: __sha512_finish_ctx (&ctx, alt_result);
305: memset (temp_result, '\0', sizeof (temp_result));
306: memset (p_bytes, '\0', key_len);
307: memset (s_bytes, '\0', salt_len);
308: memset (&ctx, '\0', sizeof (ctx));
309: memset (&alt_ctx, '\0', sizeof (alt_ctx));
310: if (copied_key != NULL)
311: memset (copied_key, '\0', key_len);
312: if (copied_salt != NULL)
313: memset (copied_salt, '\0', salt_len);
314:
315: return buffer;
316: }
317:
318: #ifndef _LIBC
319: # define libc_freeres_ptr(decl) decl
320: #endif
321: libc_freeres_ptr (static char *buffer);
322:
323:
324:
325: char *
326: __sha512_crypt (const char *key, const char *salt)
327: {
328:
329:
330:
331:
332: static int buflen;
333: int needed = (sizeof (sha512_salt_prefix) - 1
334: + sizeof (sha512_rounds_prefix) + 9 + 1
335: + strlen (salt) + 1 + 86 + 1);
336:
337: if (buflen < needed)
338: {
339: char *new_buffer = (char *) realloc (buffer, needed);
340: if (new_buffer == NULL)
341: return NULL;
342:
343: buffer = new_buffer;
344: buflen = needed;
345: }
346:
347: return __sha512_crypt_r (key, salt, buffer, buflen);
348: }
349:
350: #ifndef _LIBC
351: static void
352: __attribute__ ((__destructor__))
353: free_mem (void)
354: {
355: free (buffer);
356: }
357: #endif