1/* SHA256 and SHA512-based Unix crypt implementation. 2 * Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>. 3 */ 4 5/* Prefix for optional rounds specification. */ 6static const char str_rounds[] = "rounds=%u$"; 7 8/* Maximum salt string length. */ 9#define SALT_LEN_MAX 16 10/* Default number of rounds if not explicitly specified. */ 11#define ROUNDS_DEFAULT 5000 12/* Minimum number of rounds. */ 13#define ROUNDS_MIN 1000 14/* Maximum number of rounds. */ 15#define ROUNDS_MAX 999999999 16 17static char * 18NOINLINE 19sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) 20{ 21 void (*sha_begin)(void *ctx) FAST_FUNC; 22 void (*sha_hash)(const void *buffer, size_t len, void *ctx) FAST_FUNC; 23 void (*sha_end)(void *resbuf, void *ctx) FAST_FUNC; 24 int _32or64; 25 26 char *result, *resptr; 27 28 /* btw, sha256 needs [32] and uint32_t only */ 29 struct { 30 unsigned char alt_result[64]; 31 unsigned char temp_result[64]; 32 union { 33 sha256_ctx_t x; 34 sha512_ctx_t y; 35 } ctx; 36 union { 37 sha256_ctx_t x; 38 sha512_ctx_t y; 39 } alt_ctx; 40 } L __attribute__((__aligned__(__alignof__(uint64_t)))); 41#define alt_result (L.alt_result ) 42#define temp_result (L.temp_result) 43#define ctx (L.ctx ) 44#define alt_ctx (L.alt_ctx ) 45 unsigned salt_len; 46 unsigned key_len; 47 unsigned cnt; 48 unsigned rounds; 49 char *cp; 50 char is_sha512; 51 52 /* Analyze salt, construct already known part of result */ 53 cnt = strlen(salt_data) + 1 + 43 + 1; 54 is_sha512 = salt_data[1]; 55 if (is_sha512 == '6') 56 cnt += 43; 57 result = resptr = xzalloc(cnt); /* will provide NUL terminator */ 58 *resptr++ = '$'; 59 *resptr++ = is_sha512; 60 *resptr++ = '$'; 61 rounds = ROUNDS_DEFAULT; 62 salt_data += 3; 63 if (strncmp(salt_data, str_rounds, 7) == 0) { 64 /* 7 == strlen("rounds=") */ 65 char *endp; 66 cnt = bb_strtou(salt_data + 7, &endp, 10); 67 if (*endp == '$') { 68 salt_data = endp + 1; 69 rounds = cnt; 70 if (rounds < ROUNDS_MIN) 71 rounds = ROUNDS_MIN; 72 if (rounds > ROUNDS_MAX) 73 rounds = ROUNDS_MAX; 74 /* add "rounds=NNNNN$" to result */ 75 resptr += sprintf(resptr, str_rounds, rounds); 76 } 77 } 78 salt_len = strchrnul(salt_data, '$') - salt_data; 79 if (salt_len > SALT_LEN_MAX) 80 salt_len = SALT_LEN_MAX; 81 /* xstrdup assures suitable alignment; also we will use it 82 as a scratch space later. */ 83 salt_data = xstrndup(salt_data, salt_len); 84 /* add "salt$" to result */ 85 strcpy(resptr, salt_data); 86 resptr += salt_len; 87 *resptr++ = '$'; 88 /* key data doesn't need much processing */ 89 key_len = strlen(key_data); 90 key_data = xstrdup(key_data); 91 92 /* Which flavor of SHAnnn ops to use? */ 93 sha_begin = (void*)sha256_begin; 94 sha_hash = (void*)sha256_hash; 95 sha_end = (void*)sha256_end; 96 _32or64 = 32; 97 if (is_sha512 == '6') { 98 sha_begin = (void*)sha512_begin; 99 sha_hash = (void*)sha512_hash; 100 sha_end = (void*)sha512_end; 101 _32or64 = 64; 102 } 103 104 /* Add KEY, SALT. */ 105 sha_begin(&ctx); 106 sha_hash(key_data, key_len, &ctx); 107 sha_hash(salt_data, salt_len, &ctx); 108 109 /* Compute alternate SHA sum with input KEY, SALT, and KEY. 110 The final result will be added to the first context. */ 111 sha_begin(&alt_ctx); 112 sha_hash(key_data, key_len, &alt_ctx); 113 sha_hash(salt_data, salt_len, &alt_ctx); 114 sha_hash(key_data, key_len, &alt_ctx); 115 sha_end(alt_result, &alt_ctx); 116 117 /* Add result of this to the other context. */ 118 /* Add for any character in the key one byte of the alternate sum. */ 119 for (cnt = key_len; cnt > _32or64; cnt -= _32or64) 120 sha_hash(alt_result, _32or64, &ctx); 121 sha_hash(alt_result, cnt, &ctx); 122 123 /* Take the binary representation of the length of the key and for every 124 1 add the alternate sum, for every 0 the key. */ 125 for (cnt = key_len; cnt != 0; cnt >>= 1) 126 if ((cnt & 1) != 0) 127 sha_hash(alt_result, _32or64, &ctx); 128 else 129 sha_hash(key_data, key_len, &ctx); 130 131 /* Create intermediate result. */ 132 sha_end(alt_result, &ctx); 133 134 /* Start computation of P byte sequence. */ 135 /* For every character in the password add the entire password. */ 136 sha_begin(&alt_ctx); 137 for (cnt = 0; cnt < key_len; ++cnt) 138 sha_hash(key_data, key_len, &alt_ctx); 139 sha_end(temp_result, &alt_ctx); 140 141 /* NB: past this point, raw key_data is not used anymore */ 142 143 /* Create byte sequence P. */ 144#define p_bytes key_data /* reuse the buffer as it is of the key_len size */ 145 cp = p_bytes; /* was: ... = alloca(key_len); */ 146 for (cnt = key_len; cnt >= _32or64; cnt -= _32or64) { 147 cp = memcpy(cp, temp_result, _32or64); 148 cp += _32or64; 149 } 150 memcpy(cp, temp_result, cnt); 151 152 /* Start computation of S byte sequence. */ 153 /* For every character in the password add the entire password. */ 154 sha_begin(&alt_ctx); 155 for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) 156 sha_hash(salt_data, salt_len, &alt_ctx); 157 sha_end(temp_result, &alt_ctx); 158 159 /* NB: past this point, raw salt_data is not used anymore */ 160 161 /* Create byte sequence S. */ 162#define s_bytes salt_data /* reuse the buffer as it is of the salt_len size */ 163 cp = s_bytes; /* was: ... = alloca(salt_len); */ 164 for (cnt = salt_len; cnt >= _32or64; cnt -= _32or64) { 165 cp = memcpy(cp, temp_result, _32or64); 166 cp += _32or64; 167 } 168 memcpy(cp, temp_result, cnt); 169 170 /* Repeatedly run the collected hash value through SHA to burn 171 CPU cycles. */ 172 for (cnt = 0; cnt < rounds; ++cnt) { 173 sha_begin(&ctx); 174 175 /* Add key or last result. */ 176 if ((cnt & 1) != 0) 177 sha_hash(p_bytes, key_len, &ctx); 178 else 179 sha_hash(alt_result, _32or64, &ctx); 180 /* Add salt for numbers not divisible by 3. */ 181 if (cnt % 3 != 0) 182 sha_hash(s_bytes, salt_len, &ctx); 183 /* Add key for numbers not divisible by 7. */ 184 if (cnt % 7 != 0) 185 sha_hash(p_bytes, key_len, &ctx); 186 /* Add key or last result. */ 187 if ((cnt & 1) != 0) 188 sha_hash(alt_result, _32or64, &ctx); 189 else 190 sha_hash(p_bytes, key_len, &ctx); 191 192 sha_end(alt_result, &ctx); 193 } 194 195 /* Append encrypted password to result buffer */ 196//TODO: replace with something like 197// bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64); 198#define b64_from_24bit(B2, B1, B0, N) \ 199do { \ 200 unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \ 201 resptr = to64(resptr, w, N); \ 202} while (0) 203 if (is_sha512 == '5') { 204 unsigned i = 0; 205 while (1) { 206 unsigned j = i + 10; 207 unsigned k = i + 20; 208 if (j >= 30) j -= 30; 209 if (k >= 30) k -= 30; 210 b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4); 211 if (k == 29) 212 break; 213 i = k + 1; 214 } 215 b64_from_24bit(0, alt_result[31], alt_result[30], 3); 216 /* was: 217 b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4); 218 b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4); 219 b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4); 220 b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4); 221 b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4); 222 b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4); 223 b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4); 224 b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4); 225 b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4); 226 b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4); 227 b64_from_24bit(0, alt_result[31], alt_result[30], 3); 228 */ 229 } else { 230 unsigned i = 0; 231 while (1) { 232 unsigned j = i + 21; 233 unsigned k = i + 42; 234 if (j >= 63) j -= 63; 235 if (k >= 63) k -= 63; 236 b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4); 237 if (j == 20) 238 break; 239 i = j + 1; 240 } 241 b64_from_24bit(0, 0, alt_result[63], 2); 242 /* was: 243 b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4); 244 b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4); 245 b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4); 246 b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4); 247 b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4); 248 b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4); 249 b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4); 250 b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4); 251 b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4); 252 b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4); 253 b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4); 254 b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4); 255 b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4); 256 b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4); 257 b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4); 258 b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4); 259 b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4); 260 b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4); 261 b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4); 262 b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4); 263 b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4); 264 b64_from_24bit(0, 0, alt_result[63], 2); 265 */ 266 } 267 /* *resptr = '\0'; - xzalloc did it */ 268#undef b64_from_24bit 269 270 /* Clear the buffer for the intermediate result so that people 271 attaching to processes or reading core dumps cannot get any 272 information. */ 273 memset(&L, 0, sizeof(L)); /* [alt]_ctx and XXX_result buffers */ 274 memset(key_data, 0, key_len); /* also p_bytes */ 275 memset(salt_data, 0, salt_len); /* also s_bytes */ 276 free(key_data); 277 free(salt_data); 278#undef p_bytes 279#undef s_bytes 280 281 return result; 282#undef alt_result 283#undef temp_result 284#undef ctx 285#undef alt_ctx 286} 287