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