1 | /*
|
---|
2 | * public domain sha256 crypt implementation
|
---|
3 | *
|
---|
4 | * original sha crypt design: http://people.redhat.com/drepper/SHA-crypt.txt
|
---|
5 | * in this implementation at least 32bit int is assumed,
|
---|
6 | * key length is limited, the $5$ prefix is mandatory, '\n' and ':' is rejected
|
---|
7 | * in the salt and rounds= setting must contain a valid iteration count,
|
---|
8 | * on error "*" is returned.
|
---|
9 | */
|
---|
10 | #include <ctype.h>
|
---|
11 | #include <stdlib.h>
|
---|
12 | #include <stdio.h>
|
---|
13 | #include <string.h>
|
---|
14 | #include <stdint.h>
|
---|
15 |
|
---|
16 | /* public domain sha256 implementation based on fips180-3 */
|
---|
17 |
|
---|
18 | struct sha256 {
|
---|
19 | uint64_t len; /* processed message length */
|
---|
20 | uint32_t h[8]; /* hash state */
|
---|
21 | uint8_t buf[64]; /* message block buffer */
|
---|
22 | };
|
---|
23 |
|
---|
24 | static uint32_t ror(uint32_t n, int k) { return (n >> k) | (n << (32-k)); }
|
---|
25 | #define Ch(x,y,z) (z ^ (x & (y ^ z)))
|
---|
26 | #define Maj(x,y,z) ((x & y) | (z & (x | y)))
|
---|
27 | #define S0(x) (ror(x,2) ^ ror(x,13) ^ ror(x,22))
|
---|
28 | #define S1(x) (ror(x,6) ^ ror(x,11) ^ ror(x,25))
|
---|
29 | #define R0(x) (ror(x,7) ^ ror(x,18) ^ (x>>3))
|
---|
30 | #define R1(x) (ror(x,17) ^ ror(x,19) ^ (x>>10))
|
---|
31 |
|
---|
32 | static const uint32_t K[64] = {
|
---|
33 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
---|
34 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
---|
35 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
---|
36 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
---|
37 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
---|
38 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
---|
39 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
---|
40 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
---|
41 | };
|
---|
42 |
|
---|
43 | static void processblock(struct sha256 *s, const uint8_t *buf)
|
---|
44 | {
|
---|
45 | uint32_t W[64], t1, t2, a, b, c, d, e, f, g, h;
|
---|
46 | int i;
|
---|
47 |
|
---|
48 | for (i = 0; i < 16; i++) {
|
---|
49 | W[i] = (uint32_t)buf[4*i]<<24;
|
---|
50 | W[i] |= (uint32_t)buf[4*i+1]<<16;
|
---|
51 | W[i] |= (uint32_t)buf[4*i+2]<<8;
|
---|
52 | W[i] |= buf[4*i+3];
|
---|
53 | }
|
---|
54 | for (; i < 64; i++)
|
---|
55 | W[i] = R1(W[i-2]) + W[i-7] + R0(W[i-15]) + W[i-16];
|
---|
56 | a = s->h[0];
|
---|
57 | b = s->h[1];
|
---|
58 | c = s->h[2];
|
---|
59 | d = s->h[3];
|
---|
60 | e = s->h[4];
|
---|
61 | f = s->h[5];
|
---|
62 | g = s->h[6];
|
---|
63 | h = s->h[7];
|
---|
64 | for (i = 0; i < 64; i++) {
|
---|
65 | t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i];
|
---|
66 | t2 = S0(a) + Maj(a,b,c);
|
---|
67 | h = g;
|
---|
68 | g = f;
|
---|
69 | f = e;
|
---|
70 | e = d + t1;
|
---|
71 | d = c;
|
---|
72 | c = b;
|
---|
73 | b = a;
|
---|
74 | a = t1 + t2;
|
---|
75 | }
|
---|
76 | s->h[0] += a;
|
---|
77 | s->h[1] += b;
|
---|
78 | s->h[2] += c;
|
---|
79 | s->h[3] += d;
|
---|
80 | s->h[4] += e;
|
---|
81 | s->h[5] += f;
|
---|
82 | s->h[6] += g;
|
---|
83 | s->h[7] += h;
|
---|
84 | }
|
---|
85 |
|
---|
86 | static void pad(struct sha256 *s)
|
---|
87 | {
|
---|
88 | unsigned r = s->len % 64;
|
---|
89 |
|
---|
90 | s->buf[r++] = 0x80;
|
---|
91 | if (r > 56) {
|
---|
92 | memset(s->buf + r, 0, 64 - r);
|
---|
93 | r = 0;
|
---|
94 | processblock(s, s->buf);
|
---|
95 | }
|
---|
96 | memset(s->buf + r, 0, 56 - r);
|
---|
97 | s->len *= 8;
|
---|
98 | s->buf[56] = s->len >> 56;
|
---|
99 | s->buf[57] = s->len >> 48;
|
---|
100 | s->buf[58] = s->len >> 40;
|
---|
101 | s->buf[59] = s->len >> 32;
|
---|
102 | s->buf[60] = s->len >> 24;
|
---|
103 | s->buf[61] = s->len >> 16;
|
---|
104 | s->buf[62] = s->len >> 8;
|
---|
105 | s->buf[63] = s->len;
|
---|
106 | processblock(s, s->buf);
|
---|
107 | }
|
---|
108 |
|
---|
109 | static void sha256_init(struct sha256 *s)
|
---|
110 | {
|
---|
111 | s->len = 0;
|
---|
112 | s->h[0] = 0x6a09e667;
|
---|
113 | s->h[1] = 0xbb67ae85;
|
---|
114 | s->h[2] = 0x3c6ef372;
|
---|
115 | s->h[3] = 0xa54ff53a;
|
---|
116 | s->h[4] = 0x510e527f;
|
---|
117 | s->h[5] = 0x9b05688c;
|
---|
118 | s->h[6] = 0x1f83d9ab;
|
---|
119 | s->h[7] = 0x5be0cd19;
|
---|
120 | }
|
---|
121 |
|
---|
122 | static void sha256_sum(struct sha256 *s, uint8_t *md)
|
---|
123 | {
|
---|
124 | int i;
|
---|
125 |
|
---|
126 | pad(s);
|
---|
127 | for (i = 0; i < 8; i++) {
|
---|
128 | md[4*i] = s->h[i] >> 24;
|
---|
129 | md[4*i+1] = s->h[i] >> 16;
|
---|
130 | md[4*i+2] = s->h[i] >> 8;
|
---|
131 | md[4*i+3] = s->h[i];
|
---|
132 | }
|
---|
133 | }
|
---|
134 |
|
---|
135 | static void sha256_update(struct sha256 *s, const void *m, unsigned long len)
|
---|
136 | {
|
---|
137 | const uint8_t *p = m;
|
---|
138 | unsigned r = s->len % 64;
|
---|
139 |
|
---|
140 | s->len += len;
|
---|
141 | if (r) {
|
---|
142 | if (len < 64 - r) {
|
---|
143 | memcpy(s->buf + r, p, len);
|
---|
144 | return;
|
---|
145 | }
|
---|
146 | memcpy(s->buf + r, p, 64 - r);
|
---|
147 | len -= 64 - r;
|
---|
148 | p += 64 - r;
|
---|
149 | processblock(s, s->buf);
|
---|
150 | }
|
---|
151 | for (; len >= 64; len -= 64, p += 64)
|
---|
152 | processblock(s, p);
|
---|
153 | memcpy(s->buf, p, len);
|
---|
154 | }
|
---|
155 |
|
---|
156 | static const unsigned char b64[] =
|
---|
157 | "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
---|
158 |
|
---|
159 | static char *to64(char *s, unsigned int u, int n)
|
---|
160 | {
|
---|
161 | while (--n >= 0) {
|
---|
162 | *s++ = b64[u % 64];
|
---|
163 | u /= 64;
|
---|
164 | }
|
---|
165 | return s;
|
---|
166 | }
|
---|
167 |
|
---|
168 | /* key limit is not part of the original design, added for DoS protection.
|
---|
169 | * rounds limit has been lowered (versus the reference/spec), also for DoS
|
---|
170 | * protection. runtime is O(klen^2 + klen*rounds) */
|
---|
171 | #define KEY_MAX 256
|
---|
172 | #define SALT_MAX 16
|
---|
173 | #define ROUNDS_DEFAULT 5000
|
---|
174 | #define ROUNDS_MIN 1000
|
---|
175 | #define ROUNDS_MAX 9999999
|
---|
176 |
|
---|
177 | /* hash n bytes of the repeated md message digest */
|
---|
178 | static void hashmd(struct sha256 *s, unsigned int n, const void *md)
|
---|
179 | {
|
---|
180 | unsigned int i;
|
---|
181 |
|
---|
182 | for (i = n; i > 32; i -= 32)
|
---|
183 | sha256_update(s, md, 32);
|
---|
184 | sha256_update(s, md, i);
|
---|
185 | }
|
---|
186 |
|
---|
187 | static char *sha256crypt(const char *key, const char *setting, char *output)
|
---|
188 | {
|
---|
189 | struct sha256 ctx;
|
---|
190 | unsigned char md[32], kmd[32], smd[32];
|
---|
191 | unsigned int i, r, klen, slen;
|
---|
192 | char rounds[20] = "";
|
---|
193 | const char *salt;
|
---|
194 | char *p;
|
---|
195 |
|
---|
196 | /* reject large keys */
|
---|
197 | klen = strnlen(key, KEY_MAX+1);
|
---|
198 | if (klen > KEY_MAX)
|
---|
199 | return 0;
|
---|
200 |
|
---|
201 | /* setting: $5$rounds=n$salt$ (rounds=n$ and closing $ are optional) */
|
---|
202 | if (strncmp(setting, "$5$", 3) != 0)
|
---|
203 | return 0;
|
---|
204 | salt = setting + 3;
|
---|
205 |
|
---|
206 | r = ROUNDS_DEFAULT;
|
---|
207 | if (strncmp(salt, "rounds=", sizeof "rounds=" - 1) == 0) {
|
---|
208 | unsigned long u;
|
---|
209 | char *end;
|
---|
210 |
|
---|
211 | /*
|
---|
212 | * this is a deviation from the reference:
|
---|
213 | * bad rounds setting is rejected if it is
|
---|
214 | * - empty
|
---|
215 | * - unterminated (missing '$')
|
---|
216 | * - begins with anything but a decimal digit
|
---|
217 | * the reference implementation treats these bad
|
---|
218 | * rounds as part of the salt or parse them with
|
---|
219 | * strtoul semantics which may cause problems
|
---|
220 | * including non-portable hashes that depend on
|
---|
221 | * the host's value of ULONG_MAX.
|
---|
222 | */
|
---|
223 | salt += sizeof "rounds=" - 1;
|
---|
224 | if (!isdigit(*salt))
|
---|
225 | return 0;
|
---|
226 | u = strtoul(salt, &end, 10);
|
---|
227 | if (*end != '$')
|
---|
228 | return 0;
|
---|
229 | salt = end+1;
|
---|
230 | if (u < ROUNDS_MIN)
|
---|
231 | r = ROUNDS_MIN;
|
---|
232 | else if (u > ROUNDS_MAX)
|
---|
233 | return 0;
|
---|
234 | else
|
---|
235 | r = u;
|
---|
236 | /* needed when rounds is zero prefixed or out of bounds */
|
---|
237 | sprintf(rounds, "rounds=%u$", r);
|
---|
238 | }
|
---|
239 |
|
---|
240 | for (i = 0; i < SALT_MAX && salt[i] && salt[i] != '$'; i++)
|
---|
241 | /* reject characters that interfere with /etc/shadow parsing */
|
---|
242 | if (salt[i] == '\n' || salt[i] == ':')
|
---|
243 | return 0;
|
---|
244 | slen = i;
|
---|
245 |
|
---|
246 | /* B = sha(key salt key) */
|
---|
247 | sha256_init(&ctx);
|
---|
248 | sha256_update(&ctx, key, klen);
|
---|
249 | sha256_update(&ctx, salt, slen);
|
---|
250 | sha256_update(&ctx, key, klen);
|
---|
251 | sha256_sum(&ctx, md);
|
---|
252 |
|
---|
253 | /* A = sha(key salt repeat-B alternate-B-key) */
|
---|
254 | sha256_init(&ctx);
|
---|
255 | sha256_update(&ctx, key, klen);
|
---|
256 | sha256_update(&ctx, salt, slen);
|
---|
257 | hashmd(&ctx, klen, md);
|
---|
258 | for (i = klen; i > 0; i >>= 1)
|
---|
259 | if (i & 1)
|
---|
260 | sha256_update(&ctx, md, sizeof md);
|
---|
261 | else
|
---|
262 | sha256_update(&ctx, key, klen);
|
---|
263 | sha256_sum(&ctx, md);
|
---|
264 |
|
---|
265 | /* DP = sha(repeat-key), this step takes O(klen^2) time */
|
---|
266 | sha256_init(&ctx);
|
---|
267 | for (i = 0; i < klen; i++)
|
---|
268 | sha256_update(&ctx, key, klen);
|
---|
269 | sha256_sum(&ctx, kmd);
|
---|
270 |
|
---|
271 | /* DS = sha(repeat-salt) */
|
---|
272 | sha256_init(&ctx);
|
---|
273 | for (i = 0; i < 16 + md[0]; i++)
|
---|
274 | sha256_update(&ctx, salt, slen);
|
---|
275 | sha256_sum(&ctx, smd);
|
---|
276 |
|
---|
277 | /* iterate A = f(A,DP,DS), this step takes O(rounds*klen) time */
|
---|
278 | for (i = 0; i < r; i++) {
|
---|
279 | sha256_init(&ctx);
|
---|
280 | if (i % 2)
|
---|
281 | hashmd(&ctx, klen, kmd);
|
---|
282 | else
|
---|
283 | sha256_update(&ctx, md, sizeof md);
|
---|
284 | if (i % 3)
|
---|
285 | sha256_update(&ctx, smd, slen);
|
---|
286 | if (i % 7)
|
---|
287 | hashmd(&ctx, klen, kmd);
|
---|
288 | if (i % 2)
|
---|
289 | sha256_update(&ctx, md, sizeof md);
|
---|
290 | else
|
---|
291 | hashmd(&ctx, klen, kmd);
|
---|
292 | sha256_sum(&ctx, md);
|
---|
293 | }
|
---|
294 |
|
---|
295 | /* output is $5$rounds=n$salt$hash */
|
---|
296 | p = output;
|
---|
297 | p += sprintf(p, "$5$%s%.*s$", rounds, slen, salt);
|
---|
298 | static const unsigned char perm[][3] = {
|
---|
299 | 0,10,20,21,1,11,12,22,2,3,13,23,24,4,14,
|
---|
300 | 15,25,5,6,16,26,27,7,17,18,28,8,9,19,29 };
|
---|
301 | for (i=0; i<10; i++) p = to64(p,
|
---|
302 | (md[perm[i][0]]<<16)|(md[perm[i][1]]<<8)|md[perm[i][2]], 4);
|
---|
303 | p = to64(p, (md[31]<<8)|md[30], 3);
|
---|
304 | *p = 0;
|
---|
305 | return output;
|
---|
306 | }
|
---|
307 |
|
---|
308 | char *__crypt_sha256(const char *key, const char *setting, char *output)
|
---|
309 | {
|
---|
310 | static const char testkey[] = "Xy01@#\x01\x02\x80\x7f\xff\r\n\x81\t !";
|
---|
311 | static const char testsetting[] = "$5$rounds=1234$abc0123456789$";
|
---|
312 | static const char testhash[] = "$5$rounds=1234$abc0123456789$3VfDjPt05VHFn47C/ojFZ6KRPYrOjj1lLbH.dkF3bZ6";
|
---|
313 | char testbuf[128];
|
---|
314 | char *p, *q;
|
---|
315 |
|
---|
316 | p = sha256crypt(key, setting, output);
|
---|
317 | /* self test and stack cleanup */
|
---|
318 | q = sha256crypt(testkey, testsetting, testbuf);
|
---|
319 | if (!p || q != testbuf || memcmp(testbuf, testhash, sizeof testhash))
|
---|
320 | return "*";
|
---|
321 | return p;
|
---|
322 | }
|
---|