tech-crypto archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[PATCH] argon2 key generation method for cgdconfig(8)



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


Home | Main Index | Thread Index | Old Index