pw_encrypt_sha.c 9.2 KB

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