Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Feb 2019 18:44:10 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r344373 - in stable/11/stand: . geli i386/gptboot i386/gptzfsboot i386/isoboot i386/loader i386/zfsboot libsa libsa/geli
Message-ID:  <201902201844.x1KIiA6K004307@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Wed Feb 20 18:44:09 2019
New Revision: 344373
URL: https://svnweb.freebsd.org/changeset/base/344373

Log:
  MFC r335321, r335336: stand: move libgeliboot into libsa
  
  r335321:
  stand: move libgeliboot into libsa.
  
  Reduce by 1 the number of crazy libraries we need in stand by moving
  geli into libsa (where architecturally it belonged all along). This
  just moves things around without any code changes.
  
  r335336:
  Remove now-empty geli directory

Added:
  stable/11/stand/libsa/geli/
     - copied from r335321, head/stand/libsa/geli/
Replaced:
     - copied unchanged from r344372, stable/11/stand/geli/geliboot.c
     - copied unchanged from r344372, stable/11/stand/geli/pwgets.c
Directory Properties:
  stable/11/stand/libsa/geli/geliboot.c   (props changed)
  stable/11/stand/libsa/geli/pwgets.c   (props changed)
Deleted:
  stable/11/stand/geli/
Modified:
  stable/11/stand/Makefile
  stable/11/stand/defs.mk
  stable/11/stand/i386/gptboot/Makefile
  stable/11/stand/i386/gptzfsboot/Makefile
  stable/11/stand/i386/isoboot/Makefile
  stable/11/stand/i386/loader/Makefile
  stable/11/stand/i386/zfsboot/Makefile
  stable/11/stand/libsa/Makefile
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/stand/Makefile
==============================================================================
--- stable/11/stand/Makefile	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/Makefile	Wed Feb 20 18:44:09 2019	(r344373)
@@ -21,8 +21,6 @@ S.${MK_ZFS}+=		zfs
 S.yes+=			defaults
 S.yes+=			man
 
-S.${MK_LOADER_GELI}+=	geli
-
 .include <bsd.arch.inc.mk>
 
 S.${MK_EFI}+=		efi

Modified: stable/11/stand/defs.mk
==============================================================================
--- stable/11/stand/defs.mk	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/defs.mk	Wed Feb 20 18:44:09 2019	(r344373)
@@ -67,8 +67,7 @@ MK_LOADER_GELI=yes
 .endif
 .if ${MK_LOADER_GELI} == "yes"
 CFLAGS+=	-DLOADER_GELI_SUPPORT
-CFLAGS+=	-I${BOOTSRC}/geli
-LIBGELIBOOT=	${BOOTOBJ}/geli/libgeliboot.a
+CFLAGS+=	-I${SASRC}/geli
 .endif # MK_LOADER_GELI
 .endif # HAVE_GELI
 

Modified: stable/11/stand/i386/gptboot/Makefile
==============================================================================
--- stable/11/stand/i386/gptboot/Makefile	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/i386/gptboot/Makefile	Wed Feb 20 18:44:09 2019	(r344373)
@@ -64,7 +64,7 @@ gptboot.bin: gptboot.out
 	${OBJCOPY} -S -O binary gptboot.out ${.TARGET}
 
 gptboot.out: ${BTXCRT} gptboot.o sio.o crc32.o drv.o cons.o ${OPENCRYPTO_XTS}
-	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBGELIBOOT} ${LIBSA32}
+	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSA32}
 
 .include <bsd.prog.mk>
 

Modified: stable/11/stand/i386/gptzfsboot/Makefile
==============================================================================
--- stable/11/stand/i386/gptzfsboot/Makefile	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/i386/gptzfsboot/Makefile	Wed Feb 20 18:44:09 2019	(r344373)
@@ -75,7 +75,7 @@ gptzfsboot.bin: gptzfsboot.out
 
 gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o \
 	${OPENCRYPTO_XTS}
