This patch adds an "argon2id" password-based key generation method to cgdconfig(8).
To support Argon2, several new keygen parameters are supported in cgd parameters files: memory (integer, in kilobytes) parallelism (integer, usually the number of CPU cores) version (integer, usually 19...) time, memory, and parallelism will automatically scale. libargon2 is linked as a private library. libpthread is also required, in order to support parallel key generation. Testing: # cgdconfig -g -k argon2id adiantum > paramsfile algorithm adiantum; iv-method encblkno1; keylength 256; verify_method none; keygen argon2id { iterations 7; memory 82532; parallelism 4; version 19; salt AAAAgOfESMuR2OVia9wR2Q5UnYY=; }; # dd if=/dev/zero of=./testdisk bs=1m count=1000 # vndconfig -c vnd0 ./testdisk # cgdconfig -V re-enter cgd0 /dev/vnd0 ./paramsfile # newfs /dev/cgd1 # ...
Index: lib/Makefile =================================================================== RCS file: /cvsroot/src/lib/Makefile,v retrieving revision 1.292 diff -u -r1.292 Makefile --- lib/Makefile 25 Apr 2021 23:43:48 -0000 1.292 +++ lib/Makefile 5 Nov 2021 15:41:41 -0000 @@ -54,6 +54,10 @@ SUBDIR+= libnvmm .endif +.if (${MKARGON2} != "no") +SUBDIR+= ../external/apache2/argon2/lib/libargon2 +.endif + .if (${MKMDNS} != "no") SUBDIR+= ../external/apache2/mDNSResponder/lib .endif Index: external/apache2/Makefile =================================================================== RCS file: /cvsroot/src/external/apache2/Makefile,v retrieving revision 1.4 diff -u -r1.4 Makefile --- external/apache2/Makefile 12 Oct 2021 17:24:36 -0000 1.4 +++ external/apache2/Makefile 5 Nov 2021 15:41:41 -0000 @@ -2,6 +2,10 @@ .include <bsd.own.mk> +.if (${MKARGON2} != "no") +SUBDIR+= argon2 +.endif + .if (${MKLLVM} != "no" || ${MKLLVMRT} != "no") SUBDIR+= llvm .endif Index: external/apache2/argon2/Makefile =================================================================== RCS file: external/apache2/argon2/Makefile diff -N external/apache2/argon2/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ external/apache2/argon2/Makefile 5 Nov 2021 15:41:41 -0000 @@ -0,0 +1,7 @@ +# $NetBSD$ + +.include <bsd.own.mk> + +SUBDIR= lib + +.include <bsd.subdir.mk> Index: external/apache2/argon2/lib/Makefile =================================================================== RCS file: /cvsroot/src/external/apache2/argon2/lib/Attic/Makefile,v retrieving revision 1.1 diff -u -r1.1 Makefile --- external/apache2/argon2/lib/Makefile 9 Oct 2019 13:13:09 -0000 1.1 +++ external/apache2/argon2/lib/Makefile 5 Nov 2021 15:41:41 -0000 @@ -1,3 +1,5 @@ +# $NetBSD$ + SUBDIR= libargon2 .include <bsd.subdir.mk> Index: external/apache2/argon2/lib/libargon2/Makefile =================================================================== RCS file: external/apache2/argon2/lib/libargon2/Makefile diff -N external/apache2/argon2/lib/libargon2/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ external/apache2/argon2/lib/libargon2/Makefile 5 Nov 2021 15:41:41 -0000 @@ -0,0 +1,23 @@ +# $NetBSD$ + +LIBISPRIVATE= pic + +.include <bsd.own.mk> + +ARGON2DIR= ${NETBSDSRCDIR}/external/apache2/argon2 + +.PATH: ${ARGON2DIR}/dist/phc-winner-argon2/src \ + ${ARGON2DIR}/dist/phc-winner-argon2/src/blake2 \ + ${ARGON2DIR}/dist/phc-winner-argon2/include + +LIB= argon2 +SRCS= argon2.c core.c blake2b.c thread.c encoding.c ref.c + +CFLAGS+= -pthread +CPPFLAGS+= -I${ARGON2DIR}/dist/phc-winner-argon2/include + +.if ${MACHINE} == "vax" +COPTS.blake2b.c+= -O0 +.endif + +.include <bsd.lib.mk> Index: sbin/cgdconfig/Makefile =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/Makefile,v retrieving revision 1.15 diff -u -r1.15 Makefile --- sbin/cgdconfig/Makefile 1 Jul 2016 22:50:09 -0000 1.15 +++ sbin/cgdconfig/Makefile 5 Nov 2021 15:41:43 -0000 @@ -3,6 +3,8 @@ RUMPPRG=cgdconfig MAN= cgdconfig.8 +.include <bsd.own.mk> + SRCS+= cgdconfig.c \ cgdlex.l \ cgdparse.y \ @@ -10,6 +12,10 @@ params.c \ utils.c +.if ${MKARGON2} != "no" +SRCS+= argon2_utils.c +.endif + CPPFLAGS+= -I${.CURDIR} -I. -DYY_NO_INPUT YHEADER=1 @@ -17,4 +23,16 @@ DPADD= ${LIBUTIL} ${LIBCRYPT} ${LIBY} ${LIBL} LDADD= -lutil -lcrypt -ly -ll +.if ${MKARGON2} != "no" +ARGON2DIR= ${NETBSDSRCDIR}/external/apache2/argon2 +ARGON2OBJDIR!= cd ${ARGON2DIR}/lib/libargon2 && ${PRINTOBJDIR} +CPPFLAGS+= -I${NETBSDSRCDIR}/external/apache2/argon2/dist/phc-winner-argon2/include +CPPFLAGS+= -DHAVE_ARGON2 +LDADD+= -Wl,-Bstatic +LDADD+= -L${ARGON2OBJDIR} -largon2 +LDADD+= -Wl,-Bdynamic +LDADD+= -pthread +DPADD+= ${ARGON2OBJDIR}/libargon2.a ${LIBPTHREAD} +.endif + .include <bsd.prog.mk> Index: sbin/cgdconfig/argon2_utils.c =================================================================== RCS file: sbin/cgdconfig/argon2_utils.c diff -N sbin/cgdconfig/argon2_utils.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sbin/cgdconfig/argon2_utils.c 5 Nov 2021 15:41:43 -0000 @@ -0,0 +1,165 @@ +/* $NetBSD$ */ +/*- + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nia Alarie. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/resource.h> +#include <sys/sysctl.h> +#include <argon2.h> +#include <stdlib.h> +#include <time.h> +#include <util.h> +#include <err.h> + +#include "argon2_utils.h" + +static size_t +get_cpucount(void) +{ + const int mib[] = { CTL_HW, HW_NCPUONLINE }; + int ncpuonline = 1; + size_t ncpuonline_len = sizeof(ncpuonline); + + if (sysctl(mib, __arraycount(mib), + &ncpuonline, &ncpuonline_len, NULL, 0) < 0) { + return 1; + } + return ncpuonline; +} + +static uint64_t +get_usermem(void) +{ + const int mib[] = { CTL_HW, HW_USERMEM64 }; + uint64_t usermem64 = 0; + size_t usermem64_len = sizeof(usermem64); + struct rlimit rlim; + + if (sysctl(mib, __arraycount(mib), + &usermem64, &usermem64_len, NULL, 0) < 0) { + return 1; + } + + if (getrlimit(RLIMIT_AS, &rlim) < 0) + return usermem64; + if (usermem64 > rlim.rlim_cur && rlim.rlim_cur != RLIM_INFINITY) + usermem64 = rlim.rlim_cur; + return usermem64; +} + +void +argon2id_calibrate(size_t keylen, size_t saltlen, + size_t *iterations, size_t *memory, size_t *parallelism) +{ + size_t mem = 256; + size_t time = 1; + const size_t ncpus = get_cpucount(); + const uint64_t usermem = get_usermem(); + struct rusage ru1, ru2; + struct timeval delta; + unsigned int limit = 0; + uint8_t *key = NULL, *salt = NULL; + uint8_t tmp_pwd[17]; + char tmp_encoded[512]; + int err = ARGON2_OK; + + arc4random_buf(tmp_pwd, sizeof(tmp_pwd)); + + key = emalloc(keylen); + arc4random_buf(key, keylen); + + salt = emalloc(saltlen); + arc4random_buf(salt, saltlen); + + mem = usermem / 100000; + + if (mem < ARGON2_MIN_MEMORY) + mem = 256; + + /* Decrease 'mem' if it slows down computation too much */ + + do { + if (getrusage(RUSAGE_SELF, &ru1) == -1) + goto error; + if ((err = argon2_hash(time, mem, ncpus, + tmp_pwd, sizeof(tmp_pwd), + salt, saltlen, + key, keylen, + tmp_encoded, sizeof(tmp_encoded), + Argon2_id, ARGON2_VERSION_NUMBER)) != ARGON2_OK) { + goto error_a2; + } + if (getrusage(RUSAGE_SELF, &ru2) == -1) + goto error; + timersub(&ru2.ru_utime, &ru1.ru_utime, &delta); + if (delta.tv_sec >= 1) + mem /= 2; + if (mem < ARGON2_MIN_MEMORY) { + mem = ARGON2_MIN_MEMORY; + break; + } + } while (delta.tv_sec >= 1 && (limit++) < 3); + + /* Increase 'time' until we reach a second */ + + delta.tv_sec = 0; + delta.tv_usec = 0; + + if (getrusage(RUSAGE_SELF, &ru1) == -1) + goto error; + + for (; delta.tv_sec < 1 && time < ARGON2_MAX_TIME; ++time) { + if ((err = argon2_hash(time, mem, ncpus, + tmp_pwd, sizeof(tmp_pwd), + salt, saltlen, + key, keylen, + tmp_encoded, sizeof(tmp_encoded), + Argon2_id, ARGON2_VERSION_NUMBER)) != ARGON2_OK) { + goto error_a2; + } + if (getrusage(RUSAGE_SELF, &ru2) == -1) + goto error; + timersub(&ru2.ru_utime, &ru1.ru_utime, &delta); + } + + if (time > 1) + time--; + + free(key); + free(salt); + *iterations = time; + *memory = mem; + *parallelism = ncpus; + return; + +error_a2: + errx(EXIT_FAILURE, + "failed to calculate Argon2 hash, error code %d\n", err); +error: + errx(EXIT_FAILURE, "failed to calculate hash parameters"); +} Index: sbin/cgdconfig/argon2_utils.h =================================================================== RCS file: sbin/cgdconfig/argon2_utils.h diff -N sbin/cgdconfig/argon2_utils.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sbin/cgdconfig/argon2_utils.h 5 Nov 2021 15:41:43 -0000 @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nia Alarie. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +void argon2id_calibrate(size_t, size_t, size_t *, size_t *, size_t *); Index: sbin/cgdconfig/cgdconfig.8 =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.8,v retrieving revision 1.50 diff -u -r1.50 cgdconfig.8 --- sbin/cgdconfig/cgdconfig.8 30 Apr 2021 21:07:34 -0000 1.50 +++ sbin/cgdconfig/cgdconfig.8 5 Nov 2021 15:41:43 -0000 @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 18, 2021 +.Dd November 4, 2021 .Dt CGDCONFIG 8 .Os .Sh NAME @@ -164,6 +164,13 @@ and uses the exclusive-or of the outputs of all the methods. The methods and descriptions are as follows: .Bl -tag -width indentxxxxxxxxxxx +.It argon2id +This method requires a passphrase which is entered at configuration +time. +Argon2 is a memory-hard password hashing scheme and winner of the +2013-2015 Password Hashing Competition. +It has numerous parameters allowing its hardness to scale with the +performance of the system. .It pkcs5_pbkdf2/sha1 This method requires a passphrase which is entered at configuration time. @@ -231,8 +238,8 @@ .It re-enter prompt for passphrase twice, and ensure entered passphrases are identical. -This method only works with the pkcs5_pbkdf2/sha1 and pkcs5_pbkdf2 key -generators. +This method only works with the argon2id, pkcs5_pbkdf2/sha1, and +pkcs5_pbkdf2 key generators. .El .Ss /etc/cgd/cgd.conf The file @@ -358,10 +365,22 @@ Only used for the shell_cmd key generation method. .It iterations Ar integer The number of iterations. -Only used for pkcs5_pbkdf2/sha1 and pkcs5_pbkdf2. +Only used for argon2id, pkcs5_pbkdf2/sha1, and pkcs5_pbkdf2. .It salt Ar base64 The salt. -Only used for pkcs5_pbkdf2/sha1 and pkcs5_pbkdf2. +Only used for argon2id, pkcs5_pbkdf2/sha1, and pkcs5_pbkdf2. +.It memory Ar integer +Memory consumption in kilobytes. +Only used for argon2id. +.It parallelism Ar integer +Number of threads to use to compute the password hash. +Should be equivalent to the number of CPUs/hardware threads. +Only used for argon2id. +.It version Ar integer +Version of Argon2 to use. +Should be the most recent version, currently +.Dv 19 . +Only used for argon2id. .El .Sh FILES .Bl -tag -width indentxxxxxxxxxxxxxxxxxx -compact @@ -475,6 +494,15 @@ .Xr fstab 5 , .Xr disklabel 8 , .Xr gpt 8 +.Rs +.%T "Argon2: the memory-hard function for password hashing and other applications" +.%A Alex Biryukov +.%A Daniel Dinu +.%A Dmitry Khovratovich +.%D 2017 +.%I University of Luxembourg +.%U https://www.password-hashing.net/ +.Re .Pp .Dq PKCS #5 v2.0: Password-Based Cryptography Standard , RSA Laboratories, March 25, 1999. Index: sbin/cgdconfig/cgdconfig.c =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.c,v retrieving revision 1.52 diff -u -r1.52 cgdconfig.c --- sbin/cgdconfig/cgdconfig.c 16 Jun 2021 23:22:08 -0000 1.52 +++ sbin/cgdconfig/cgdconfig.c 5 Nov 2021 15:41:43 -0000 @@ -36,6 +36,9 @@ __RCSID("$NetBSD: cgdconfig.c,v 1.52 2021/06/16 23:22:08 riastradh Exp $"); #endif +#ifdef HAVE_ARGON2 +#include <argon2.h> +#endif #include <err.h> #include <errno.h> #include <fcntl.h> @@ -113,6 +116,9 @@ static bits_t *getkey(const char *, struct keygen *, size_t); static bits_t *getkey_storedkey(const char *, struct keygen *, size_t); static bits_t *getkey_randomkey(const char *, struct keygen *, size_t, int); +#ifdef HAVE_ARGON2 +static bits_t *getkey_argon2id(const char *, struct keygen *, size_t); +#endif static bits_t *getkey_pkcs5_pbkdf2(const char *, struct keygen *, size_t, int); static bits_t *getkey_shell_cmd(const char *, struct keygen *, size_t); @@ -337,6 +343,11 @@ case KEYGEN_URANDOMKEY: tmp = getkey_randomkey(dev, kg, len, 0); break; +#ifdef HAVE_ARGON2 + case KEYGEN_ARGON2ID: + tmp = getkey_argon2id(dev, kg, len); + break; +#endif case KEYGEN_PKCS5_PBKDF2_SHA1: tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 0); break; @@ -454,6 +465,42 @@ return ret; } +#ifdef HAVE_ARGON2 +static bits_t * +getkey_argon2id(const char *target, struct keygen *kg, size_t keylen) +{ + bits_t *ret; + char *passp; + char buf[1024]; + uint8_t raw[256]; + char encoded[512]; + int err; + + snprintf(buf, sizeof(buf), "%s's passphrase%s:", target, + pflag & PFLAG_GETPASS_ECHO ? " (echo)" : ""); + passp = maybe_getpass(buf); + if ((err = argon2_hash(kg->kg_iterations, kg->kg_memory, + kg->kg_parallelism, + passp, strlen(passp), + bits_getbuf(kg->kg_salt), + BITS2BYTES(bits_len(kg->kg_salt)), + raw, sizeof(raw), + encoded, sizeof(encoded), + Argon2_id, kg->kg_version)) != ARGON2_OK) { + warnx("failed to generate Argon2id key, error code %d", err); + return NULL; + } + + ret = bits_new(raw, keylen); + kg->kg_key = bits_dup(ret); + explicit_memset(passp, 0, strlen(passp)); + explicit_memset(encoded, 0, sizeof(encoded)); + explicit_memset(raw, 0, sizeof(raw)); + free(passp); + return ret; +} +#endif + /*ARGSUSED*/ static bits_t * getkey_shell_cmd(const char *target, struct keygen *kg, size_t keylen) @@ -606,8 +653,9 @@ for (kg = p->keygen; (pflag & PFLAG_GETPASS_MASK) && kg; kg = kg->next) - if ((kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1) || - (kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD )) { + if (kg->kg_method == KEYGEN_ARGON2ID || + kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1 || + kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD) { loop = 1; break; } @@ -984,22 +1032,39 @@ verify_reenter(struct params *p) { struct keygen *kg; - bits_t *orig_key, *key; + bits_t *orig_key, *key = NULL; int ret; ret = 0; for (kg = p->keygen; kg && !ret; kg = kg->next) { - if ((kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1) && - (kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD )) + if (kg->kg_method != KEYGEN_ARGON2ID && + kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1 && + kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD) continue; orig_key = kg->kg_key; kg->kg_key = NULL; - /* add a compat flag till the _OLD method goes away */ - key = getkey_pkcs5_pbkdf2("re-enter device", kg, - bits_len(orig_key), - kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD); + switch (kg->kg_method) { +#ifdef HAVE_ARGON2 + case KEYGEN_ARGON2ID: + key = getkey_argon2id("re-enter device", kg, + bits_len(orig_key)); + break; +#endif + case KEYGEN_PKCS5_PBKDF2_SHA1: + key = getkey_pkcs5_pbkdf2("re-enter device", kg, + bits_len(orig_key), 0); + break; + case KEYGEN_PKCS5_PBKDF2_OLD: + key = getkey_pkcs5_pbkdf2("re-enter device", kg, + bits_len(orig_key), 1); + break; + default: + warnx("unsupported keygen method"); + kg->kg_key = orig_key; + return -1; + } ret = !bits_match(key, orig_key); Index: sbin/cgdconfig/cgdlex.l =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/cgdlex.l,v retrieving revision 1.5 diff -u -r1.5 cgdlex.l --- sbin/cgdconfig/cgdlex.l 29 Oct 2009 14:49:03 -0000 1.5 +++ sbin/cgdconfig/cgdlex.l 5 Nov 2021 15:41:43 -0000 @@ -98,6 +98,9 @@ keygen { RETTOKEN(KEYGEN); } salt { RETTOKEN(SALT); } iterations { RETTOKEN(ITERATIONS); } +memory { RETTOKEN(MEMORY); } +parallelism { RETTOKEN(PARALLELISM); } +version { RETTOKEN(VERSION); } key { RETTOKEN(KEY); } cmd { RETTOKEN(CMD); } keygen_method { RETTOKEN(KEYGEN_METHOD); } Index: sbin/cgdconfig/cgdparse.y =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/cgdparse.y,v retrieving revision 1.5 diff -u -r1.5 cgdparse.y --- sbin/cgdconfig/cgdparse.y 17 Jul 2008 16:24:55 -0000 1.5 +++ sbin/cgdconfig/cgdparse.y 5 Nov 2021 15:41:43 -0000 @@ -67,7 +67,7 @@ %token <string> STRINGLIT %token <token> ALGORITHM KEYLENGTH IVMETHOD VERIFY_METHOD -%token <token> KEYGEN SALT ITERATIONS KEY CMD +%token <token> KEYGEN SALT ITERATIONS MEMORY PARALLELISM VERSION KEY CMD %token EOL @@ -99,6 +99,9 @@ kgvar: SALT bits EOL { $$ = keygen_salt($2); } | ITERATIONS INTEGER EOL { $$ = keygen_iterations($2); } + | MEMORY INTEGER EOL { $$ = keygen_memory($2); } + | PARALLELISM INTEGER EOL { $$ = keygen_parallelism($2); } + | VERSION INTEGER EOL { $$ = keygen_version($2); } | KEY bits EOL { $$ = keygen_key($2); } | CMD stringlit EOL { $$ = keygen_cmd($2); } | EOL { $$ = NULL; } Index: sbin/cgdconfig/params.c =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/params.c,v retrieving revision 1.31 diff -u -r1.31 params.c --- sbin/cgdconfig/params.c 3 Jun 2021 15:40:27 -0000 1.31 +++ sbin/cgdconfig/params.c 5 Nov 2021 15:41:43 -0000 @@ -45,6 +45,11 @@ #include <string.h> #include <util.h> +#ifdef HAVE_ARGON2 +#include <argon2.h> +#include "argon2_utils.h" +#endif + #include "params.h" #include "pkcs5_pbkdf2.h" #include "utils.h" @@ -314,6 +319,9 @@ kg = emalloc(sizeof(*kg)); kg->kg_method = KEYGEN_UNKNOWN; kg->kg_iterations = (size_t)-1; + kg->kg_memory = (size_t)-1; + kg->kg_parallelism = (size_t)-1; + kg->kg_version = (size_t)-1; kg->kg_salt = NULL; kg->kg_key = NULL; kg->kg_cmd = NULL; @@ -346,6 +354,34 @@ if (!kg) return 1; switch (kg->kg_method) { +#ifdef HAVE_ARGON2 + case KEYGEN_ARGON2ID: + if (kg->kg_iterations == (size_t)-1) { + warnx("keygen argon2id must provide `iterations'"); + return 0; + } + if (kg->kg_memory == (size_t)-1) { + warnx("keygen argon2id must provide `memory'"); + return 0; + } + if (kg->kg_parallelism == (size_t)-1) { + warnx("keygen argon2id must provide `parallelism'"); + return 0; + } + if (kg->kg_version == (size_t)-1) { + warnx("keygen argon2id must provide `version'"); + return 0; + } + if (kg->kg_cmd) + warnx("keygen argon2id does not need a `cmd'"); + if (kg->kg_key) + warnx("keygen argon2id does not need a `key'"); + if (!kg->kg_salt) { + warnx("keygen argon2id must provide a salt"); + return 0; + } + break; +#endif case KEYGEN_PKCS5_PBKDF2_OLD: if (kg->kg_iterations == (size_t)-1) { warnx("keygen pkcs5_pbkdf2 must provide `iterations'"); @@ -445,6 +481,14 @@ case KEYGEN_URANDOMKEY: case KEYGEN_SHELL_CMD: break; +#ifdef HAVE_ARGON2 + case KEYGEN_ARGON2ID: + kg->kg_version = ARGON2_VERSION_NUMBER; + kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1); + argon2id_calibrate(BITS2BYTES(keylen), DEFAULT_SALTLEN, + &kg->kg_iterations, &kg->kg_memory, &kg->kg_parallelism); + break; +#endif case KEYGEN_PKCS5_PBKDF2_OLD: case KEYGEN_PKCS5_PBKDF2_SHA1: kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1); @@ -488,6 +532,15 @@ if (kg2->kg_iterations != (size_t)-1 && kg2->kg_iterations > 0) kg1->kg_iterations = kg2->kg_iterations; + if (kg2->kg_memory != (size_t)-1 && kg2->kg_memory > 0) + kg1->kg_memory = kg2->kg_memory; + + if (kg2->kg_parallelism != (size_t)-1 && kg2->kg_parallelism > 0) + kg1->kg_parallelism = kg2->kg_parallelism; + + if (kg2->kg_version != (size_t)-1 && kg2->kg_version > 0) + kg1->kg_version = kg2->kg_version; + if (kg2->kg_salt) bits_assign(&kg1->kg_salt, kg2->kg_salt); @@ -506,6 +559,10 @@ struct keygen *kg = keygen_new(); const char *kgm = string_tocharstar(in); +#ifdef HAVE_ARGON2 + if (!strcmp("argon2id", kgm)) + kg->kg_method = KEYGEN_ARGON2ID; +#endif if (!strcmp("pkcs5_pbkdf2", kgm)) kg->kg_method = KEYGEN_PKCS5_PBKDF2_OLD; if (!strcmp("pkcs5_pbkdf2/sha1", kgm)) @@ -551,6 +608,33 @@ return kg; } +struct keygen * +keygen_memory(size_t in) +{ + struct keygen *kg = keygen_new(); + + kg->kg_memory = in; + return kg; +} + +struct keygen * +keygen_parallelism(size_t in) +{ + struct keygen *kg = keygen_new(); + + kg->kg_parallelism = in; + return kg; +} + +struct keygen * +keygen_version(size_t in) +{ + struct keygen *kg = keygen_new(); + + kg->kg_version = in; + return kg; +} + void keygen_addlist(struct keygen **l, struct keygen *e) { @@ -743,6 +827,17 @@ case KEYGEN_URANDOMKEY: (void)fprintf(f, "urandomkey;\n"); break; +#ifdef HAVE_ARGON2 + case KEYGEN_ARGON2ID: + (void)fprintf(f, "argon2id {\n"); + print_kvpair_int(f, ts, "iterations", kg->kg_iterations); + print_kvpair_int(f, ts, "memory", kg->kg_memory); + print_kvpair_int(f, ts, "parallelism", kg->kg_parallelism); + print_kvpair_int(f, ts, "version", kg->kg_version); + print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt); + (void)fprintf(f, "};\n"); + break; +#endif case KEYGEN_PKCS5_PBKDF2_OLD: (void)fprintf(f, "pkcs5_pbkdf2 {\n"); print_kvpair_int(f, ts, "iterations", kg->kg_iterations); Index: sbin/cgdconfig/params.h =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/params.h,v retrieving revision 1.11 diff -u -r1.11 params.h --- sbin/cgdconfig/params.h 14 Dec 2014 12:31:39 -0000 1.11 +++ sbin/cgdconfig/params.h 5 Nov 2021 15:41:43 -0000 @@ -37,6 +37,9 @@ struct keygen { int kg_method; size_t kg_iterations; + size_t kg_memory; /* only used for Argon2 */ + size_t kg_parallelism; /* only used for Argon2 */ + size_t kg_version; /* only used for Argon2 */ bits_t *kg_salt; bits_t *kg_key; string_t *kg_cmd; @@ -63,6 +66,7 @@ #define KEYGEN_URANDOMKEY 0x4 #define KEYGEN_PKCS5_PBKDF2_SHA1 0x5 #define KEYGEN_SHELL_CMD 0x6 +#define KEYGEN_ARGON2ID 0x7 /* verification methods */ @@ -108,6 +112,9 @@ struct keygen *keygen_set_method(struct keygen *, string_t *); struct keygen *keygen_salt(bits_t *); struct keygen *keygen_iterations(size_t); +struct keygen *keygen_memory(size_t); +struct keygen *keygen_parallelism(size_t); +struct keygen *keygen_version(size_t); struct keygen *keygen_key(bits_t *); struct keygen *keygen_cmd(string_t *);