Sun Feb 13 13:32:03 2022 UTC ()
remove dup assignments (RVP)


(christos)
diff -r1.15 -r1.16 src/lib/libcrypt/crypt-argon2.c

cvs diff -r1.15 -r1.16 src/lib/libcrypt/crypt-argon2.c (switch to unified diff)

--- src/lib/libcrypt/crypt-argon2.c 2021/11/22 14:30:24 1.15
+++ src/lib/libcrypt/crypt-argon2.c 2022/02/13 13:32:03 1.16
@@ -1,431 +1,428 @@ @@ -1,431 +1,428 @@
1/* 1/*
2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 13 *
14 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 14 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE. 24 * POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27#include <sys/resource.h> 27#include <sys/resource.h>
28#include <sys/param.h> 28#include <sys/param.h>
29#include <sys/sysctl.h> 29#include <sys/sysctl.h>
30#include <sys/syslimits.h> 30#include <sys/syslimits.h>
31 31
32#include <stdlib.h> 32#include <stdlib.h>
33#include <stdio.h>  33#include <stdio.h>
34#include <unistd.h> 34#include <unistd.h>
35#include <stdio.h> 35#include <stdio.h>
36#include <string.h> 36#include <string.h>
37#include <time.h> 37#include <time.h>
38#include <pwd.h> 38#include <pwd.h>
39#include <errno.h> 39#include <errno.h>
40#include <argon2.h> 40#include <argon2.h>
41 41
42#include <err.h> 42#include <err.h>
43#include "crypt.h" 43#include "crypt.h"
44 44
45crypt_private int 45crypt_private int
46estimate_argon2_params(argon2_type, uint32_t *, 46estimate_argon2_params(argon2_type, uint32_t *,
47 uint32_t *, uint32_t *); 47 uint32_t *, uint32_t *);
48 48
49/* defaults pulled from run.c */ 49/* defaults pulled from run.c */
50#define HASHLEN 32 50#define HASHLEN 32
51#define T_COST_DEF 3  51#define T_COST_DEF 3
52#define LOG_M_COST_DEF 12 /* 2^12 = 4 MiB */ 52#define LOG_M_COST_DEF 12 /* 2^12 = 4 MiB */
53#define LANES_DEF 1 53#define LANES_DEF 1
54#define THREADS_DEF 1 54#define THREADS_DEF 1
55#define OUTLEN_DEF 32 55#define OUTLEN_DEF 32
56#define MAX_PASS_LEN 128 56#define MAX_PASS_LEN 128
57 57
58#define ARGON2_CONTEXT_INITIALIZER \ 58#define ARGON2_CONTEXT_INITIALIZER \
59 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 59 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
60 T_COST_DEF, LOG_M_COST_DEF,\ 60 T_COST_DEF, LOG_M_COST_DEF,\
61 LANES_DEF, THREADS_DEF, \ 61 LANES_DEF, THREADS_DEF, \
62 ARGON2_VERSION_NUMBER, 0, 0, ARGON2_DEFAULT_FLAGS} 62 ARGON2_VERSION_NUMBER, 0, 0, ARGON2_DEFAULT_FLAGS}
63 63
64#define ARGON2_ARGON2_STR "argon2" 64#define ARGON2_ARGON2_STR "argon2"
65#define ARGON2_ARGON2I_STR "argon2i" 65#define ARGON2_ARGON2I_STR "argon2i"
66#define ARGON2_ARGON2D_STR "argon2d" 66#define ARGON2_ARGON2D_STR "argon2d"
67#define ARGON2_ARGON2ID_STR "argon2id" 67#define ARGON2_ARGON2ID_STR "argon2id"
68 68
69/* 69/*
70 * Unpadded Base64 calculations are taken from the Apache2/CC-0 70 * Unpadded Base64 calculations are taken from the Apache2/CC-0
71 * licensed libargon2 for compatibility 71 * licensed libargon2 for compatibility
72 */ 72 */
73 73
74/* 74/*
75 * Some macros for constant-time comparisons. These work over values in 75 * Some macros for constant-time comparisons. These work over values in
76 * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true". 76 * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
77 */ 77 */
78#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF) 78#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
79#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF) 79#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
80#define GE(x, y) (GT(y, x) ^ 0xFF) 80#define GE(x, y) (GT(y, x) ^ 0xFF)
81#define LT(x, y) GT(y, x) 81#define LT(x, y) GT(y, x)
82#define LE(x, y) GE(y, x) 82#define LE(x, y) GE(y, x)
83 83
84static unsigned 84static unsigned
85b64_char_to_byte(int c) 85b64_char_to_byte(int c)
86{ 86{
87 unsigned x; 87 unsigned x;
88 88
89 x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) | 89 x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
90 (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) | 90 (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
91 (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) | 91 (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
92 (EQ(c, '/') & 63); 92 (EQ(c, '/') & 63);
93 return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF)); 93 return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
94} 94}
95 95
96static const char * 96static const char *
97from_base64(void *dst, size_t *dst_len, const char *src) 97from_base64(void *dst, size_t *dst_len, const char *src)
98{ 98{
99 size_t len; 99 size_t len;
100 unsigned char *buf; 100 unsigned char *buf;
101 unsigned acc, acc_len; 101 unsigned acc, acc_len;
102 102
103 buf = (unsigned char *)dst; 103 buf = (unsigned char *)dst;
104 len = 0; 104 len = 0;
105 acc = 0; 105 acc = 0;
106 acc_len = 0; 106 acc_len = 0;
107 for (;;) { 107 for (;;) {
108 unsigned d; 108 unsigned d;
109 109
110 d = b64_char_to_byte(*src); 110 d = b64_char_to_byte(*src);
111 if (d == 0xFF) { 111 if (d == 0xFF) {
112 break; 112 break;
113 } 113 }
114 src++; 114 src++;
115 acc = (acc << 6) + d; 115 acc = (acc << 6) + d;
116 acc_len += 6; 116 acc_len += 6;
117 if (acc_len >= 8) { 117 if (acc_len >= 8) {
118 acc_len -= 8; 118 acc_len -= 8;
119 if ((len++) >= *dst_len) { 119 if ((len++) >= *dst_len) {
120 return NULL; 120 return NULL;
121 } 121 }
122 *buf++ = (acc >> acc_len) & 0xFF; 122 *buf++ = (acc >> acc_len) & 0xFF;
123 } 123 }
124 } 124 }
125 125
126 /* 126 /*
127 * If the input length is equal to 1 modulo 4 (which is 127 * If the input length is equal to 1 modulo 4 (which is
128 * invalid), then there will remain 6 unprocessed bits; 128 * invalid), then there will remain 6 unprocessed bits;
129 * otherwise, only 0, 2 or 4 bits are buffered. The buffered 129 * otherwise, only 0, 2 or 4 bits are buffered. The buffered
130 * bits must also all be zero. 130 * bits must also all be zero.
131 */ 131 */
132 if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) { 132 if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
133 return NULL; 133 return NULL;
134 } 134 }
135 *dst_len = len; 135 *dst_len = len;
136 return src; 136 return src;
137} 137}
138 138
139/* 139/*
140 * Used to find default parameters that perform well on the host 140 * Used to find default parameters that perform well on the host
141 * machine. Inputs should dereference to either 0 (to estimate), 141 * machine. Inputs should dereference to either 0 (to estimate),
142 * or desired value. 142 * or desired value.
143 */ 143 */
144crypt_private int 144crypt_private int
145estimate_argon2_params(argon2_type atype, uint32_t *etime, 145estimate_argon2_params(argon2_type atype, uint32_t *etime,
146 uint32_t *ememory, uint32_t *ethreads) 146 uint32_t *ememory, uint32_t *ethreads)
147{ 147{
148 const int mib[] = { CTL_HW, HW_USERMEM64 }; 148 const int mib[] = { CTL_HW, HW_USERMEM64 };
149 struct timespec tp1, tp2, delta; 149 struct timespec tp1, tp2, delta;
150 char tmp_salt[16]; 150 char tmp_salt[16];
151 char tmp_pwd[16]; 151 char tmp_pwd[16];
152 uint32_t tmp_hash[32]; 152 uint32_t tmp_hash[32];
153 char tmp_encoded[256]; 153 char tmp_encoded[256];
154 struct rlimit rlim; 154 struct rlimit rlim;
155 uint64_t max_mem; /* usermem64 returns bytes */ 155 uint64_t max_mem; /* usermem64 returns bytes */
156 size_t max_mem_sz = sizeof(max_mem); 156 size_t max_mem_sz = sizeof(max_mem);
157 /* low values from argon2 test suite... */ 157 /* low values from argon2 test suite... */
158 uint32_t memory = 256; /* 256k; argon2 wants kilobytes */ 158 uint32_t memory = 256; /* 256k; argon2 wants kilobytes */
159 uint32_t time = 3; 159 uint32_t time = 3;
160 uint32_t threads = 1; 160 uint32_t threads = 1;
161 161
162 if (*ememory < ARGON2_MIN_MEMORY) { 162 if (*ememory < ARGON2_MIN_MEMORY) {
163 /* 163 /*
164 * attempt to find a reasonble bound for memory use 164 * attempt to find a reasonble bound for memory use
165 */ 165 */
166 if (sysctl(mib, __arraycount(mib), 166 if (sysctl(mib, __arraycount(mib),
167 &max_mem, &max_mem_sz, NULL, 0) < 0) { 167 &max_mem, &max_mem_sz, NULL, 0) < 0) {
168 goto error; 168 goto error;
169 } 169 }
170 if (getrlimit(RLIMIT_AS, &rlim) < 0) 170 if (getrlimit(RLIMIT_AS, &rlim) < 0)
171 goto error; 171 goto error;
172 if (max_mem > rlim.rlim_cur && rlim.rlim_cur != RLIM_INFINITY) 172 if (max_mem > rlim.rlim_cur && rlim.rlim_cur != RLIM_INFINITY)
173 max_mem = rlim.rlim_cur; 173 max_mem = rlim.rlim_cur;
174 174
175 /* 175 /*
176 * Note that adding memory also greatly slows the algorithm. 176 * Note that adding memory also greatly slows the algorithm.
177 * Do we need to be concerned about memory usage during 177 * Do we need to be concerned about memory usage during
178 * concurrent connections? 178 * concurrent connections?
179 */ 179 */
180 max_mem /= 1000000; /* bytes down to mb */ 180 max_mem /= 1000000; /* bytes down to mb */
181 if (max_mem > 30000) { 181 if (max_mem > 30000) {
182 memory = 32768; 182 memory = 32768;
183 } else if (max_mem > 15000) { 183 } else if (max_mem > 15000) {
184 memory = 16384; 184 memory = 16384;
185 } else if (max_mem > 7000) { 185 } else if (max_mem > 7000) {
186 memory = 8192; 186 memory = 8192;
187 } else if (max_mem > 3000) { 187 } else if (max_mem > 3000) {
188 memory = 4096; 188 memory = 4096;
189 } else if (max_mem > 900) { 189 } else if (max_mem > 900) {
190 memory = 1024; 190 memory = 1024;
191 } else if (max_mem > 24) { 191 } else if (max_mem > 24) {
192 memory = 256; 192 memory = 256;
193 } else { 193 } else {
194 memory = ARGON2_MIN_MEMORY; 194 memory = ARGON2_MIN_MEMORY;
195 } 195 }
196 } else { 196 } else {
197 memory = *ememory; 197 memory = *ememory;
198 } 198 }
199 199
200 if (*etime < ARGON2_MIN_TIME) { 200 if (*etime < ARGON2_MIN_TIME) {
201 /* 201 /*
202 * just fill these with random stuff since we'll immediately 202 * just fill these with random stuff since we'll immediately
203 * discard them after calculating hashes for 1 second 203 * discard them after calculating hashes for 1 second
204 */ 204 */
205 arc4random_buf(tmp_pwd, sizeof(tmp_pwd)); 205 arc4random_buf(tmp_pwd, sizeof(tmp_pwd));
206 arc4random_buf(tmp_salt, sizeof(tmp_salt)); 206 arc4random_buf(tmp_salt, sizeof(tmp_salt));
207 207
208 if (clock_gettime(CLOCK_MONOTONIC, &tp1) == -1) 208 if (clock_gettime(CLOCK_MONOTONIC, &tp1) == -1)
209 goto error; 209 goto error;
210 for (; delta.tv_sec < 1 && time < ARGON2_MAX_TIME; ++time) { 210 for (; delta.tv_sec < 1 && time < ARGON2_MAX_TIME; ++time) {
211 if (argon2_hash(time, memory, threads, 211 if (argon2_hash(time, memory, threads,
212 tmp_pwd, sizeof(tmp_pwd),  212 tmp_pwd, sizeof(tmp_pwd),
213 tmp_salt, sizeof(tmp_salt),  213 tmp_salt, sizeof(tmp_salt),
214 tmp_hash, sizeof(tmp_hash),  214 tmp_hash, sizeof(tmp_hash),
215 tmp_encoded, sizeof(tmp_encoded),  215 tmp_encoded, sizeof(tmp_encoded),
216 atype, ARGON2_VERSION_NUMBER) != ARGON2_OK) { 216 atype, ARGON2_VERSION_NUMBER) != ARGON2_OK) {
217 goto reset; 217 goto reset;
218 } 218 }
219 if (clock_gettime(CLOCK_MONOTONIC, &tp2) == -1) 219 if (clock_gettime(CLOCK_MONOTONIC, &tp2) == -1)
220 break; 220 break;
221 if (timespeccmp(&tp1, &tp2, >)) 221 if (timespeccmp(&tp1, &tp2, >))
222 break; /* broken system... */ 222 break; /* broken system... */
223 timespecsub(&tp2, &tp1, &delta); 223 timespecsub(&tp2, &tp1, &delta);
224 } 224 }
225 } else { 225 } else {
226 time = *etime; 226 time = *etime;
227 } 227 }
228 228
229error: 229error:
230 *etime = time; 230 *etime = time;
231 *ememory = memory; 231 *ememory = memory;
232 *ethreads = threads; 232 *ethreads = threads;
233 return 0; 233 return 0;
234reset: 234reset:
235 time = 3; 235 time = 3;
236 memory = 256; 236 memory = 256;
237 threads = 1; 237 threads = 1;
238 goto error; 238 goto error;
239} 239}
240 240
241 241
242/* process params to argon2 */ 242/* process params to argon2 */
243/* we don't force param order as input, */ 243/* we don't force param order as input, */
244/* but we do provide the expected order to argon2 api */ 244/* but we do provide the expected order to argon2 api */
245static int 245static int
246decode_option(argon2_context *ctx, argon2_type *atype, const char *option)  246decode_option(argon2_context *ctx, argon2_type *atype, const char *option)
247{ 247{
248 size_t tmp = 0; 248 size_t tmp = 0;
249 char *in = 0, *inp; 249 char *in = 0, *inp;
250 char *a = 0; 250 char *a = 0;
251 char *p = 0; 251 char *p = 0;
252 size_t sl; 252 size_t sl;
253 int error = 0; 253 int error = 0;
254 254
255 in = (char *)strdup(option); 255 in = (char *)strdup(option);
256 inp = in; 256 inp = in;
257 257
258 if (*inp == '$') inp++; 258 if (*inp == '$') inp++;
259 259
260 a = strsep(&inp, "$"); 260 a = strsep(&inp, "$");
261 261
262 sl = strlen(a); 262 sl = strlen(a);
263 263
264 if (sl == strlen(ARGON2_ARGON2I_STR) &&  264 if (sl == strlen(ARGON2_ARGON2I_STR) &&
265 !(strcmp(ARGON2_ARGON2I_STR, a))) { 265 !(strcmp(ARGON2_ARGON2I_STR, a))) {
266 *atype=Argon2_i; 266 *atype=Argon2_i;
267 } else if (sl == strlen(ARGON2_ARGON2D_STR) &&  267 } else if (sl == strlen(ARGON2_ARGON2D_STR) &&
268 !(strcmp(ARGON2_ARGON2D_STR, a))) { 268 !(strcmp(ARGON2_ARGON2D_STR, a))) {
269 *atype=Argon2_d; 269 *atype=Argon2_d;
270 } 270 }
271 else if (sl == strlen(ARGON2_ARGON2ID_STR) &&  271 else if (sl == strlen(ARGON2_ARGON2ID_STR) &&
272 !(strcmp(ARGON2_ARGON2ID_STR, a))) { 272 !(strcmp(ARGON2_ARGON2ID_STR, a))) {
273 *atype=Argon2_id; 273 *atype=Argon2_id;
274 } else { /* default to id, we assume simple mistake */ 274 } else { /* default to id, we assume simple mistake */
275 /* don't abandon yet */ 275 /* don't abandon yet */
276 *atype=Argon2_id; 276 *atype=Argon2_id;
277 } 277 }
278 278
279 a = strsep(&inp, "$"); 279 a = strsep(&inp, "$");
280 280
281 /* parse the version number of the hash, if it's there */ 281 /* parse the version number of the hash, if it's there */
282 if (strncmp(a, "v=", 2) == 0) { 282 if (strncmp(a, "v=", 2) == 0) {
283 a += 2; 283 a += 2;
284 if ((getnum(a, &tmp))<0) { /* on error, default to current */ 284 if ((getnum(a, &tmp))<0) { /* on error, default to current */
285 /* should start thinking about aborting */ 285 /* should start thinking about aborting */
286 ctx->version = ARGON2_VERSION_10; 286 ctx->version = ARGON2_VERSION_10;
287 } else { 287 } else {
288 ctx->version = tmp; 288 ctx->version = tmp;
289 } 289 }
290 a = strsep(&inp, "$"); 290 a = strsep(&inp, "$");
291 } else { 291 } else {
292 /* 292 /*
293 * This is a parameter list, not a version number, use the 293 * This is a parameter list, not a version number, use the
294 * default version. 294 * default version.
295 */ 295 */
296 ctx->version = ARGON2_VERSION_10; 296 ctx->version = ARGON2_VERSION_10;
297 } 297 }
298 298
299 /* parse labelled argon2 params */ 299 /* parse labelled argon2 params */
300 /* m_cost (m) 300 /* m_cost (m)
301 * t_cost (t) 301 * t_cost (t)
302 * threads (p) 302 * threads (p)
303 */ 303 */
304 while ((p = strsep(&a, ","))) { 304 while ((p = strsep(&a, ","))) {
305 switch (*p) { 305 switch (*p) {
306 case 'm': 306 case 'm':
307 p += strlen("m="); 307 p += strlen("m=");
308 if ((getnum(p, &tmp)) < 0) { 308 if ((getnum(p, &tmp)) < 0) {
309 --error; 309 --error;
310 } else { 310 } else {
311 ctx->m_cost = tmp; 311 ctx->m_cost = tmp;
312 } 312 }
313 break; 313 break;
314 case 't': 314 case 't':
315 p += strlen("t="); 315 p += strlen("t=");
316 if ((getnum(p, &tmp)) < 0) { 316 if ((getnum(p, &tmp)) < 0) {
317 --error; 317 --error;
318 } else { 318 } else {
319 ctx->t_cost = tmp; 319 ctx->t_cost = tmp;
320 } 320 }
321 break; 321 break;
322 case 'p': 322 case 'p':
323 p += strlen("p="); 323 p += strlen("p=");
324 if ((getnum(p, &tmp)) < 0) { 324 if ((getnum(p, &tmp)) < 0) {
325 --error; 325 --error;
326 } else { 326 } else {
327 ctx->threads = tmp; 327 ctx->threads = tmp;
328 } 328 }
329 break; 329 break;
330 default: 330 default:
331 return -1; 331 return -1;
332 332
333 } 333 }
334 } 334 }
335 335
336 a = strsep(&inp, "$"); 336 a = strsep(&inp, "$");
337 337
338 sl = ctx->saltlen; 338 sl = ctx->saltlen;
339 339
340 if (from_base64(ctx->salt, &sl, a) == NULL) 340 if (from_base64(ctx->salt, &sl, a) == NULL)
341 return -1; 341 return -1;
342 342
343 ctx->saltlen = sl; 343 ctx->saltlen = sl;
344 344
345 a = strsep(&inp, "$"); 345 a = strsep(&inp, "$");
346 346
347 if (a) { 347 if (a) {
348 snprintf((char *)ctx->pwd, ctx->pwdlen, "%s", a); 348 snprintf((char *)ctx->pwd, ctx->pwdlen, "%s", a);
349 } else { 349 } else {
350 /* don't care if passwd hash is missing */ 350 /* don't care if passwd hash is missing */
351 /* if missing, most likely coming from */ 351 /* if missing, most likely coming from */
352 /* pwhash or similar */  352 /* pwhash or similar */
353 } 353 }
354 354
355 /* free our token buffer */ 355 /* free our token buffer */
356 free(in); 356 free(in);
357 357
358 /* 0 on success, <0 otherwise */ 358 /* 0 on success, <0 otherwise */
359 return error; 359 return error;
360} 360}
361 361
362crypt_private char *  362crypt_private char *
363__crypt_argon2(const char *pw, const char * salt) 363__crypt_argon2(const char *pw, const char * salt)
364{ 364{
365 /* we use the libargon2 api to generate */ 365 /* we use the libargon2 api to generate */
366 /* return code */ 366 /* return code */
367 int rc = 0; 367 int rc = 0;
368 /* output buffer */ 368 /* output buffer */
369 char ebuf[32]; 369 char ebuf[32];
370 /* argon2 variable, default to id */ 370 /* argon2 variable, default to id */
371 argon2_type atype = Argon2_id; 371 argon2_type atype = Argon2_id;
372 /* default to current argon2 version */ 372 /* default to current argon2 version */
373 /* argon2 context to collect params */ 373 /* argon2 context to collect params */
374 argon2_context ctx = ARGON2_CONTEXT_INITIALIZER; 374 argon2_context ctx = ARGON2_CONTEXT_INITIALIZER;
375 /* argon2 encoded buffer */ 375 /* argon2 encoded buffer */
376 char encodebuf[256]; 376 char encodebuf[256];
377 /* argon2 salt buffer */ 377 /* argon2 salt buffer */
378 char saltbuf[128]; 378 char saltbuf[128];
379 /* argon2 pwd buffer */ 379 /* argon2 pwd buffer */
380 char pwdbuf[128]; 380 char pwdbuf[128];
381 /* returned static buffer */ 381 /* returned static buffer */
382 static char rbuf[512]; 382 static char rbuf[512];
383 383
384 /* clear buffers */ 384 /* clear buffers */
385 explicit_memset(rbuf, 0, sizeof(rbuf)); 385 explicit_memset(rbuf, 0, sizeof(rbuf));
386 386
387 /* we use static buffers to avoid allocation */ 387 /* we use static buffers to avoid allocation */
388 /* and easier cleanup */ 388 /* and easier cleanup */
389 ctx.out = (uint8_t *)ebuf; 
390 ctx.outlen = sizeof(ebuf); 
391 
392 ctx.out = (uint8_t *)encodebuf; 389 ctx.out = (uint8_t *)encodebuf;
393 ctx.outlen = sizeof(encodebuf); 390 ctx.outlen = sizeof(encodebuf);
394 391
395 ctx.salt = (uint8_t *)saltbuf; 392 ctx.salt = (uint8_t *)saltbuf;
396 ctx.saltlen = sizeof(saltbuf); 393 ctx.saltlen = sizeof(saltbuf);
397 394
398 ctx.pwd = (uint8_t *)pwdbuf; 395 ctx.pwd = (uint8_t *)pwdbuf;
399 ctx.pwdlen = sizeof(pwdbuf); 396 ctx.pwdlen = sizeof(pwdbuf);
400 397
401 /* decode salt string to argon2 params */ 398 /* decode salt string to argon2 params */
402 /* argon2 context for param collection */ 399 /* argon2 context for param collection */
403 rc = decode_option(&ctx, &atype, salt); 400 rc = decode_option(&ctx, &atype, salt);
404 401
405 if (rc < 0) { 402 if (rc < 0) {
406 /* unable to parse input params */ 403 /* unable to parse input params */
407 return NULL; 404 return NULL;
408 } 405 }
409 406
410 rc = argon2_hash(ctx.t_cost, ctx.m_cost, 407 rc = argon2_hash(ctx.t_cost, ctx.m_cost,
411 ctx.threads, pw, strlen(pw), ctx.salt, ctx.saltlen, 408 ctx.threads, pw, strlen(pw), ctx.salt, ctx.saltlen,
412 ebuf, sizeof(ebuf), encodebuf, sizeof(encodebuf), 409 ebuf, sizeof(ebuf), encodebuf, sizeof(encodebuf),
413 atype, ctx.version); 410 atype, ctx.version);
414 411
415 if (rc != ARGON2_OK) { 412 if (rc != ARGON2_OK) {
416 fprintf(stderr, "argon2: failed: %s\n", 413 fprintf(stderr, "argon2: failed: %s\n",
417 argon2_error_message(rc)); 414 argon2_error_message(rc));
418 return NULL; 415 return NULL;
419 } 416 }
420 417
421 memcpy(rbuf, encodebuf, sizeof(encodebuf)); 418 memcpy(rbuf, encodebuf, sizeof(encodebuf));
422 419
423 /* clear buffers */ 420 /* clear buffers */
424 explicit_memset(ebuf, 0, sizeof(ebuf)); 421 explicit_memset(ebuf, 0, sizeof(ebuf));
425 explicit_memset(encodebuf, 0, sizeof(encodebuf)); 422 explicit_memset(encodebuf, 0, sizeof(encodebuf));
426 explicit_memset(saltbuf, 0, sizeof(saltbuf)); 423 explicit_memset(saltbuf, 0, sizeof(saltbuf));
427 explicit_memset(pwdbuf, 0, sizeof(pwdbuf)); 424 explicit_memset(pwdbuf, 0, sizeof(pwdbuf));
428 425
429 /* return encoded str */ 426 /* return encoded str */
430 return rbuf; 427 return rbuf;
431} 428}