-	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBGELIBOOT} ${LIBZFSBOOT} ${LIBSA32}
+	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBZFSBOOT} ${LIBSA32}
 
 zfsboot.o: ${ZFSSRC}/zfsimpl.c
 

Modified: stable/11/stand/i386/isoboot/Makefile
==============================================================================
--- stable/11/stand/i386/isoboot/Makefile	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/i386/isoboot/Makefile	Wed Feb 20 18:44:09 2019	(r344373)
@@ -66,6 +66,6 @@ isoboot.bin: isoboot.out
 	${OBJCOPY} -S -O binary isoboot.out ${.TARGET}
 
 isoboot.out: ${BTXCRT} isoboot.o sio.o crc32.o drv.o cons.o ${OPENCRYPTO_XTS}
-	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBGELIBOOT} ${LIBSA32}
+	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSA32}
 
 .include <bsd.prog.mk>

Modified: stable/11/stand/i386/loader/Makefile
==============================================================================
--- stable/11/stand/i386/loader/Makefile	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/i386/loader/Makefile	Wed Feb 20 18:44:09 2019	(r344373)
@@ -71,8 +71,8 @@ FILESMODE_${LOADER}= ${BINMODE} -b
 # XXX crt0.o needs to be first for pxeboot(8) to work
 OBJS=	${BTXCRT}
 
-DPADD=	${LDR_INTERP32} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBGELIBOOT} ${LIBSA32}
-LDADD=	${LDR_INTERP32} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBGELIBOOT} ${LIBSA32}
+DPADD=	${LDR_INTERP32} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSA32}
+LDADD=	${LDR_INTERP32} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSA32}
 
 .if ${MACHINE_CPUARCH} == "amd64"
 CFLAGS+=	-DLOADER_PREFER_AMD64

Modified: stable/11/stand/i386/zfsboot/Makefile
==============================================================================
--- stable/11/stand/i386/zfsboot/Makefile	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/i386/zfsboot/Makefile	Wed Feb 20 18:44:09 2019	(r344373)
@@ -82,7 +82,7 @@ zfsboot.bin: zfsboot.out
 	${OBJCOPY} -S -O binary zfsboot.out ${.TARGET}
 
 zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o
-	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBZFSBOOT} ${LIBGELIBOOT} ${LIBSA32}
+	${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBZFSBOOT} ${LIBSA32}
 
 SRCS=	zfsboot.c
 

Modified: stable/11/stand/libsa/Makefile
==============================================================================
--- stable/11/stand/libsa/Makefile	Wed Feb 20 18:40:14 2019	(r344372)
+++ stable/11/stand/libsa/Makefile	Wed Feb 20 18:44:09 2019	(r344373)
@@ -146,4 +146,9 @@ CFLAGS.bzipfs.c+= -I${SRCTOP}/contrib/bzip2
 .PATH: ${SYSDIR}/libkern
 SRCS+=  explicit_bzero.c
 
+# Maybe GELI
+.if ${MK_LOADER_GELI} == "yes"
+.include "${SASRC}/geli/Makefile.inc"
+.endif
+
 .include <bsd.lib.mk>

