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 *);
 

Reply via email to