pwhash_argon2i.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include <errno.h>
  2. #include <limits.h>
  3. #include <stddef.h>
  4. #include <stdint.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "argon2-core.h"
  8. #include "argon2-encoding.h"
  9. #include "argon2.h"
  10. #include "crypto_pwhash.h"
  11. #include "crypto_pwhash_argon2i.h"
  12. #include "crypto_pwhash_argon2id.h"
  13. #include "private/common.h"
  14. #include "randombytes.h"
  15. #include "utils.h"
  16. #define STR_HASHBYTES 32U
  17. int
  18. crypto_pwhash_argon2i_alg_argon2i13(void)
  19. {
  20. return crypto_pwhash_argon2i_ALG_ARGON2I13;
  21. }
  22. size_t
  23. crypto_pwhash_argon2i_bytes_min(void)
  24. {
  25. COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MIN >= ARGON2_MIN_OUTLEN);
  26. return crypto_pwhash_argon2i_BYTES_MIN;
  27. }
  28. size_t
  29. crypto_pwhash_argon2i_bytes_max(void)
  30. {
  31. COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MAX <= ARGON2_MAX_OUTLEN);
  32. return crypto_pwhash_argon2i_BYTES_MAX;
  33. }
  34. size_t
  35. crypto_pwhash_argon2i_passwd_min(void)
  36. {
  37. COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
  38. return crypto_pwhash_argon2i_PASSWD_MIN;
  39. }
  40. size_t
  41. crypto_pwhash_argon2i_passwd_max(void)
  42. {
  43. COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
  44. return crypto_pwhash_argon2i_PASSWD_MAX;
  45. }
  46. size_t
  47. crypto_pwhash_argon2i_saltbytes(void)
  48. {
  49. COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
  50. COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
  51. return crypto_pwhash_argon2i_SALTBYTES;
  52. }
  53. size_t
  54. crypto_pwhash_argon2i_strbytes(void)
  55. {
  56. return crypto_pwhash_argon2i_STRBYTES;
  57. }
  58. const char*
  59. crypto_pwhash_argon2i_strprefix(void)
  60. {
  61. return crypto_pwhash_argon2i_STRPREFIX;
  62. }
  63. size_t
  64. crypto_pwhash_argon2i_opslimit_min(void)
  65. {
  66. COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
  67. return crypto_pwhash_argon2i_OPSLIMIT_MIN;
  68. }
  69. size_t
  70. crypto_pwhash_argon2i_opslimit_max(void)
  71. {
  72. COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
  73. return crypto_pwhash_argon2i_OPSLIMIT_MAX;
  74. }
  75. size_t
  76. crypto_pwhash_argon2i_memlimit_min(void)
  77. {
  78. COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
  79. return crypto_pwhash_argon2i_MEMLIMIT_MIN;
  80. }
  81. size_t
  82. crypto_pwhash_argon2i_memlimit_max(void)
  83. {
  84. COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
  85. return crypto_pwhash_argon2i_MEMLIMIT_MAX;
  86. }
  87. size_t
  88. crypto_pwhash_argon2i_opslimit_interactive(void)
  89. {
  90. return crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE;
  91. }
  92. size_t
  93. crypto_pwhash_argon2i_memlimit_interactive(void)
  94. {
  95. return crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE;
  96. }
  97. size_t
  98. crypto_pwhash_argon2i_opslimit_moderate(void)
  99. {
  100. return crypto_pwhash_argon2i_OPSLIMIT_MODERATE;
  101. }
  102. size_t
  103. crypto_pwhash_argon2i_memlimit_moderate(void)
  104. {
  105. return crypto_pwhash_argon2i_MEMLIMIT_MODERATE;
  106. }
  107. size_t
  108. crypto_pwhash_argon2i_opslimit_sensitive(void)
  109. {
  110. return crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE;
  111. }
  112. size_t
  113. crypto_pwhash_argon2i_memlimit_sensitive(void)
  114. {
  115. return crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE;
  116. }
  117. int
  118. crypto_pwhash_argon2i(unsigned char *const out, unsigned long long outlen,
  119. const char *const passwd, unsigned long long passwdlen,
  120. const unsigned char *const salt,
  121. unsigned long long opslimit, size_t memlimit, int alg)
  122. {
  123. memset(out, 0, outlen);
  124. if (outlen > crypto_pwhash_argon2i_BYTES_MAX) {
  125. errno = EFBIG;
  126. return -1;
  127. }
  128. if (outlen < crypto_pwhash_argon2i_BYTES_MIN) {
  129. errno = EINVAL;
  130. return -1;
  131. }
  132. if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
  133. opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
  134. memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
  135. errno = EFBIG;
  136. return -1;
  137. }
  138. if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
  139. opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
  140. memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
  141. errno = EINVAL;
  142. return -1;
  143. }
  144. if ((const void *) out == (const void *) passwd) {
  145. errno = EINVAL;
  146. return -1;
  147. }
  148. switch (alg) {
  149. case crypto_pwhash_argon2i_ALG_ARGON2I13:
  150. if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
  151. (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
  152. (size_t) crypto_pwhash_argon2i_SALTBYTES, out,
  153. (size_t) outlen) != ARGON2_OK) {
  154. return -1; /* LCOV_EXCL_LINE */
  155. }
  156. return 0;
  157. default:
  158. errno = EINVAL;
  159. return -1;
  160. }
  161. }
  162. int
  163. crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES],
  164. const char *const passwd,
  165. unsigned long long passwdlen,
  166. unsigned long long opslimit, size_t memlimit)
  167. {
  168. unsigned char salt[crypto_pwhash_argon2i_SALTBYTES];
  169. memset(out, 0, crypto_pwhash_argon2i_STRBYTES);
  170. if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX ||
  171. opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX ||
  172. memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) {
  173. errno = EFBIG;
  174. return -1;
  175. }
  176. if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN ||
  177. opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN ||
  178. memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) {
  179. errno = EINVAL;
  180. return -1;
  181. }
  182. randombytes_buf(salt, sizeof salt);
  183. if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
  184. (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
  185. sizeof salt, STR_HASHBYTES, out,
  186. crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) {
  187. return -1; /* LCOV_EXCL_LINE */
  188. }
  189. return 0;
  190. }
  191. int
  192. crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES],
  193. const char *const passwd,
  194. unsigned long long passwdlen)
  195. {
  196. int verify_ret;
  197. if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX) {
  198. errno = EFBIG;
  199. return -1;
  200. }
  201. /* LCOV_EXCL_START */
  202. if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN) {
  203. errno = EINVAL;
  204. return -1;
  205. }
  206. /* LCOV_EXCL_STOP */
  207. verify_ret = argon2i_verify(str, passwd, (size_t) passwdlen);
  208. if (verify_ret == ARGON2_OK) {
  209. return 0;
  210. }
  211. if (verify_ret == ARGON2_VERIFY_MISMATCH) {
  212. errno = EINVAL;
  213. }
  214. return -1;
  215. }
  216. static int
  217. _needs_rehash(const char *str, unsigned long long opslimit, size_t memlimit,
  218. argon2_type type)
  219. {
  220. unsigned char *fodder;
  221. argon2_context ctx;
  222. size_t fodder_len;
  223. int ret = -1;
  224. fodder_len = strlen(str);
  225. memlimit /= 1024U;
  226. if (opslimit > UINT32_MAX || memlimit > UINT32_MAX ||
  227. fodder_len >= crypto_pwhash_STRBYTES) {
  228. errno = EINVAL;
  229. return -1;
  230. }
  231. memset(&ctx, 0, sizeof ctx);
  232. if ((fodder = (unsigned char *) calloc(fodder_len, 1U)) == NULL) {
  233. return -1; /* LCOV_EXCL_LINE */
  234. }
  235. ctx.out = ctx.pwd = ctx.salt = fodder;
  236. ctx.outlen = ctx.pwdlen = ctx.saltlen = (uint32_t) fodder_len;
  237. ctx.ad = ctx.secret = NULL;
  238. ctx.adlen = ctx.secretlen = 0U;
  239. if (argon2_decode_string(&ctx, str, type) != 0) {
  240. errno = EINVAL;
  241. ret = -1;
  242. } else if (ctx.t_cost != (uint32_t) opslimit ||
  243. ctx.m_cost != (uint32_t) memlimit) {
  244. ret = 1;
  245. } else {
  246. ret = 0;
  247. }
  248. free(fodder);
  249. return ret;
  250. }
  251. int
  252. crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES],
  253. unsigned long long opslimit, size_t memlimit)
  254. {
  255. return _needs_rehash(str, opslimit, memlimit, Argon2_i);
  256. }
  257. int
  258. crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES],
  259. unsigned long long opslimit, size_t memlimit)
  260. {
  261. return _needs_rehash(str, opslimit, memlimit, Argon2_id);
  262. }