Copied: stable/11/stand/libsa/geli/geliboot.c (from r344372, stable/11/stand/geli/geliboot.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/11/stand/libsa/geli/geliboot.c	Wed Feb 20 18:44:09 2019	(r344373, copy of r344372, stable/11/stand/geli/geliboot.c)
@@ -0,0 +1,437 @@
+/*-
+ * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
+ * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * All rights reserved.
+ *
+ * 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 AUTHORS 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 AUTHORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "geliboot_internal.h"
+#include "geliboot.h"
+
+SLIST_HEAD(geli_list, geli_entry) geli_head = SLIST_HEAD_INITIALIZER(geli_head);
+struct geli_list *geli_headp;
+
+typedef u_char geli_ukey[G_ELI_USERKEYLEN];
+
+static geli_ukey saved_keys[GELI_MAX_KEYS];
+static unsigned int nsaved_keys = 0;
+
+/*
+ * Copy keys from local storage to the keybuf struct.
+ * Destroy the local storage when finished.
+ */
+void
+geli_fill_keybuf(struct keybuf *fkeybuf)
+{
+	unsigned int i;
+
+	for (i = 0; i < nsaved_keys; i++) {
+		fkeybuf->kb_ents[i].ke_type = KEYBUF_TYPE_GELI;
+		memcpy(fkeybuf->kb_ents[i].ke_data, saved_keys[i],
+		    G_ELI_USERKEYLEN);
+	}
+	fkeybuf->kb_nents = nsaved_keys;
+	explicit_bzero(saved_keys, sizeof(saved_keys));
+}
+
+/*
+ * Copy keys from a keybuf struct into local storage.
+ * Zero out the keybuf.
+ */
+void
+geli_save_keybuf(struct keybuf *skeybuf)
+{
+	unsigned int i;
+
+	for (i = 0; i < skeybuf->kb_nents && i < GELI_MAX_KEYS; i++) {
+		memcpy(saved_keys[i], skeybuf->kb_ents[i].ke_data,
+		    G_ELI_USERKEYLEN);
+		explicit_bzero(skeybuf->kb_ents[i].ke_data,
+		    G_ELI_USERKEYLEN);
+		skeybuf->kb_ents[i].ke_type = KEYBUF_TYPE_NONE;
+	}
+	nsaved_keys = skeybuf->kb_nents;
+	skeybuf->kb_nents = 0;
+}
+
+static void
+save_key(geli_ukey key)
+{
+
+	/*
+	 * If we run out of key space, the worst that will happen is
+	 * it will ask the user for the password again.
+	 */
+	if (nsaved_keys < GELI_MAX_KEYS) {
+		memcpy(saved_keys[nsaved_keys], key, G_ELI_USERKEYLEN);
+		nsaved_keys++;
+	}
+}
+
+static int
+geli_same_device(struct geli_entry *ge, struct dsk *dskp)
+{
+
+	if (ge->dsk->drive == dskp->drive &&
+	    dskp->part == 255 && ge->dsk->part == dskp->slice) {
+		/*
+		 * Sometimes slice = slice, and sometimes part = slice
+		 * If the incoming struct dsk has part=255, it means look at
+		 * the slice instead of the part number
+		 */
+		return (0);
+	}
+
+	/* Is this the same device? */
+	if (ge->dsk->drive != dskp->drive ||
+	    ge->dsk->slice != dskp->slice ||
+	    ge->dsk->part != dskp->part) {
+		return (1);
+	}
+
+	return (0);
+}
+
+static int
+geli_findkey(struct geli_entry *ge, struct dsk *dskp, u_char *mkey)
+{
+	u_int keynum;
+	int i;
+
+	if (ge->keybuf_slot >= 0) {
+		if (g_eli_mkey_decrypt(&ge->md, saved_keys[ge->keybuf_slot],
+		    mkey, &keynum) == 0) {
+			return (0);
+		}
+	}
+
+	for (i = 0; i < nsaved_keys; i++) {
+		if (g_eli_mkey_decrypt(&ge->md, saved_keys[i], mkey,
+		    &keynum) == 0) {
+			ge->keybuf_slot = i;
+			return (0);
+		}
+	}
+
+	return (1);
+}
+
+void
+geli_init(void)
+{
+
+	geli_count = 0;
+	SLIST_INIT(&geli_head);
+}
+
+/*
+ * Read the last sector of the drive or partition pointed to by dsk and see
+ * if it is GELI encrypted
+ */
+int
+geli_taste(int read_func(void *vdev, void *priv, off_t off, void *buf,
+    size_t bytes), struct dsk *dskp, daddr_t lastsector)
+{
+	struct g_eli_metadata md;
+	u_char buf[DEV_GELIBOOT_BSIZE];
+	int error;
+	off_t alignsector;
+
+	alignsector = rounddown2(lastsector * DEV_BSIZE, DEV_GELIBOOT_BSIZE);
+	if (alignsector + DEV_GELIBOOT_BSIZE > ((lastsector + 1) * DEV_BSIZE)) {
+		/* Don't read past the end of the disk */
+		alignsector = (lastsector * DEV_BSIZE) + DEV_BSIZE
+		    - DEV_GELIBOOT_BSIZE;
+	}
+	error = read_func(NULL, dskp, alignsector, &buf, DEV_GELIBOOT_BSIZE);
+	if (error != 0) {
+		return (error);
+	}
+	/* Extract the last 4k sector of the disk. */
+	error = eli_metadata_decode(buf, &md);
+	if (error != 0) {
+		/* Try the last 512 byte sector instead. */
+		error = eli_metadata_decode(buf +
+		    (DEV_GELIBOOT_BSIZE - DEV_BSIZE), &md);
+		if (error != 0) {
+			return (error);
+		}
+	}
+
+	if (!(md.md_flags & G_ELI_FLAG_GELIBOOT)) {
+		/* The GELIBOOT feature is not activated */
+		return (1);
+	}
+	if ((md.md_flags & G_ELI_FLAG_ONETIME)) {
+		/* Swap device, skip it. */
+		return (1);
+	}
+	if (md.md_iterations < 0) {
+		/* XXX TODO: Support loading key files. */
+		/* Disk does not have a passphrase, skip it. */
+		return (1);
+	}
+	geli_e = malloc(sizeof(struct geli_entry));
+	if (geli_e == NULL)
+		return (2);
+
+	geli_e->dsk = malloc(sizeof(struct dsk));
+	if (geli_e->dsk == NULL)
+		return (2);
+	memcpy(geli_e->dsk, dskp, sizeof(struct dsk));
+	geli_e->part_end = lastsector;
+	if (dskp->part == 255) {
+		geli_e->dsk->part = dskp->slice;
+	}
+	geli_e->keybuf_slot = -1;
+
+	geli_e->md = md;
+	eli_metadata_softc(&geli_e->sc, &md, DEV_BSIZE,
+	    (lastsector + DEV_BSIZE) * DEV_BSIZE);
+
+	SLIST_INSERT_HEAD(&geli_head, geli_e, entries);
+	geli_count++;
+
+	return (0);
+}
+
+/*
+ * Attempt to decrypt the device
+ */
+static int
+geli_attach(struct geli_entry *ge, struct dsk *dskp, const char *passphrase,
+    u_char *mkeyp)
+{
+	u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN], *mkp;
+	u_int keynum;
+	struct hmac_ctx ctx;
+	int error;
+
+	if (mkeyp != NULL) {
+		memcpy(&mkey, mkeyp, G_ELI_DATAIVKEYLEN);
+		explicit_bzero(mkeyp, G_ELI_DATAIVKEYLEN);
+	}
+
+	if (mkeyp != NULL || geli_findkey(ge, dskp, mkey) == 0) {
+		goto found_key;
+	}
+
+	g_eli_crypto_hmac_init(&ctx, NULL, 0);
+	/*
+	 * Prepare Derived-Key from the user passphrase.
+	 */
+	if (geli_e->md.md_iterations < 0) {
+		/* XXX TODO: Support loading key files. */
+		return (1);
+	} else if (geli_e->md.md_iterations == 0) {
+		g_eli_crypto_hmac_update(&ctx, geli_e->md.md_salt,
+		    sizeof(geli_e->md.md_salt));
+		g_eli_crypto_hmac_update(&ctx, (const uint8_t *)passphrase,
+		    strlen(passphrase));
+	} else if (geli_e->md.md_iterations > 0) {
+		printf("Calculating GELI Decryption Key disk%dp%d @ %d"
+		    " iterations...\n", dskp->unit,
+		    (dskp->slice > 0 ? dskp->slice : dskp->part),
+		    geli_e->md.md_iterations);
+		u_char dkey[G_ELI_USERKEYLEN];
+
+		pkcs5v2_genkey(dkey, sizeof(dkey), geli_e->md.md_salt,
+		    sizeof(geli_e->md.md_salt), passphrase,
+		    geli_e->md.md_iterations);
+		g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
+		explicit_bzero(dkey, sizeof(dkey));
+	}
+
+	g_eli_crypto_hmac_final(&ctx, key, 0);
+
+	error = g_eli_mkey_decrypt(&geli_e->md, key, mkey, &keynum);
+	if (error == -1) {
+		explicit_bzero(mkey, sizeof(mkey));
+		explicit_bzero(key, sizeof(key));
+		printf("Bad GELI key: bad password?\n");
+		return (error);
+	} else if (error != 0) {
+		explicit_bzero(mkey, sizeof(mkey));
+		explicit_bzero(key, sizeof(key));
+		printf("Failed to decrypt GELI master key: %d\n", error);
+		return (error);
+	} else {
+		/* Add key to keychain */
+		save_key(key);
+		explicit_bzero(&key, sizeof(key));
+	}
+
+found_key:
+	/* Store the keys */
+	bcopy(mkey, geli_e->sc.sc_mkey, sizeof(geli_e->sc.sc_mkey));
+	bcopy(mkey, geli_e->sc.sc_ivkey, sizeof(geli_e->sc.sc_ivkey));
+	mkp = mkey + sizeof(geli_e->sc.sc_ivkey);
+	if ((geli_e->sc.sc_flags & G_ELI_FLAG_AUTH) == 0) {
+		bcopy(mkp, geli_e->sc.sc_ekey, G_ELI_DATAKEYLEN);
+	} else {
+		/*
+		 * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
+		 */
+		g_eli_crypto_hmac(mkp, G_ELI_MAXKEYLEN, (const uint8_t *)"\x10", 1,
+		    geli_e->sc.sc_ekey, 0);
+	}
+	explicit_bzero(mkey, sizeof(mkey));
+
+	/* Initialize the per-sector IV. */
+	switch (geli_e->sc.sc_ealgo) {
+	case CRYPTO_AES_XTS:
+		break;
+	default:
+		SHA256_Init(&geli_e->sc.sc_ivctx);
+		SHA256_Update(&geli_e->sc.sc_ivctx, geli_e->sc.sc_ivkey,
+		    sizeof(geli_e->sc.sc_ivkey));
+		break;
+	}
+
+	return (0);
+}
+
+int
+is_geli(struct dsk *dskp)
+{
+	SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
+		if (geli_same_device(geli_e, dskp) == 0) {
+			return (0);
+		}
+	}
+
+	return (1);
+}
+
+int
+geli_read(struct dsk *dskp, off_t offset, u_char *buf, size_t bytes)
+{
+	u_char iv[G_ELI_IVKEYLEN];
+	u_char *pbuf;
+	int error;
+	off_t dstoff;
+	uint64_t keyno;
+	size_t n, nsec, secsize;
+	struct g_eli_key gkey;
+
+	pbuf = buf;
+	SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
+		if (geli_same_device(geli_e, dskp) != 0) {
+			continue;
+		}
+
+		secsize = geli_e->sc.sc_sectorsize;
+		nsec = bytes / secsize;
+		if (nsec == 0) {
+			/*
+			 * A read of less than the GELI sector size has been
+			 * requested. The caller provided destination buffer may
+			 * not be big enough to boost the read to a full sector,
+			 * so just attempt to decrypt the truncated sector.
+			 */
+			secsize = bytes;
+			nsec = 1;
+		}
+
+		for (n = 0, dstoff = offset; n < nsec; n++, dstoff += secsize) {
+
+			g_eli_crypto_ivgen(&geli_e->sc, dstoff, iv,
+			    G_ELI_IVKEYLEN);
+
+			/* Get the key that corresponds to this offset. */
+			keyno = (dstoff >> G_ELI_KEY_SHIFT) / secsize;
+			g_eli_key_fill(&geli_e->sc, &gkey, keyno);
+
+			error = geliboot_crypt(geli_e->sc.sc_ealgo, 0, pbuf,
+			    secsize, gkey.gek_key,
+			    geli_e->sc.sc_ekeylen, iv);
+
+			if (error != 0) {
+				explicit_bzero(&gkey, sizeof(gkey));
+				printf("Failed to decrypt in geli_read()!");
+				return (error);
+			}
+			pbuf += secsize;
+		}
+		explicit_bzero(&gkey, sizeof(gkey));
+		return (0);
+	}
+
+	printf("GELI provider not found\n");
+	return (1);
+}
+
+int
+geli_havekey(struct dsk *dskp)
+{
+	u_char mkey[G_ELI_DATAIVKEYLEN];
+
+	SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
+		if (geli_same_device(geli_e, dskp) != 0) {
+			continue;
+		}
+
+		if (geli_findkey(geli_e, dskp, mkey) == 0) {
+			if (geli_attach(geli_e, dskp, NULL, mkey) == 0) {
+				return (0);
+			}
+		}
+	}
+	explicit_bzero(mkey, sizeof(mkey));
+
+	return (1);
+}
+
+int
+geli_passphrase(char *pw, int disk, int parttype, int part, struct dsk *dskp)
+{
+	int i;
+
+	SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
+		if (geli_same_device(geli_e, dskp) != 0) {
+			continue;
+		}
+
+		/* TODO: Implement GELI keyfile(s) support */
+		for (i = 0; i < 3; i++) {
+			/* Try cached passphrase */
+			if (i == 0 && pw[0] != '\0') {
+				if (geli_attach(geli_e, dskp, pw, NULL) == 0) {
+					return (0);
+				}
+			}
+			printf("GELI Passphrase for disk%d%c%d: ", disk,
+			    parttype, part);
+			pwgets(pw, GELI_PW_MAXLEN,
+			    (geli_e->md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS) == 0);
+			printf("\n");
+			if (geli_attach(geli_e, dskp, pw, NULL) == 0) {
+				return (0);
+			}
+		}
+	}
+
+	return (1);
+}

