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 (; 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 if (delta.tv_sec >= 1) 225 break; 226 } 227 } else { 228 time = *etime; 229 } 230 231 error: 232 *etime = time; 233 *ememory = memory; 234 *ethreads = threads; 235 return 0; 236 reset: 237 time = 3; 238 memory = 256; 239 threads = 1; 240 goto error; 241 } 242 243 244 /* process params to argon2 */ 245 /* we don't force param order as input, */ 246 /* but we do provide the expected order to argon2 api */ 247 static int 248 decode_option(argon2_context *ctx, argon2_type *atype, const char *option) 249 { 250 size_t tmp = 0; 251 char *in = 0, *inp; 252 char *a = 0; 253 char *p = 0; 254 size_t sl; 255 int error = 0; 256 257 in = (char *)strdup(option); 258 inp = in; 259 260 if (*inp == '$') inp++; 261 262 a = strsep(&inp, "$"); 263 264 sl = strlen(a); 265 266 if (sl == strlen(ARGON2_ARGON2I_STR) && 267 !(strcmp(ARGON2_ARGON2I_STR, a))) { 268 *atype=Argon2_i; 269 } else if (sl == strlen(ARGON2_ARGON2D_STR) && 270 !(strcmp(ARGON2_ARGON2D_STR, a))) { 271 *atype=Argon2_d; 272 } 273 else if (sl == strlen(ARGON2_ARGON2ID_STR) && 274 !(strcmp(ARGON2_ARGON2ID_STR, a))) { 275 *atype=Argon2_id; 276 } else { /* default to id, we assume simple mistake */ 277 /* don't abandon yet */ 278 *atype=Argon2_id; 279 } 280 281 a = strsep(&inp, "$"); 282 283 /* parse the version number of the hash, if it's there */ 284 if (strncmp(a, "v=", 2) == 0) { 285 a += 2; 286 if ((getnum(a, &tmp))<0) { /* on error, default to current */ 287 /* should start thinking about aborting */ 288 ctx->version = ARGON2_VERSION_10; 289 } else { 290 ctx->version = tmp; 291 } 292 a = strsep(&inp, "$"); 293 } else { 294 /* 295 * This is a parameter list, not a version number, use the 296 * default version. 297 */ 298 ctx->version = ARGON2_VERSION_10; 299 } 300 301 /* parse labelled argon2 params */ 302 /* m_cost (m) 303 * t_cost (t) 304 * threads (p) 305 */ 306 while ((p = strsep(&a, ","))) { 307 switch (*p) { 308 case 'm': 309 p += strlen("m="); 310 if ((getnum(p, &tmp)) < 0) { 311 --error; 312 } else { 313 ctx->m_cost = tmp; 314 } 315 break; 316 case 't': 317 p += strlen("t="); 318 if ((getnum(p, &tmp)) < 0) { 319 --error; 320 } else { 321 ctx->t_cost = tmp; 322 } 323 break; 324 case 'p': 325 p += strlen("p="); 326 if ((getnum(p, &tmp)) < 0) { 327 --error; 328 } else { 329 ctx->threads = tmp; 330 } 331 break; 332 default: 333 free(in); 334 return -1; 335 336 } 337 } 338 339 a = strsep(&inp, "$"); 340 if (a == NULL) { 341 free(in); 342 return -1; 343 } 344 345 sl = ctx->saltlen; 346 347 if (from_base64(ctx->salt, &sl, a) == NULL) { 348 free(in); 349 return -1; 350 } 351 352 ctx->saltlen = sl; 353 354 a = strsep(&inp, "$"); 355 356 if (a) { 357 snprintf((char *)ctx->pwd, ctx->pwdlen, "%s", a); 358 } else { 359 /* don't care if passwd hash is missing */ 360 /* if missing, most likely coming from */ 361 /* pwhash or similar */ 362 } 363 364 /* free our token buffer */ 365 free(in); 366 367 /* 0 on success, <0 otherwise */ 368 return error; 369 } 370 371 crypt_private char * 372 __crypt_argon2(const char *pw, const char * salt) 373 { 374 /* we use the libargon2 api to generate */ 375 /* return code */ 376 int rc = 0; 377 /* output buffer */ 378 char ebuf[32]; 379 /* argon2 variable, default to id */ 380 argon2_type atype = Argon2_id; 381 /* default to current argon2 version */ 382 /* argon2 context to collect params */ 383 argon2_context ctx = ARGON2_CONTEXT_INITIALIZER; 384 /* argon2 encoded buffer */ 385 char encodebuf[256]; 386 /* argon2 salt buffer */ 387 char saltbuf[128]; 388 /* argon2 pwd buffer */ 389 char pwdbuf[128]; 390 /* returned static buffer */ 391 static char rbuf[512]; 392 393 /* clear buffers */ 394 explicit_memset(rbuf, 0, sizeof(rbuf)); 395 396 /* we use static buffers to avoid allocation */ 397 /* and easier cleanup */ 398 ctx.out = (uint8_t *)encodebuf; 399 ctx.outlen = sizeof(encodebuf); 400 401 ctx.salt = (uint8_t *)saltbuf; 402 ctx.saltlen = sizeof(saltbuf); 403 404 ctx.pwd = (uint8_t *)pwdbuf; 405 ctx.pwdlen = sizeof(pwdbuf); 406 407 /* decode salt string to argon2 params */ 408 /* argon2 context for param collection */ 409 rc = decode_option(&ctx, &atype, salt); 410 411 if (rc < 0) { 412 /* unable to parse input params */ 413 return NULL; 414 } 415 416 rc = argon2_hash(ctx.t_cost, ctx.m_cost, 417 ctx.threads, pw, strlen(pw), ctx.salt, ctx.saltlen, 418 ebuf, sizeof(ebuf), encodebuf, sizeof(encodebuf), 419 atype, ctx.version); 420 421 if (rc != ARGON2_OK) { 422 fprintf(stderr, "argon2: failed: %s\n", 423 argon2_error_message(rc)); 424 return NULL; 425 } 426 427 memcpy(rbuf, encodebuf, sizeof(encodebuf)); 428 429 /* clear buffers */ 430 explicit_memset(ebuf, 0, sizeof(ebuf)); 431 explicit_memset(encodebuf, 0, sizeof(encodebuf)); 432 explicit_memset(saltbuf, 0, sizeof(saltbuf)); 433 explicit_memset(pwdbuf, 0, sizeof(pwdbuf)); 434 435 /* return encoded str */ 436 return rbuf; 437 } 438