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 switch (alg) {
163 case crypto_pwhash_argon2id_ALG_ARGON2ID13:
164 if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
165 (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
166 (size_t) crypto_pwhash_argon2id_SALTBYTES, out,
167 (size_t) outlen) != ARGON2_OK) {
168 return -1; /* LCOV_EXCL_LINE */
169 }
170 return 0;
171 default:
172 errno = EINVAL;
173 return -1;
174 }
175 }
176
177 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)178 crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES],
179 const char *const passwd,
180 unsigned long long passwdlen,
181 unsigned long long opslimit, size_t memlimit)
182 {
183 unsigned char salt[crypto_pwhash_argon2id_SALTBYTES];
184
185 memset(out, 0, crypto_pwhash_argon2id_STRBYTES);
186 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX ||
187 opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX ||
188 memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) {
189 errno = EFBIG;
190 return -1;
191 }
192 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN ||
193 opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN ||
194 memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) {
195 errno = EINVAL;
196 return -1;
197 }
198 randombytes_buf(salt, sizeof salt);
199 if (argon2id_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U),
200 (uint32_t) 1U, passwd, (size_t) passwdlen, salt,
201 sizeof salt, STR_HASHBYTES, out,
202 crypto_pwhash_argon2id_STRBYTES) != ARGON2_OK) {
203 return -1; /* LCOV_EXCL_LINE */
204 }
205 return 0;
206 }
207
208 int
crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],const char * const passwd,unsigned long long passwdlen)209 crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES],
210 const char *const passwd,
211 unsigned long long passwdlen)
212 {
213 int verify_ret;
214
215 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX) {
216 errno = EFBIG;
217 return -1;
218 }
219 /* LCOV_EXCL_START */
220 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN) {
221 errno = EINVAL;
222 return -1;
223 }
224 /* LCOV_EXCL_STOP */
225
226 verify_ret = argon2id_verify(str, passwd, (size_t) passwdlen);
227 if (verify_ret == ARGON2_OK) {
228 return 0;
229 }
230 if (verify_ret == ARGON2_VERIFY_MISMATCH) {
231 errno = EINVAL;
232 }
233 return -1;
234 }
235