16737f3b9SNolan Lum /*
2d8ee3b5dSSamuel J. Greear * SHA512-based Unix crypt implementation.
3d8ee3b5dSSamuel J. Greear * Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.
46737f3b9SNolan Lum */
5d8ee3b5dSSamuel J. Greear #include <errno.h>
6d8ee3b5dSSamuel J. Greear #include <limits.h>
7d8ee3b5dSSamuel J. Greear #include <stdbool.h>
8d8ee3b5dSSamuel J. Greear #include <stdint.h>
9d8ee3b5dSSamuel J. Greear #include <stdio.h>
10d8ee3b5dSSamuel J. Greear #include <stdlib.h>
116737f3b9SNolan Lum #include <string.h>
12d8ee3b5dSSamuel J. Greear #include <sys/endian.h>
13d8ee3b5dSSamuel J. Greear #include <sys/param.h>
14d8ee3b5dSSamuel J. Greear #include <sys/types.h>
156737f3b9SNolan Lum
16*e0369600Szrj #include "crypt.h"
170fe46dc6SMatthew Dillon #include "local.h"
186737f3b9SNolan Lum
194c7c7880SSascha Wildner #if _BYTE_ORDER == _LITTLE_ENDIAN
20d8ee3b5dSSamuel J. Greear # define SWAP(n) \
21d8ee3b5dSSamuel J. Greear (((n) << 56) \
22d8ee3b5dSSamuel J. Greear | (((n) & 0xff00) << 40) \
23d8ee3b5dSSamuel J. Greear | (((n) & 0xff0000) << 24) \
24d8ee3b5dSSamuel J. Greear | (((n) & 0xff000000) << 8) \
25d8ee3b5dSSamuel J. Greear | (((n) >> 8) & 0xff000000) \
26d8ee3b5dSSamuel J. Greear | (((n) >> 24) & 0xff0000) \
27d8ee3b5dSSamuel J. Greear | (((n) >> 40) & 0xff00) \
28d8ee3b5dSSamuel J. Greear | ((n) >> 56))
29d8ee3b5dSSamuel J. Greear #else
30d8ee3b5dSSamuel J. Greear # define SWAP(n) (n)
31d8ee3b5dSSamuel J. Greear #endif
326737f3b9SNolan Lum
336737f3b9SNolan Lum
34d8ee3b5dSSamuel J. Greear /* This array contains the bytes used to pad the buffer to the next
35d8ee3b5dSSamuel J. Greear 64-byte boundary. (FIPS 180-2:5.1.2) */
36d8ee3b5dSSamuel J. Greear static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
376737f3b9SNolan Lum
386737f3b9SNolan Lum
39d8ee3b5dSSamuel J. Greear /* Constants for SHA512 from FIPS 180-2:4.2.3. */
40d8ee3b5dSSamuel J. Greear static const uint64_t K[80] =
41d8ee3b5dSSamuel J. Greear {
42d8ee3b5dSSamuel J. Greear UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
43d8ee3b5dSSamuel J. Greear UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
44d8ee3b5dSSamuel J. Greear UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
45d8ee3b5dSSamuel J. Greear UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
46d8ee3b5dSSamuel J. Greear UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
47d8ee3b5dSSamuel J. Greear UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
48d8ee3b5dSSamuel J. Greear UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
49d8ee3b5dSSamuel J. Greear UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
50d8ee3b5dSSamuel J. Greear UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
51d8ee3b5dSSamuel J. Greear UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
52d8ee3b5dSSamuel J. Greear UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
53d8ee3b5dSSamuel J. Greear UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
54d8ee3b5dSSamuel J. Greear UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
55d8ee3b5dSSamuel J. Greear UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
56d8ee3b5dSSamuel J. Greear UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
57d8ee3b5dSSamuel J. Greear UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
58d8ee3b5dSSamuel J. Greear UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
59d8ee3b5dSSamuel J. Greear UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
60d8ee3b5dSSamuel J. Greear UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
61d8ee3b5dSSamuel J. Greear UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
62d8ee3b5dSSamuel J. Greear UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
63d8ee3b5dSSamuel J. Greear UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
64d8ee3b5dSSamuel J. Greear UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
65d8ee3b5dSSamuel J. Greear UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
66d8ee3b5dSSamuel J. Greear UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
67d8ee3b5dSSamuel J. Greear UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
68d8ee3b5dSSamuel J. Greear UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
69d8ee3b5dSSamuel J. Greear UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
70d8ee3b5dSSamuel J. Greear UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
71d8ee3b5dSSamuel J. Greear UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
72d8ee3b5dSSamuel J. Greear UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
73d8ee3b5dSSamuel J. Greear UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
74d8ee3b5dSSamuel J. Greear UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
75d8ee3b5dSSamuel J. Greear UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
76d8ee3b5dSSamuel J. Greear UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
77d8ee3b5dSSamuel J. Greear UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
78d8ee3b5dSSamuel J. Greear UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
79d8ee3b5dSSamuel J. Greear UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
80d8ee3b5dSSamuel J. Greear UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
81d8ee3b5dSSamuel J. Greear UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
82d8ee3b5dSSamuel J. Greear };
836737f3b9SNolan Lum
846737f3b9SNolan Lum
85d8ee3b5dSSamuel J. Greear /* Process LEN bytes of BUFFER, accumulating context into CTX.
86d8ee3b5dSSamuel J. Greear It is assumed that LEN % 128 == 0. */
870fe46dc6SMatthew Dillon void
__crypt__sha512_process_block(const void * buffer,size_t len,struct sha512_ctx * ctx)880fe46dc6SMatthew Dillon __crypt__sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
89d8ee3b5dSSamuel J. Greear {
90d8ee3b5dSSamuel J. Greear const uint64_t *words = buffer;
91d8ee3b5dSSamuel J. Greear size_t nwords = len / sizeof (uint64_t);
92d8ee3b5dSSamuel J. Greear uint64_t a = ctx->H[0];
93d8ee3b5dSSamuel J. Greear uint64_t b = ctx->H[1];
94d8ee3b5dSSamuel J. Greear uint64_t c = ctx->H[2];
95d8ee3b5dSSamuel J. Greear uint64_t d = ctx->H[3];
96d8ee3b5dSSamuel J. Greear uint64_t e = ctx->H[4];
97d8ee3b5dSSamuel J. Greear uint64_t f = ctx->H[5];
98d8ee3b5dSSamuel J. Greear uint64_t g = ctx->H[6];
99d8ee3b5dSSamuel J. Greear uint64_t h = ctx->H[7];
1006737f3b9SNolan Lum
101d8ee3b5dSSamuel J. Greear /* First increment the byte count. FIPS 180-2 specifies the possible
102d8ee3b5dSSamuel J. Greear length of the file up to 2^128 bits. Here we only compute the
103d8ee3b5dSSamuel J. Greear number of bytes. Do a double word increment. */
104d8ee3b5dSSamuel J. Greear ctx->total[0] += len;
105d8ee3b5dSSamuel J. Greear if (ctx->total[0] < len)
106d8ee3b5dSSamuel J. Greear ++ctx->total[1];
1076737f3b9SNolan Lum
108d8ee3b5dSSamuel J. Greear /* Process all bytes in the buffer with 128 bytes in each round of
109d8ee3b5dSSamuel J. Greear the loop. */
110d8ee3b5dSSamuel J. Greear while (nwords > 0)
111d8ee3b5dSSamuel J. Greear {
112d8ee3b5dSSamuel J. Greear uint64_t W[80];
113d8ee3b5dSSamuel J. Greear uint64_t a_save = a;
114d8ee3b5dSSamuel J. Greear uint64_t b_save = b;
115d8ee3b5dSSamuel J. Greear uint64_t c_save = c;
116d8ee3b5dSSamuel J. Greear uint64_t d_save = d;
117d8ee3b5dSSamuel J. Greear uint64_t e_save = e;
118d8ee3b5dSSamuel J. Greear uint64_t f_save = f;
119d8ee3b5dSSamuel J. Greear uint64_t g_save = g;
120d8ee3b5dSSamuel J. Greear uint64_t h_save = h;
121d8ee3b5dSSamuel J. Greear
122d8ee3b5dSSamuel J. Greear /* Operators defined in FIPS 180-2:4.1.2. */
123d8ee3b5dSSamuel J. Greear #define Ch(x, y, z) ((x & y) ^ (~x & z))
124d8ee3b5dSSamuel J. Greear #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
125d8ee3b5dSSamuel J. Greear #define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
126d8ee3b5dSSamuel J. Greear #define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
127d8ee3b5dSSamuel J. Greear #define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
128d8ee3b5dSSamuel J. Greear #define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
129d8ee3b5dSSamuel J. Greear
130d8ee3b5dSSamuel J. Greear /* It is unfortunate that C does not provide an operator for
131d8ee3b5dSSamuel J. Greear cyclic rotation. Hope the C compiler is smart enough. */
132d8ee3b5dSSamuel J. Greear #define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
133d8ee3b5dSSamuel J. Greear
134d8ee3b5dSSamuel J. Greear /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
135d8ee3b5dSSamuel J. Greear for (unsigned int t = 0; t < 16; ++t)
136d8ee3b5dSSamuel J. Greear {
137d8ee3b5dSSamuel J. Greear W[t] = SWAP (*words);
138d8ee3b5dSSamuel J. Greear ++words;
1396737f3b9SNolan Lum }
140d8ee3b5dSSamuel J. Greear for (unsigned int t = 16; t < 80; ++t)
141d8ee3b5dSSamuel J. Greear W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
1426737f3b9SNolan Lum
143d8ee3b5dSSamuel J. Greear /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
144d8ee3b5dSSamuel J. Greear for (unsigned int t = 0; t < 80; ++t)
145d8ee3b5dSSamuel J. Greear {
146d8ee3b5dSSamuel J. Greear uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
147d8ee3b5dSSamuel J. Greear uint64_t T2 = S0 (a) + Maj (a, b, c);
148d8ee3b5dSSamuel J. Greear h = g;
149d8ee3b5dSSamuel J. Greear g = f;
150d8ee3b5dSSamuel J. Greear f = e;
151d8ee3b5dSSamuel J. Greear e = d + T1;
152d8ee3b5dSSamuel J. Greear d = c;
153d8ee3b5dSSamuel J. Greear c = b;
154d8ee3b5dSSamuel J. Greear b = a;
155d8ee3b5dSSamuel J. Greear a = T1 + T2;
1566737f3b9SNolan Lum }
157d8ee3b5dSSamuel J. Greear
158d8ee3b5dSSamuel J. Greear /* Add the starting values of the context according to FIPS 180-2:6.3.2
159d8ee3b5dSSamuel J. Greear step 4. */
160d8ee3b5dSSamuel J. Greear a += a_save;
161d8ee3b5dSSamuel J. Greear b += b_save;
162d8ee3b5dSSamuel J. Greear c += c_save;
163d8ee3b5dSSamuel J. Greear d += d_save;
164d8ee3b5dSSamuel J. Greear e += e_save;
165d8ee3b5dSSamuel J. Greear f += f_save;
166d8ee3b5dSSamuel J. Greear g += g_save;
167d8ee3b5dSSamuel J. Greear h += h_save;
168d8ee3b5dSSamuel J. Greear
169d8ee3b5dSSamuel J. Greear /* Prepare for the next round. */
170d8ee3b5dSSamuel J. Greear nwords -= 16;
171d8ee3b5dSSamuel J. Greear }
172d8ee3b5dSSamuel J. Greear
173d8ee3b5dSSamuel J. Greear /* Put checksum in context given as argument. */
174d8ee3b5dSSamuel J. Greear ctx->H[0] = a;
175d8ee3b5dSSamuel J. Greear ctx->H[1] = b;
176d8ee3b5dSSamuel J. Greear ctx->H[2] = c;
177d8ee3b5dSSamuel J. Greear ctx->H[3] = d;
178d8ee3b5dSSamuel J. Greear ctx->H[4] = e;
179d8ee3b5dSSamuel J. Greear ctx->H[5] = f;
180d8ee3b5dSSamuel J. Greear ctx->H[6] = g;
181d8ee3b5dSSamuel J. Greear ctx->H[7] = h;
182d8ee3b5dSSamuel J. Greear }
183d8ee3b5dSSamuel J. Greear
184d8ee3b5dSSamuel J. Greear
185d8ee3b5dSSamuel J. Greear /* Initialize structure containing state of computation.
186d8ee3b5dSSamuel J. Greear (FIPS 180-2:5.3.3) */
1870fe46dc6SMatthew Dillon void
__crypt__sha512_init_ctx(struct sha512_ctx * ctx)1880fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (struct sha512_ctx *ctx)
189d8ee3b5dSSamuel J. Greear {
190d8ee3b5dSSamuel J. Greear ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
191d8ee3b5dSSamuel J. Greear ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
192d8ee3b5dSSamuel J. Greear ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
193d8ee3b5dSSamuel J. Greear ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
194d8ee3b5dSSamuel J. Greear ctx->H[4] = UINT64_C (0x510e527fade682d1);
195d8ee3b5dSSamuel J. Greear ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
196d8ee3b5dSSamuel J. Greear ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
197d8ee3b5dSSamuel J. Greear ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
198d8ee3b5dSSamuel J. Greear
199d8ee3b5dSSamuel J. Greear ctx->total[0] = ctx->total[1] = 0;
200d8ee3b5dSSamuel J. Greear ctx->buflen = 0;
201d8ee3b5dSSamuel J. Greear }
202d8ee3b5dSSamuel J. Greear
203d8ee3b5dSSamuel J. Greear
204d8ee3b5dSSamuel J. Greear /* Process the remaining bytes in the internal buffer and the usual
205d8ee3b5dSSamuel J. Greear prolog according to the standard and write the result to RESBUF.
206d8ee3b5dSSamuel J. Greear
207d8ee3b5dSSamuel J. Greear IMPORTANT: On some systems it is required that RESBUF is correctly
208d8ee3b5dSSamuel J. Greear aligned for a 32 bits value. */
2090fe46dc6SMatthew Dillon void *
__crypt__sha512_finish_ctx(struct sha512_ctx * ctx,void * resbuf)2100fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
211d8ee3b5dSSamuel J. Greear {
212d8ee3b5dSSamuel J. Greear /* Take yet unprocessed bytes into account. */
213d8ee3b5dSSamuel J. Greear uint64_t bytes = ctx->buflen;
214d8ee3b5dSSamuel J. Greear size_t pad;
215d8ee3b5dSSamuel J. Greear
216d8ee3b5dSSamuel J. Greear /* Now count remaining bytes. */
217d8ee3b5dSSamuel J. Greear ctx->total[0] += bytes;
218d8ee3b5dSSamuel J. Greear if (ctx->total[0] < bytes)
219d8ee3b5dSSamuel J. Greear ++ctx->total[1];
220d8ee3b5dSSamuel J. Greear
221d8ee3b5dSSamuel J. Greear pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes;
222d8ee3b5dSSamuel J. Greear memcpy (&ctx->buffer[bytes], fillbuf, pad);
223d8ee3b5dSSamuel J. Greear
224d8ee3b5dSSamuel J. Greear /* Put the 128-bit file length in *bits* at the end of the buffer. */
225d8ee3b5dSSamuel J. Greear *(uint64_t *) &ctx->buffer[bytes + pad + 8] = SWAP (ctx->total[0] << 3);
226d8ee3b5dSSamuel J. Greear *(uint64_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
227d8ee3b5dSSamuel J. Greear (ctx->total[0] >> 61));
228d8ee3b5dSSamuel J. Greear
229d8ee3b5dSSamuel J. Greear /* Process last bytes. */
2300fe46dc6SMatthew Dillon __crypt__sha512_process_block (ctx->buffer, bytes + pad + 16, ctx);
231d8ee3b5dSSamuel J. Greear
232d8ee3b5dSSamuel J. Greear /* Put result from CTX in first 64 bytes following RESBUF. */
233d8ee3b5dSSamuel J. Greear for (unsigned int i = 0; i < 8; ++i)
234d8ee3b5dSSamuel J. Greear ((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]);
235d8ee3b5dSSamuel J. Greear
236d8ee3b5dSSamuel J. Greear return resbuf;
237d8ee3b5dSSamuel J. Greear }
238d8ee3b5dSSamuel J. Greear
239d8ee3b5dSSamuel J. Greear
2400fe46dc6SMatthew Dillon void
__crypt__sha512_process_bytes(const void * buffer,size_t len,struct sha512_ctx * ctx)2410fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
242d8ee3b5dSSamuel J. Greear {
243d8ee3b5dSSamuel J. Greear /* When we already have some bits in our internal buffer concatenate
244d8ee3b5dSSamuel J. Greear both inputs first. */
245d8ee3b5dSSamuel J. Greear if (ctx->buflen != 0)
246d8ee3b5dSSamuel J. Greear {
247d8ee3b5dSSamuel J. Greear size_t left_over = ctx->buflen;
248d8ee3b5dSSamuel J. Greear size_t add = 256 - left_over > len ? len : 256 - left_over;
249d8ee3b5dSSamuel J. Greear
250d8ee3b5dSSamuel J. Greear memcpy (&ctx->buffer[left_over], buffer, add);
251d8ee3b5dSSamuel J. Greear ctx->buflen += add;
252d8ee3b5dSSamuel J. Greear
253d8ee3b5dSSamuel J. Greear if (ctx->buflen > 128)
254d8ee3b5dSSamuel J. Greear {
2550fe46dc6SMatthew Dillon __crypt__sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
256d8ee3b5dSSamuel J. Greear
257d8ee3b5dSSamuel J. Greear ctx->buflen &= 127;
258d8ee3b5dSSamuel J. Greear /* The regions in the following copy operation cannot overlap. */
259d8ee3b5dSSamuel J. Greear memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
260d8ee3b5dSSamuel J. Greear ctx->buflen);
261d8ee3b5dSSamuel J. Greear }
262d8ee3b5dSSamuel J. Greear
263d8ee3b5dSSamuel J. Greear buffer = (const char *) buffer + add;
264d8ee3b5dSSamuel J. Greear len -= add;
265d8ee3b5dSSamuel J. Greear }
266d8ee3b5dSSamuel J. Greear
267d8ee3b5dSSamuel J. Greear /* Process available complete blocks. */
268d8ee3b5dSSamuel J. Greear if (len >= 128)
269d8ee3b5dSSamuel J. Greear {
270d8ee3b5dSSamuel J. Greear #if __GNUC__ >= 2
271d8ee3b5dSSamuel J. Greear # define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint64_t) != 0)
272d8ee3b5dSSamuel J. Greear #else
273d8ee3b5dSSamuel J. Greear # define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint64_t) != 0)
274d8ee3b5dSSamuel J. Greear #endif
275d8ee3b5dSSamuel J. Greear if (UNALIGNED_P (buffer))
276d8ee3b5dSSamuel J. Greear while (len > 128)
277d8ee3b5dSSamuel J. Greear {
2780fe46dc6SMatthew Dillon __crypt__sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128,
279d8ee3b5dSSamuel J. Greear ctx);
280d8ee3b5dSSamuel J. Greear buffer = (const char *) buffer + 128;
281d8ee3b5dSSamuel J. Greear len -= 128;
282d8ee3b5dSSamuel J. Greear }
283d8ee3b5dSSamuel J. Greear else
284d8ee3b5dSSamuel J. Greear {
2850fe46dc6SMatthew Dillon __crypt__sha512_process_block (buffer, len & ~127, ctx);
286d8ee3b5dSSamuel J. Greear buffer = (const char *) buffer + (len & ~127);
287d8ee3b5dSSamuel J. Greear len &= 127;
288d8ee3b5dSSamuel J. Greear }
289d8ee3b5dSSamuel J. Greear }
290d8ee3b5dSSamuel J. Greear
291d8ee3b5dSSamuel J. Greear /* Move remaining bytes into internal buffer. */
292d8ee3b5dSSamuel J. Greear if (len > 0)
293d8ee3b5dSSamuel J. Greear {
294d8ee3b5dSSamuel J. Greear size_t left_over = ctx->buflen;
295d8ee3b5dSSamuel J. Greear
296d8ee3b5dSSamuel J. Greear memcpy (&ctx->buffer[left_over], buffer, len);
297d8ee3b5dSSamuel J. Greear left_over += len;
298d8ee3b5dSSamuel J. Greear if (left_over >= 128)
299d8ee3b5dSSamuel J. Greear {
3000fe46dc6SMatthew Dillon __crypt__sha512_process_block (ctx->buffer, 128, ctx);
301d8ee3b5dSSamuel J. Greear left_over -= 128;
302d8ee3b5dSSamuel J. Greear memcpy (ctx->buffer, &ctx->buffer[128], left_over);
303d8ee3b5dSSamuel J. Greear }
304d8ee3b5dSSamuel J. Greear ctx->buflen = left_over;
305d8ee3b5dSSamuel J. Greear }
306d8ee3b5dSSamuel J. Greear }
307d8ee3b5dSSamuel J. Greear
308d8ee3b5dSSamuel J. Greear
309d8ee3b5dSSamuel J. Greear /* Define our magic string to mark salt for SHA512 "encryption"
310d8ee3b5dSSamuel J. Greear replacement. */
311d8ee3b5dSSamuel J. Greear static const char sha512_salt_prefix[] = "$6$";
312d8ee3b5dSSamuel J. Greear
313d8ee3b5dSSamuel J. Greear /* Prefix for optional rounds specification. */
314d8ee3b5dSSamuel J. Greear static const char sha512_rounds_prefix[] = "rounds=";
315d8ee3b5dSSamuel J. Greear
316d8ee3b5dSSamuel J. Greear /* Maximum salt string length. */
317d8ee3b5dSSamuel J. Greear #define SALT_LEN_MAX 16
318d8ee3b5dSSamuel J. Greear /* Default number of rounds if not explicitly specified. */
319d8ee3b5dSSamuel J. Greear #define ROUNDS_DEFAULT 5000
320d8ee3b5dSSamuel J. Greear /* Minimum number of rounds. */
321d8ee3b5dSSamuel J. Greear #define ROUNDS_MIN 1000
322d8ee3b5dSSamuel J. Greear /* Maximum number of rounds. */
323d8ee3b5dSSamuel J. Greear #define ROUNDS_MAX 999999999
324d8ee3b5dSSamuel J. Greear
325d8ee3b5dSSamuel J. Greear /* Table with characters for base64 transformation. */
326d8ee3b5dSSamuel J. Greear static const char b64t[64] =
327d8ee3b5dSSamuel J. Greear "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
328d8ee3b5dSSamuel J. Greear
329d8ee3b5dSSamuel J. Greear
330d8ee3b5dSSamuel J. Greear static char *
crypt_sha512_r(const char * key,const char * salt,char * buffer,int buflen)331d8ee3b5dSSamuel J. Greear crypt_sha512_r (const char *key, const char *salt, char *buffer, int buflen)
332d8ee3b5dSSamuel J. Greear {
333d8ee3b5dSSamuel J. Greear unsigned char alt_result[64]
334d8ee3b5dSSamuel J. Greear __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
335d8ee3b5dSSamuel J. Greear unsigned char temp_result[64]
336d8ee3b5dSSamuel J. Greear __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
337d8ee3b5dSSamuel J. Greear struct sha512_ctx ctx;
338d8ee3b5dSSamuel J. Greear struct sha512_ctx alt_ctx;
339d8ee3b5dSSamuel J. Greear size_t salt_len;
340d8ee3b5dSSamuel J. Greear size_t key_len;
341d8ee3b5dSSamuel J. Greear size_t cnt;
342d8ee3b5dSSamuel J. Greear char *cp;
343d8ee3b5dSSamuel J. Greear char *copied_key = NULL;
344d8ee3b5dSSamuel J. Greear char *copied_salt = NULL;
345d8ee3b5dSSamuel J. Greear char *p_bytes;
346d8ee3b5dSSamuel J. Greear char *s_bytes;
347d8ee3b5dSSamuel J. Greear /* Default number of rounds. */
348d8ee3b5dSSamuel J. Greear size_t rounds = ROUNDS_DEFAULT;
349d8ee3b5dSSamuel J. Greear bool rounds_custom = false;
350d8ee3b5dSSamuel J. Greear
351d8ee3b5dSSamuel J. Greear /* Find beginning of salt string. The prefix should normally always
352d8ee3b5dSSamuel J. Greear be present. Just in case it is not. */
353d8ee3b5dSSamuel J. Greear if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
354d8ee3b5dSSamuel J. Greear /* Skip salt prefix. */
355d8ee3b5dSSamuel J. Greear salt += sizeof (sha512_salt_prefix) - 1;
356d8ee3b5dSSamuel J. Greear
357d8ee3b5dSSamuel J. Greear if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
358d8ee3b5dSSamuel J. Greear == 0)
359d8ee3b5dSSamuel J. Greear {
360d8ee3b5dSSamuel J. Greear const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
361d8ee3b5dSSamuel J. Greear char *endp;
362d8ee3b5dSSamuel J. Greear unsigned long int srounds = strtoul (num, &endp, 10);
363d8ee3b5dSSamuel J. Greear if (*endp == '$')
364d8ee3b5dSSamuel J. Greear {
365d8ee3b5dSSamuel J. Greear salt = endp + 1;
366d8ee3b5dSSamuel J. Greear rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
367d8ee3b5dSSamuel J. Greear rounds_custom = true;
368d8ee3b5dSSamuel J. Greear }
369d8ee3b5dSSamuel J. Greear }
370d8ee3b5dSSamuel J. Greear
371d8ee3b5dSSamuel J. Greear salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
372d8ee3b5dSSamuel J. Greear key_len = strlen (key);
373d8ee3b5dSSamuel J. Greear
374d8ee3b5dSSamuel J. Greear if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
375d8ee3b5dSSamuel J. Greear {
376d8ee3b5dSSamuel J. Greear char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
377d8ee3b5dSSamuel J. Greear key = copied_key =
378d8ee3b5dSSamuel J. Greear memcpy (tmp + __alignof__ (uint64_t)
379d8ee3b5dSSamuel J. Greear - (tmp - (char *) 0) % __alignof__ (uint64_t),
380d8ee3b5dSSamuel J. Greear key, key_len);
381d8ee3b5dSSamuel J. Greear }
382d8ee3b5dSSamuel J. Greear
383d8ee3b5dSSamuel J. Greear if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0)
384d8ee3b5dSSamuel J. Greear {
385d8ee3b5dSSamuel J. Greear char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
386d8ee3b5dSSamuel J. Greear salt = copied_salt =
387d8ee3b5dSSamuel J. Greear memcpy (tmp + __alignof__ (uint64_t)
388d8ee3b5dSSamuel J. Greear - (tmp - (char *) 0) % __alignof__ (uint64_t),
389d8ee3b5dSSamuel J. Greear salt, salt_len);
390d8ee3b5dSSamuel J. Greear }
391d8ee3b5dSSamuel J. Greear
392d8ee3b5dSSamuel J. Greear /* Prepare for the real work. */
3930fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&ctx);
394d8ee3b5dSSamuel J. Greear
395d8ee3b5dSSamuel J. Greear /* Add the key string. */
3960fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (key, key_len, &ctx);
397d8ee3b5dSSamuel J. Greear
398d8ee3b5dSSamuel J. Greear /* The last part is the salt string. This must be at most 16
399d8ee3b5dSSamuel J. Greear characters and it ends at the first `$' character (for
400d8ee3b5dSSamuel J. Greear compatibility with existing implementations). */
4010fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (salt, salt_len, &ctx);
402d8ee3b5dSSamuel J. Greear
403d8ee3b5dSSamuel J. Greear
404d8ee3b5dSSamuel J. Greear /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The
405d8ee3b5dSSamuel J. Greear final result will be added to the first context. */
4060fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&alt_ctx);
407d8ee3b5dSSamuel J. Greear
408d8ee3b5dSSamuel J. Greear /* Add key. */
4090fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (key, key_len, &alt_ctx);
410d8ee3b5dSSamuel J. Greear
411d8ee3b5dSSamuel J. Greear /* Add salt. */
4120fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (salt, salt_len, &alt_ctx);
413d8ee3b5dSSamuel J. Greear
414d8ee3b5dSSamuel J. Greear /* Add key again. */
4150fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (key, key_len, &alt_ctx);
416d8ee3b5dSSamuel J. Greear
417d8ee3b5dSSamuel J. Greear /* Now get result of this (64 bytes) and add it to the other
418d8ee3b5dSSamuel J. Greear context. */
4190fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&alt_ctx, alt_result);
420d8ee3b5dSSamuel J. Greear
421d8ee3b5dSSamuel J. Greear /* Add for any character in the key one byte of the alternate sum. */
422d8ee3b5dSSamuel J. Greear for (cnt = key_len; cnt > 64; cnt -= 64)
4230fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (alt_result, 64, &ctx);
4240fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (alt_result, cnt, &ctx);
425d8ee3b5dSSamuel J. Greear
426d8ee3b5dSSamuel J. Greear /* Take the binary representation of the length of the key and for every
427d8ee3b5dSSamuel J. Greear 1 add the alternate sum, for every 0 the key. */
428d8ee3b5dSSamuel J. Greear for (cnt = key_len; cnt > 0; cnt >>= 1)
429d8ee3b5dSSamuel J. Greear if ((cnt & 1) != 0)
4300fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (alt_result, 64, &ctx);
431d8ee3b5dSSamuel J. Greear else
4320fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (key, key_len, &ctx);
433d8ee3b5dSSamuel J. Greear
434d8ee3b5dSSamuel J. Greear /* Create intermediate result. */
4350fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&ctx, alt_result);
436d8ee3b5dSSamuel J. Greear
437d8ee3b5dSSamuel J. Greear /* Start computation of P byte sequence. */
4380fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&alt_ctx);
439d8ee3b5dSSamuel J. Greear
440d8ee3b5dSSamuel J. Greear /* For every character in the password add the entire password. */
441d8ee3b5dSSamuel J. Greear for (cnt = 0; cnt < key_len; ++cnt)
4420fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (key, key_len, &alt_ctx);
443d8ee3b5dSSamuel J. Greear
444d8ee3b5dSSamuel J. Greear /* Finish the digest. */
4450fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&alt_ctx, temp_result);
446d8ee3b5dSSamuel J. Greear
447d8ee3b5dSSamuel J. Greear /* Create byte sequence P. */
448d8ee3b5dSSamuel J. Greear cp = p_bytes = alloca (key_len);
449d8ee3b5dSSamuel J. Greear for (cnt = key_len; cnt >= 64; cnt -= 64)
450d8ee3b5dSSamuel J. Greear cp = mempcpy (cp, temp_result, 64);
451d8ee3b5dSSamuel J. Greear memcpy (cp, temp_result, cnt);
452d8ee3b5dSSamuel J. Greear
453d8ee3b5dSSamuel J. Greear /* Start computation of S byte sequence. */
4540fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&alt_ctx);
455d8ee3b5dSSamuel J. Greear
456d8ee3b5dSSamuel J. Greear /* For every character in the password add the entire password. */
457d8ee3b5dSSamuel J. Greear for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
4580fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (salt, salt_len, &alt_ctx);
459d8ee3b5dSSamuel J. Greear
460d8ee3b5dSSamuel J. Greear /* Finish the digest. */
4610fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&alt_ctx, temp_result);
462d8ee3b5dSSamuel J. Greear
463d8ee3b5dSSamuel J. Greear /* Create byte sequence S. */
464d8ee3b5dSSamuel J. Greear cp = s_bytes = alloca (salt_len);
465d8ee3b5dSSamuel J. Greear for (cnt = salt_len; cnt >= 64; cnt -= 64)
466d8ee3b5dSSamuel J. Greear cp = mempcpy (cp, temp_result, 64);
467d8ee3b5dSSamuel J. Greear memcpy (cp, temp_result, cnt);
468d8ee3b5dSSamuel J. Greear
469d8ee3b5dSSamuel J. Greear /* Repeatedly run the collected hash value through SHA512 to burn
470d8ee3b5dSSamuel J. Greear CPU cycles. */
471d8ee3b5dSSamuel J. Greear for (cnt = 0; cnt < rounds; ++cnt)
472d8ee3b5dSSamuel J. Greear {
473d8ee3b5dSSamuel J. Greear /* New context. */
4740fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&ctx);
475d8ee3b5dSSamuel J. Greear
476d8ee3b5dSSamuel J. Greear /* Add key or last result. */
477d8ee3b5dSSamuel J. Greear if ((cnt & 1) != 0)
4780fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (p_bytes, key_len, &ctx);
479d8ee3b5dSSamuel J. Greear else
4800fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (alt_result, 64, &ctx);
481d8ee3b5dSSamuel J. Greear
482d8ee3b5dSSamuel J. Greear /* Add salt for numbers not divisible by 3. */
483d8ee3b5dSSamuel J. Greear if (cnt % 3 != 0)
4840fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (s_bytes, salt_len, &ctx);
485d8ee3b5dSSamuel J. Greear
486d8ee3b5dSSamuel J. Greear /* Add key for numbers not divisible by 7. */
487d8ee3b5dSSamuel J. Greear if (cnt % 7 != 0)
4880fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (p_bytes, key_len, &ctx);
489d8ee3b5dSSamuel J. Greear
490d8ee3b5dSSamuel J. Greear /* Add key or last result. */
491d8ee3b5dSSamuel J. Greear if ((cnt & 1) != 0)
4920fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (alt_result, 64, &ctx);
493d8ee3b5dSSamuel J. Greear else
4940fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (p_bytes, key_len, &ctx);
495d8ee3b5dSSamuel J. Greear
496d8ee3b5dSSamuel J. Greear /* Create intermediate result. */
4970fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&ctx, alt_result);
498d8ee3b5dSSamuel J. Greear }
499d8ee3b5dSSamuel J. Greear
500d8ee3b5dSSamuel J. Greear /* Now we can construct the result string. It consists of three
501d8ee3b5dSSamuel J. Greear parts. */
502d8ee3b5dSSamuel J. Greear cp = stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen));
503d8ee3b5dSSamuel J. Greear buflen -= sizeof (sha512_salt_prefix) - 1;
504d8ee3b5dSSamuel J. Greear
505d8ee3b5dSSamuel J. Greear if (rounds_custom)
506d8ee3b5dSSamuel J. Greear {
507d8ee3b5dSSamuel J. Greear int n = snprintf (cp, MAX (0, buflen), "%s%zu$",
508d8ee3b5dSSamuel J. Greear sha512_rounds_prefix, rounds);
509d8ee3b5dSSamuel J. Greear cp += n;
510d8ee3b5dSSamuel J. Greear buflen -= n;
511d8ee3b5dSSamuel J. Greear }
512d8ee3b5dSSamuel J. Greear
513d8ee3b5dSSamuel J. Greear cp = stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
514d8ee3b5dSSamuel J. Greear buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
515d8ee3b5dSSamuel J. Greear
516d8ee3b5dSSamuel J. Greear if (buflen > 0)
517d8ee3b5dSSamuel J. Greear {
518d8ee3b5dSSamuel J. Greear *cp++ = '$';
519d8ee3b5dSSamuel J. Greear --buflen;
520d8ee3b5dSSamuel J. Greear }
521d8ee3b5dSSamuel J. Greear
522d8ee3b5dSSamuel J. Greear #define b64_from_24bit(B2, B1, B0, N) \
523d8ee3b5dSSamuel J. Greear do { \
524d8ee3b5dSSamuel J. Greear unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
525d8ee3b5dSSamuel J. Greear int n = (N); \
526d8ee3b5dSSamuel J. Greear while (n-- > 0 && buflen > 0) \
527d8ee3b5dSSamuel J. Greear { \
528d8ee3b5dSSamuel J. Greear *cp++ = b64t[w & 0x3f]; \
529d8ee3b5dSSamuel J. Greear --buflen; \
530d8ee3b5dSSamuel J. Greear w >>= 6; \
531d8ee3b5dSSamuel J. Greear } \
532d8ee3b5dSSamuel J. Greear } while (0)
533d8ee3b5dSSamuel J. Greear
534d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4);
535d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4);
536d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4);
537d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4);
538d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4);
539d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4);
540d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4);
541d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4);
542d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4);
543d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4);
544d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4);
545d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4);
546d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4);
547d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4);
548d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4);
549d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4);
550d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4);
551d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4);
552d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4);
553d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4);
554d8ee3b5dSSamuel J. Greear b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4);
555d8ee3b5dSSamuel J. Greear b64_from_24bit (0, 0, alt_result[63], 2);
556d8ee3b5dSSamuel J. Greear
557d8ee3b5dSSamuel J. Greear if (buflen <= 0)
558d8ee3b5dSSamuel J. Greear {
559d8ee3b5dSSamuel J. Greear errno = ERANGE;
560d8ee3b5dSSamuel J. Greear buffer = NULL;
561d8ee3b5dSSamuel J. Greear }
562d8ee3b5dSSamuel J. Greear else
563d8ee3b5dSSamuel J. Greear *cp = '\0'; /* Terminate the string. */
564d8ee3b5dSSamuel J. Greear
565d8ee3b5dSSamuel J. Greear /* Clear the buffer for the intermediate result so that people
566d8ee3b5dSSamuel J. Greear attaching to processes or reading core dumps cannot get any
567d8ee3b5dSSamuel J. Greear information. We do it in this way to clear correct_words[]
568d8ee3b5dSSamuel J. Greear inside the SHA512 implementation as well. */
5690fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&ctx);
5700fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&ctx, alt_result);
571d8ee3b5dSSamuel J. Greear memset (temp_result, '\0', sizeof (temp_result));
572d8ee3b5dSSamuel J. Greear memset (p_bytes, '\0', key_len);
573d8ee3b5dSSamuel J. Greear memset (s_bytes, '\0', salt_len);
574d8ee3b5dSSamuel J. Greear memset (&ctx, '\0', sizeof (ctx));
575d8ee3b5dSSamuel J. Greear memset (&alt_ctx, '\0', sizeof (alt_ctx));
576d8ee3b5dSSamuel J. Greear if (copied_key != NULL)
577d8ee3b5dSSamuel J. Greear memset (copied_key, '\0', key_len);
578d8ee3b5dSSamuel J. Greear if (copied_salt != NULL)
579d8ee3b5dSSamuel J. Greear memset (copied_salt, '\0', salt_len);
580d8ee3b5dSSamuel J. Greear
581d8ee3b5dSSamuel J. Greear return buffer;
582d8ee3b5dSSamuel J. Greear }
583d8ee3b5dSSamuel J. Greear
584d8ee3b5dSSamuel J. Greear
585d8ee3b5dSSamuel J. Greear /* This entry point is equivalent to the `crypt' function in Unix
586d8ee3b5dSSamuel J. Greear libcs. */
587d8ee3b5dSSamuel J. Greear char *
crypt_sha512(const char * key,const char * salt)588d8ee3b5dSSamuel J. Greear crypt_sha512 (const char *key, const char *salt)
589d8ee3b5dSSamuel J. Greear {
590d8ee3b5dSSamuel J. Greear /* We don't want to have an arbitrary limit in the size of the
591d8ee3b5dSSamuel J. Greear password. We can compute an upper bound for the size of the
592d8ee3b5dSSamuel J. Greear result in advance and so we can prepare the buffer we pass to
593d8ee3b5dSSamuel J. Greear `crypt_sha512_r'. */
594d8ee3b5dSSamuel J. Greear static char *buffer;
595d8ee3b5dSSamuel J. Greear static int buflen;
596d8ee3b5dSSamuel J. Greear int needed = (sizeof (sha512_salt_prefix) - 1
597d8ee3b5dSSamuel J. Greear + sizeof (sha512_rounds_prefix) + 9 + 1
598d8ee3b5dSSamuel J. Greear + strlen (salt) + 1 + 86 + 1);
599d8ee3b5dSSamuel J. Greear
600d8ee3b5dSSamuel J. Greear if (buflen < needed)
601d8ee3b5dSSamuel J. Greear {
602d8ee3b5dSSamuel J. Greear char *new_buffer = (char *) realloc (buffer, needed);
603d8ee3b5dSSamuel J. Greear if (new_buffer == NULL)
604d8ee3b5dSSamuel J. Greear return NULL;
605d8ee3b5dSSamuel J. Greear
606d8ee3b5dSSamuel J. Greear buffer = new_buffer;
607d8ee3b5dSSamuel J. Greear buflen = needed;
608d8ee3b5dSSamuel J. Greear }
609d8ee3b5dSSamuel J. Greear
610d8ee3b5dSSamuel J. Greear return crypt_sha512_r (key, salt, buffer, buflen);
611d8ee3b5dSSamuel J. Greear }
612d8ee3b5dSSamuel J. Greear
613d8ee3b5dSSamuel J. Greear
614d8ee3b5dSSamuel J. Greear #ifdef TEST
615d8ee3b5dSSamuel J. Greear static const struct
616d8ee3b5dSSamuel J. Greear {
617d8ee3b5dSSamuel J. Greear const char *input;
618d8ee3b5dSSamuel J. Greear const char result[64];
619d8ee3b5dSSamuel J. Greear } tests[] =
620d8ee3b5dSSamuel J. Greear {
621d8ee3b5dSSamuel J. Greear /* Test vectors from FIPS 180-2: appendix C.1. */
622d8ee3b5dSSamuel J. Greear { "abc",
623d8ee3b5dSSamuel J. Greear "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31"
624d8ee3b5dSSamuel J. Greear "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
625d8ee3b5dSSamuel J. Greear "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
626d8ee3b5dSSamuel J. Greear "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" },
627d8ee3b5dSSamuel J. Greear /* Test vectors from FIPS 180-2: appendix C.2. */
628d8ee3b5dSSamuel J. Greear { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
629d8ee3b5dSSamuel J. Greear "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
630d8ee3b5dSSamuel J. Greear "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
631d8ee3b5dSSamuel J. Greear "\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18"
632d8ee3b5dSSamuel J. Greear "\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
633d8ee3b5dSSamuel J. Greear "\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09" },
634d8ee3b5dSSamuel J. Greear /* Test vectors from the NESSIE project. */
635d8ee3b5dSSamuel J. Greear { "",
636d8ee3b5dSSamuel J. Greear "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07"
637d8ee3b5dSSamuel J. Greear "\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
638d8ee3b5dSSamuel J. Greear "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f"
639d8ee3b5dSSamuel J. Greear "\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" },
640d8ee3b5dSSamuel J. Greear { "a",
641d8ee3b5dSSamuel J. Greear "\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2"
642d8ee3b5dSSamuel J. Greear "\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53"
643d8ee3b5dSSamuel J. Greear "\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46"
644d8ee3b5dSSamuel J. Greear "\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75" },
645d8ee3b5dSSamuel J. Greear { "message digest",
646d8ee3b5dSSamuel J. Greear "\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51"
647d8ee3b5dSSamuel J. Greear "\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33"
648d8ee3b5dSSamuel J. Greear "\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20"
649d8ee3b5dSSamuel J. Greear "\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c" },
650d8ee3b5dSSamuel J. Greear { "abcdefghijklmnopqrstuvwxyz",
651d8ee3b5dSSamuel J. Greear "\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81"
652d8ee3b5dSSamuel J. Greear "\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29"
653d8ee3b5dSSamuel J. Greear "\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59"
654d8ee3b5dSSamuel J. Greear "\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1" },
655d8ee3b5dSSamuel J. Greear { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
656d8ee3b5dSSamuel J. Greear "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
657d8ee3b5dSSamuel J. Greear "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
658d8ee3b5dSSamuel J. Greear "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
659d8ee3b5dSSamuel J. Greear "\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" },
660d8ee3b5dSSamuel J. Greear { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
661d8ee3b5dSSamuel J. Greear "\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93"
662d8ee3b5dSSamuel J. Greear "\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4"
663d8ee3b5dSSamuel J. Greear "\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab"
664d8ee3b5dSSamuel J. Greear "\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94" },
665d8ee3b5dSSamuel J. Greear { "123456789012345678901234567890123456789012345678901234567890"
666d8ee3b5dSSamuel J. Greear "12345678901234567890",
667d8ee3b5dSSamuel J. Greear "\x72\xec\x1e\xf1\x12\x4a\x45\xb0\x47\xe8\xb7\xc7\x5a\x93\x21\x95"
668d8ee3b5dSSamuel J. Greear "\x13\x5b\xb6\x1d\xe2\x4e\xc0\xd1\x91\x40\x42\x24\x6e\x0a\xec\x3a"
669d8ee3b5dSSamuel J. Greear "\x23\x54\xe0\x93\xd7\x6f\x30\x48\xb4\x56\x76\x43\x46\x90\x0c\xb1"
670d8ee3b5dSSamuel J. Greear "\x30\xd2\xa4\xfd\x5d\xd1\x6a\xbb\x5e\x30\xbc\xb8\x50\xde\xe8\x43" }
671d8ee3b5dSSamuel J. Greear };
672e62ef63cSSascha Wildner #define ntests (NELEM(tests))
673d8ee3b5dSSamuel J. Greear
674d8ee3b5dSSamuel J. Greear
675d8ee3b5dSSamuel J. Greear static const struct
676d8ee3b5dSSamuel J. Greear {
677d8ee3b5dSSamuel J. Greear const char *salt;
678d8ee3b5dSSamuel J. Greear const char *input;
679d8ee3b5dSSamuel J. Greear const char *expected;
680d8ee3b5dSSamuel J. Greear } tests2[] =
681d8ee3b5dSSamuel J. Greear {
682d8ee3b5dSSamuel J. Greear { "$6$saltstring", "Hello world!",
683d8ee3b5dSSamuel J. Greear "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu"
684d8ee3b5dSSamuel J. Greear "esI68u4OTLiBFdcbYEdFCoEOfaS35inz1" },
685d8ee3b5dSSamuel J. Greear { "$6$rounds=10000$saltstringsaltstring", "Hello world!",
686d8ee3b5dSSamuel J. Greear "$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb"
687d8ee3b5dSSamuel J. Greear "HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." },
688d8ee3b5dSSamuel J. Greear { "$6$rounds=5000$toolongsaltstring", "This is just a test",
689d8ee3b5dSSamuel J. Greear "$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ"
690d8ee3b5dSSamuel J. Greear "zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" },
691d8ee3b5dSSamuel J. Greear { "$6$rounds=1400$anotherlongsaltstring",
692d8ee3b5dSSamuel J. Greear "a very much longer text to encrypt. This one even stretches over more"
693d8ee3b5dSSamuel J. Greear "than one line.",
694d8ee3b5dSSamuel J. Greear "$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP"
695d8ee3b5dSSamuel J. Greear "vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" },
696d8ee3b5dSSamuel J. Greear { "$6$rounds=77777$short",
697d8ee3b5dSSamuel J. Greear "we have a short salt string but not a short password",
698d8ee3b5dSSamuel J. Greear "$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g"
699d8ee3b5dSSamuel J. Greear "ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0" },
700d8ee3b5dSSamuel J. Greear { "$6$rounds=123456$asaltof16chars..", "a short string",
701d8ee3b5dSSamuel J. Greear "$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc"
702d8ee3b5dSSamuel J. Greear "elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" },
703d8ee3b5dSSamuel J. Greear { "$6$rounds=10$roundstoolow", "the minimum number is still observed",
704d8ee3b5dSSamuel J. Greear "$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x"
705d8ee3b5dSSamuel J. Greear "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." },
706d8ee3b5dSSamuel J. Greear };
707e62ef63cSSascha Wildner #define ntests2 (NELEM(tests2))
708d8ee3b5dSSamuel J. Greear
709d8ee3b5dSSamuel J. Greear
710d8ee3b5dSSamuel J. Greear int
main(void)711d8ee3b5dSSamuel J. Greear main (void)
712d8ee3b5dSSamuel J. Greear {
713d8ee3b5dSSamuel J. Greear struct sha512_ctx ctx;
714d8ee3b5dSSamuel J. Greear char sum[64];
715d8ee3b5dSSamuel J. Greear int result = 0;
716d8ee3b5dSSamuel J. Greear int cnt;
717d8ee3b5dSSamuel J. Greear
718d8ee3b5dSSamuel J. Greear for (cnt = 0; cnt < (int) ntests; ++cnt)
719d8ee3b5dSSamuel J. Greear {
7200fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&ctx);
7210fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx);
7220fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&ctx, sum);
723d8ee3b5dSSamuel J. Greear if (memcmp (tests[cnt].result, sum, 64) != 0)
724d8ee3b5dSSamuel J. Greear {
725d8ee3b5dSSamuel J. Greear printf ("test %d run %d failed\n", cnt, 1);
726d8ee3b5dSSamuel J. Greear result = 1;
727d8ee3b5dSSamuel J. Greear }
728d8ee3b5dSSamuel J. Greear
7290fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&ctx);
730d8ee3b5dSSamuel J. Greear for (int i = 0; tests[cnt].input[i] != '\0'; ++i)
7310fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (&tests[cnt].input[i], 1, &ctx);
7320fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&ctx, sum);
733d8ee3b5dSSamuel J. Greear if (memcmp (tests[cnt].result, sum, 64) != 0)
734d8ee3b5dSSamuel J. Greear {
735d8ee3b5dSSamuel J. Greear printf ("test %d run %d failed\n", cnt, 2);
736d8ee3b5dSSamuel J. Greear result = 1;
737d8ee3b5dSSamuel J. Greear }
738d8ee3b5dSSamuel J. Greear }
739d8ee3b5dSSamuel J. Greear
740d8ee3b5dSSamuel J. Greear /* Test vector from FIPS 180-2: appendix C.3. */
741d8ee3b5dSSamuel J. Greear char buf[1000];
742d8ee3b5dSSamuel J. Greear memset (buf, 'a', sizeof (buf));
7430fe46dc6SMatthew Dillon __crypt__sha512_init_ctx (&ctx);
744d8ee3b5dSSamuel J. Greear for (int i = 0; i < 1000; ++i)
7450fe46dc6SMatthew Dillon __crypt__sha512_process_bytes (buf, sizeof (buf), &ctx);
7460fe46dc6SMatthew Dillon __crypt__sha512_finish_ctx (&ctx, sum);
747d8ee3b5dSSamuel J. Greear static const char expected[64] =
748d8ee3b5dSSamuel J. Greear "\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
749d8ee3b5dSSamuel J. Greear "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
750d8ee3b5dSSamuel J. Greear "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b"
751d8ee3b5dSSamuel J. Greear "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b";
752d8ee3b5dSSamuel J. Greear if (memcmp (expected, sum, 64) != 0)
753d8ee3b5dSSamuel J. Greear {
754d8ee3b5dSSamuel J. Greear printf ("test %d failed\n", cnt);
755d8ee3b5dSSamuel J. Greear result = 1;
756d8ee3b5dSSamuel J. Greear }
757d8ee3b5dSSamuel J. Greear
758d8ee3b5dSSamuel J. Greear for (cnt = 0; cnt < ntests2; ++cnt)
759d8ee3b5dSSamuel J. Greear {
760d8ee3b5dSSamuel J. Greear char *cp = crypt_sha512 (tests2[cnt].input, tests2[cnt].salt);
761d8ee3b5dSSamuel J. Greear
762d8ee3b5dSSamuel J. Greear if (strcmp (cp, tests2[cnt].expected) != 0)
763d8ee3b5dSSamuel J. Greear {
764d8ee3b5dSSamuel J. Greear printf ("test %d: expected \"%s\", got \"%s\"\n",
765d8ee3b5dSSamuel J. Greear cnt, tests2[cnt].expected, cp);
766d8ee3b5dSSamuel J. Greear result = 1;
767d8ee3b5dSSamuel J. Greear }
768d8ee3b5dSSamuel J. Greear }
769d8ee3b5dSSamuel J. Greear
770d8ee3b5dSSamuel J. Greear if (result == 0)
771d8ee3b5dSSamuel J. Greear puts ("all tests OK");
772d8ee3b5dSSamuel J. Greear
773d8ee3b5dSSamuel J. Greear return result;
774d8ee3b5dSSamuel J. Greear }
775d8ee3b5dSSamuel J. Greear #endif
776d8ee3b5dSSamuel J. Greear
777