Copied: stable/11/stand/libsa/geli/pwgets.c (from r344372, stable/11/stand/geli/pwgets.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/11/stand/libsa/geli/pwgets.c	Wed Feb 20 18:44:09 2019	(r344373, copy of r344372, stable/11/stand/geli/pwgets.c)
@@ -0,0 +1,79 @@
+/*	$NetBSD: gets.c,v 1.6 1995/10/11 21:16:57 pk Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *	@(#)gets.c	8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "stand.h"
+
+/* gets() with constrained input length, for passwords */
+
+void
+pwgets(char *buf, int n, int hide)
+{
+    int c;
+    char *lp;
+
+    for (lp = buf;;)
+	switch (c = getchar() & 0177) {
+	case '\n':
+	case '\r':
+	    *lp = '\0';
+	    putchar('\n');
+	    return;
+	case '\b':
+	case '\177':
+	    if (lp > buf) {
+		lp--;
+		if (hide == 0) {
+			putchar('\b');
+			putchar(' ');
+			putchar('\b');
+		}
+	    }
+	    break;
+	case 'u'&037:
+	case 'w'&037:
+	    lp = buf;
+	    putchar('\n');
+	    break;
+	default:
+	    if ((n < 1) || ((lp - buf) < n - 1)) {
+		*lp++ = c;
+		if (hide == 0) {
+			putchar('*');
+		}
+	    }
+	}
+    /*NOTREACHED*/
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902201844.x1KIiA6K004307>