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