1
2 #include <errno.h>
3 #include <limits.h>
4 #include <stddef.h>
5 #include <stdint.h>
6 #include <string.h>
7
8 #include "argon2-core.h"
9 #include "argon2.h"
10 #include "crypto_pwhash_argon2id.h"
11 #include "private/common.h"
12 #include "randombytes.h"
13 #include "utils.h"
14
15 #define STR_HASHBYTES 32U
16
17 int
crypto_pwhash_argon2id_alg_argon2id13(void)18 crypto_pwhash_argon2id_alg_argon2id13(void)
19 {
20 return crypto_pwhash_argon2id_ALG_ARGON2ID13;
21 }
22
23 size_t
crypto_pwhash_argon2id_bytes_min(void)24 crypto_pwhash_argon2id_bytes_min(void)
25 {
26 COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MIN >= ARGON2_MIN_OUTLEN);
27 return crypto_pwhash_argon2id_BYTES_MIN;
28 }
29
30 size_t
crypto_pwhash_argon2id_bytes_max(void)31 crypto_pwhash_argon2id_bytes_max(void)
32 {
33 COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MAX <= ARGON2_MAX_OUTLEN);
34 return crypto_pwhash_argon2id_BYTES_MAX;
35 }
36
37 size_t
crypto_pwhash_argon2id_passwd_min(void)38 crypto_pwhash_argon2id_passwd_min(void)
39 {
40 COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH);
41 return crypto_pwhash_argon2id_PASSWD_MIN;
42 }
43
44 size_t
crypto_pwhash_argon2id_passwd_max(void)45 crypto_pwhash_argon2id_passwd_max(void)
46 {
47 COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH);
48 return crypto_pwhash_argon2id_PASSWD_MAX;
49 }
50
51 size_t
crypto_pwhash_argon2id_saltbytes(void)52 crypto_pwhash_argon2id_saltbytes(void)
53 {
54 COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES >= ARGON2_MIN_SALT_LENGTH);
55 COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES <= ARGON2_MAX_SALT_LENGTH);
56 return crypto_pwhash_argon2id_SALTBYTES;
57 }
58
59 size_t
crypto_pwhash_argon2id_strbytes(void)60 crypto_pwhash_argon2id_strbytes(void)
61 {
62 return crypto_pwhash_argon2id_STRBYTES;
63 }
64
65 const char*
crypto_pwhash_argon2id_strprefix(void)66 crypto_pwhash_argon2id_strprefix(void)
67 {
68 return crypto_pwhash_argon2id_STRPREFIX;
69 }
70
71 size_t
crypto_pwhash_argon2id_opslimit_min(void)72 crypto_pwhash_argon2id_opslimit_min(void)
73 {
74 COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MIN >= ARGON2_MIN_TIME);
75 return crypto_pwhash_argon2id_OPSLIMIT_MIN;
76 }
77
78 size_t
crypto_pwhash_argon2id_opslimit_max(void)79 crypto_pwhash_argon2id_opslimit_max(void)
80 {
81 COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MAX <= ARGON2_MAX_TIME);
82 return crypto_pwhash_argon2id_OPSLIMIT_MAX;
83 }
84
85 size_t
crypto_pwhash_argon2id_memlimit_min(void)86 crypto_pwhash_argon2id_memlimit_min(void)
87 {
88 COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY);
89 return crypto_pwhash_argon2id_MEMLIMIT_MIN;
90 }
91
92 size_t
crypto_pwhash_argon2id_memlimit_max(void)93 crypto_pwhash_argon2id_memlimit_max(void)
94 {
95 COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY);
96 return crypto_pwhash_argon2id_MEMLIMIT_MAX;
97 }
98
99 size_t
crypto_pwhash_argon2id_opslimit_interactive(void)100 crypto_pwhash_argon2id_opslimit_interactive(void)
101 {
102 return crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE;
103 }
104
105 size_t
crypto_pwhash_argon2id_memlimit_interactive(void)106 crypto_pwhash_argon2id_memlimit_interactive(void)
107 {
108 return crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE;
109 }
110
111 size_t
crypto_pwhash_argon2id_opslimit_moderate(void)112 crypto_pwhash_argon2id_opslimit_moderate(void)
113 {
114 return crypto_pwhash_argon2id_OPSLIMIT_MODERATE;
115 }
116
117 size_t
crypto_pwhash_argon2id_memlimit_moderate(void)118 crypto_pwhash_argon2id_memlimit_moderate(void)
119 {
120 return crypto_pwhash_argon2id_MEMLIMIT_MODERATE;
121 }
122
123 size_t
crypto_pwhash_argon2id_opslimit_sensitive(void)124 crypto_pwhash_argon2id_opslimit_sensitive(void)
125 {
126 return crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE;
127 }
128
129 size_t
crypto_pwhash_argon2id_memlimit_sensitive(void)130 crypto_pwhash_argon2id_memlimit_sensitive(void)
131 {
132 return crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE;
133 }
134
135 int
crypto_pwhash_argon2id(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)136 crypto_pwhash_argon2id(unsigned char *const out, unsigned long long outlen,
137 const char *const passwd, unsigned long long passwdlen,
138 const unsigned char *const salt,
139 unsigned long long opslimit, size_t memlimit, int alg)
140 {
141 memset(out, 0, outlen);
142 if (outlen > crypto_pwhash_argon2id_BYTES_MAX) {
143 errno = EFBIG;
144 return -1;
145 }
146 if (outlen < crypto_pwhash_argon2id_BYTES_MIN) {
147 errno = EINVAL;
148 return -1;
149 }
150 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
151 opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
152 memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
153 errno = EFBIG;
154 return -1;
155 }
156 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
157 opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
158 memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
159 errno = EINVAL;
160 return -1;
161 }
162 if ((const void *) out == (const void *) passwd) {
163 errno = EINVAL;
164 return -1;
165 }
166 switch (alg) {
167 case crypto_pwhash_argon2id_ALG_ARGON2ID13:
168 if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
169 (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
170 (size_t) crypto_pwhash_argon2id_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_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES],const char * const passwd,unsigned long long passwdlen,unsigned long long opslimit,size_t memlimit)182 crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_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_argon2id_SALTBYTES];
188
189 memset(out, 0, crypto_pwhash_argon2id_STRBYTES);
190 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
191 opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
192 memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
193 errno = EFBIG;
194 return -1;
195 }
196 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
197 opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
198 memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
199 errno = EINVAL;
200 return -1;
201 }
202 randombytes_buf(salt, sizeof salt);
203 if (argon2id_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_argon2id_STRBYTES) != ARGON2_OK) {
207 return -1; /* LCOV_EXCL_LINE */
208 }
209 return 0;
210 }
211
212 int
crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],const char * const passwd,unsigned long long passwdlen)213 crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],
214 const char *const passwd,
215 unsigned long long passwdlen)
216 {
217 int verify_ret;
218
219 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX) {
220 errno = EFBIG;
221 return -1;
222 }
223 /* LCOV_EXCL_START */
224 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN) {
225 errno = EINVAL;
226 return -1;
227 }
228 /* LCOV_EXCL_STOP */
229
230 verify_ret = argon2id_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