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