pwhash_scryptsalsa208sha256.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include <errno.h>
  2. #include <limits.h>
  3. #include <stddef.h>
  4. #include <stdint.h>
  5. #include <string.h>
  6. #include "crypto_pwhash_scryptsalsa208sha256.h"
  7. #include "crypto_scrypt.h"
  8. #include "private/common.h"
  9. #include "randombytes.h"
  10. #include "utils.h"
  11. #define SETTING_SIZE(saltbytes) \
  12. ((sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + \
  13. BYTES2CHARS(saltbytes))
  14. static int
  15. pickparams(unsigned long long opslimit, const size_t memlimit,
  16. uint32_t *const N_log2, uint32_t *const p, uint32_t *const r)
  17. {
  18. unsigned long long maxN;
  19. unsigned long long maxrp;
  20. if (opslimit < 32768) {
  21. opslimit = 32768;
  22. }
  23. *r = 8;
  24. if (opslimit < memlimit / 32) {
  25. *p = 1;
  26. maxN = opslimit / (*r * 4);
  27. for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
  28. if ((uint64_t)(1) << *N_log2 > maxN / 2) {
  29. break;
  30. }
  31. }
  32. } else {
  33. maxN = memlimit / ((size_t) *r * 128);
  34. for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
  35. if ((uint64_t)(1) << *N_log2 > maxN / 2) {
  36. break;
  37. }
  38. }
  39. maxrp = (opslimit / 4) / ((uint64_t)(1) << *N_log2);
  40. /* LCOV_EXCL_START */
  41. if (maxrp > 0x3fffffff) {
  42. maxrp = 0x3fffffff;
  43. }
  44. /* LCOV_EXCL_STOP */
  45. *p = (uint32_t)(maxrp) / *r;
  46. }
  47. return 0;
  48. }
  49. static size_t
  50. sodium_strnlen(const char *str, size_t maxlen)
  51. {
  52. size_t i = 0U;
  53. while (i < maxlen && str[i] != 0) {
  54. i++;
  55. }
  56. return i;
  57. }
  58. size_t
  59. crypto_pwhash_scryptsalsa208sha256_bytes_min(void)
  60. {
  61. return crypto_pwhash_scryptsalsa208sha256_BYTES_MIN;
  62. }
  63. size_t
  64. crypto_pwhash_scryptsalsa208sha256_bytes_max(void)
  65. {
  66. return crypto_pwhash_scryptsalsa208sha256_BYTES_MAX;
  67. }
  68. size_t
  69. crypto_pwhash_scryptsalsa208sha256_passwd_min(void)
  70. {
  71. return crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN;
  72. }
  73. size_t
  74. crypto_pwhash_scryptsalsa208sha256_passwd_max(void)
  75. {
  76. return crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX;
  77. }
  78. size_t
  79. crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
  80. {
  81. return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
  82. }
  83. size_t
  84. crypto_pwhash_scryptsalsa208sha256_strbytes(void)
  85. {
  86. return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
  87. }
  88. const char *
  89. crypto_pwhash_scryptsalsa208sha256_strprefix(void)
  90. {
  91. return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
  92. }
  93. size_t
  94. crypto_pwhash_scryptsalsa208sha256_opslimit_min(void)
  95. {
  96. return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN;
  97. }
  98. size_t
  99. crypto_pwhash_scryptsalsa208sha256_opslimit_max(void)
  100. {
  101. return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX;
  102. }
  103. size_t
  104. crypto_pwhash_scryptsalsa208sha256_memlimit_min(void)
  105. {
  106. return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN;
  107. }
  108. size_t
  109. crypto_pwhash_scryptsalsa208sha256_memlimit_max(void)
  110. {
  111. return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX;
  112. }
  113. size_t
  114. crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
  115. {
  116. return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
  117. }
  118. size_t
  119. crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
  120. {
  121. return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
  122. }
  123. size_t
  124. crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
  125. {
  126. return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
  127. }
  128. size_t
  129. crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
  130. {
  131. return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
  132. }
  133. int
  134. crypto_pwhash_scryptsalsa208sha256(unsigned char *const out,
  135. unsigned long long outlen,
  136. const char *const passwd,
  137. unsigned long long passwdlen,
  138. const unsigned char *const salt,
  139. unsigned long long opslimit, size_t memlimit)
  140. {
  141. uint32_t N_log2;
  142. uint32_t p;
  143. uint32_t r;
  144. memset(out, 0, outlen);
  145. if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX ||
  146. outlen > crypto_pwhash_scryptsalsa208sha256_BYTES_MAX) {
  147. errno = EFBIG; /* LCOV_EXCL_LINE */
  148. return -1; /* LCOV_EXCL_LINE */
  149. }
  150. if (outlen < crypto_pwhash_scryptsalsa208sha256_BYTES_MIN ||
  151. pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
  152. errno = EINVAL; /* LCOV_EXCL_LINE */
  153. return -1; /* LCOV_EXCL_LINE */
  154. }
  155. if ((const void *) out == (const void *) passwd) {
  156. errno = EINVAL;
  157. return -1;
  158. }
  159. return crypto_pwhash_scryptsalsa208sha256_ll(
  160. (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) salt,
  161. crypto_pwhash_scryptsalsa208sha256_SALTBYTES, (uint64_t)(1) << N_log2,
  162. r, p, out, (size_t) outlen);
  163. }
  164. int
  165. crypto_pwhash_scryptsalsa208sha256_str(
  166. char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
  167. const char *const passwd, unsigned long long passwdlen,
  168. unsigned long long opslimit, size_t memlimit)
  169. {
  170. uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
  171. char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
  172. escrypt_local_t escrypt_local;
  173. uint32_t N_log2;
  174. uint32_t p;
  175. uint32_t r;
  176. memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
  177. if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX) {
  178. errno = EFBIG; /* LCOV_EXCL_LINE */
  179. return -1; /* LCOV_EXCL_LINE */
  180. }
  181. if (passwdlen < crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN ||
  182. pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
  183. errno = EINVAL; /* LCOV_EXCL_LINE */
  184. return -1; /* LCOV_EXCL_LINE */
  185. }
  186. randombytes_buf(salt, sizeof salt);
  187. if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, (uint8_t *) setting,
  188. sizeof setting) == NULL) {
  189. errno = EINVAL; /* LCOV_EXCL_LINE */
  190. return -1; /* LCOV_EXCL_LINE */
  191. }
  192. if (escrypt_init_local(&escrypt_local) != 0) {
  193. return -1; /* LCOV_EXCL_LINE */
  194. }
  195. if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
  196. (const uint8_t *) setting, (uint8_t *) out,
  197. crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
  198. /* LCOV_EXCL_START */
  199. escrypt_free_local(&escrypt_local);
  200. errno = EINVAL;
  201. return -1;
  202. /* LCOV_EXCL_STOP */
  203. }
  204. escrypt_free_local(&escrypt_local);
  205. COMPILER_ASSERT(
  206. SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) ==
  207. crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES);
  208. COMPILER_ASSERT(
  209. crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
  210. crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U ==
  211. crypto_pwhash_scryptsalsa208sha256_STRBYTES);
  212. return 0;
  213. }
  214. int
  215. crypto_pwhash_scryptsalsa208sha256_str_verify(
  216. const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
  217. const char *const passwd, unsigned long long passwdlen)
  218. {
  219. char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
  220. escrypt_local_t escrypt_local;
  221. int ret = -1;
  222. if (sodium_strnlen(str, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
  223. crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U) {
  224. return -1;
  225. }
  226. if (escrypt_init_local(&escrypt_local) != 0) {
  227. return -1; /* LCOV_EXCL_LINE */
  228. }
  229. memset(wanted, 0, sizeof wanted);
  230. if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
  231. (const uint8_t *) str, (uint8_t *) wanted,
  232. sizeof wanted) == NULL) {
  233. escrypt_free_local(&escrypt_local);
  234. return -1;
  235. }
  236. escrypt_free_local(&escrypt_local);
  237. ret = sodium_memcmp(wanted, str, sizeof wanted);
  238. sodium_memzero(wanted, sizeof wanted);
  239. return ret;
  240. }
  241. int
  242. crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(
  243. const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
  244. unsigned long long opslimit, size_t memlimit)
  245. {
  246. uint32_t N_log2, N_log2_;
  247. uint32_t p, p_;
  248. uint32_t r, r_;
  249. if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
  250. errno = EINVAL;
  251. return -1;
  252. }
  253. if (sodium_strnlen(str, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
  254. crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U) {
  255. errno = EINVAL;
  256. return -1;
  257. }
  258. if (escrypt_parse_setting((const uint8_t *) str,
  259. &N_log2_, &r_, &p_) == NULL) {
  260. errno = EINVAL;
  261. return -1;
  262. }
  263. if (N_log2 != N_log2_ || r != r_ || p != p_) {
  264. return 1;
  265. }
  266. return 0;
  267. }