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 18struct 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 24static 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 32static const uint32_t K[64] = { 330x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 340xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 350xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 360x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 370x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 380xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 390x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 400x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 41}; 42 43static 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 86static 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 109static 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 122static 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 135static 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 156static const unsigned char b64[] = 157"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 158 159static 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 */ 178static 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 187static 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 308char *__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} 323