Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Feb 2019 23:42:03 +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: r344397 - in stable/11: sbin/geom/class/eli stand/libsa/geli sys/geom/eli
Message-ID:  <201902202342.x1KNg3qP086981@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Wed Feb 20 23:42:03 2019
New Revision: 344397
URL: https://svnweb.freebsd.org/changeset/base/344397

Log:
  MFC r316312, r332361, r333438-r333439, r339804: GELI dry-run
  
  r316312:
  sys/geom/eli: Switch bzero() to explicit_bzero() for sensitive data
  
  In GELI, anywhere we are zeroing out possibly sensitive data, like
  the metadata struct, the metadata sector (both contain the encrypted
  master key), the user key, or the master key, use explicit_bzero.
  
  Didn't touch the bzero() used to initialize structs.
  
  r332361:
  Introduce dry run option for attaching the device.
  This will allow us to verify if passphrase and key is valid without
  decrypting whole device.
  
  r333438:
  Change option dry-run from 'n' to 'C' in geli attach command.
  
  'n' is used in other commands to define the key index.
  We should be consistent with that.
  'C' option is used by patch(1) to perform dryrun so lets use that.
  
  r333439:
  Introduce the 'n' flag for the geli attach command.
  
  If the 'n' flag is provided the provided key number will be used to
  decrypt device. This can be used combined with dryrun to verify if the key
  is set correctly. This can be also used to determine which key slot we want to
  change on already attached device.
  
  r339804:
  Restore backward compatibility for "attach" verb.
  
  In r332361 and r333439, two new parameters were added to geli attach
  verb using gctl_get_paraml, which requires the value to be present.
  This would prevent old geli(8) binary from attaching geli(4) device
  as they have no knowledge about the new parameters.
  
  Restore backward compatibility by treating the absense of these two
  values as seeing the default value supplied by userland.

Modified:
  stable/11/sbin/geom/class/eli/geli.8
  stable/11/sbin/geom/class/eli/geom_eli.c
  stable/11/stand/libsa/geli/geliboot.c
  stable/11/sys/geom/eli/g_eli.c
  stable/11/sys/geom/eli/g_eli.h
  stable/11/sys/geom/eli/g_eli_ctl.c
  stable/11/sys/geom/eli/g_eli_key.c
  stable/11/sys/geom/eli/g_eli_key_cache.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/geom/class/eli/geli.8
==============================================================================
--- stable/11/sbin/geom/class/eli/geli.8	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/sbin/geom/class/eli/geli.8	Wed Feb 20 23:42:03 2019	(r344397)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 17, 2017
+.Dd May 9, 2018
 .Dt GELI 8
 .Os
 .Sh NAME
@@ -67,7 +67,8 @@ utility:
 .Cm init
 .Nm
 .Cm attach
-.Op Fl dprv
+.Op Fl Cdprv
+.Op Fl n Ar keyno
 .Op Fl j Ar passfile
 .Op Fl k Ar keyfile
 .Ar prov
@@ -393,6 +394,9 @@ suffix.
 .Pp
 Additional options include:
 .Bl -tag -width ".Fl j Ar passfile"
+.It Fl C
+Do a dry-run decryption.
+This is useful to verify passphrase and keyfile without decrypting the device.
 .It Fl d
 If specified, a decrypted provider will be detached automatically on last close.
 This can help with scarce memory so the user does not have to remember to detach the
@@ -404,6 +408,9 @@ Probably a better choice is the
 option for the
 .Cm detach
 subcommand.
+.It Fl n Ar keyno
+Specifies the index number of the Master Key copy to use (could be 0 or 1).
+If the index number is not provided all keys will be tested.
 .It Fl j Ar passfile
 Specifies a file which contains the passphrase component of the User Key
 (or part of it).

Modified: stable/11/sbin/geom/class/eli/geom_eli.c
==============================================================================
--- stable/11/sbin/geom/class/eli/geom_eli.c	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/sbin/geom/class/eli/geom_eli.c	Wed Feb 20 23:42:03 2019	(r344397)
@@ -86,7 +86,7 @@ static int eli_backup_create(struct gctl_req *req, con
  *
  * init [-bdgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov
  * label - alias for 'init'
- * attach [-dprv] [-j passfile] [-k keyfile] prov
+ * attach [-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov
  * detach [-fl] prov ...
  * stop - alias for 'detach'
  * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov
@@ -145,14 +145,16 @@ struct g_command class_commands[] = {
 	},
 	{ "attach", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main,
 	    {
+		{ 'C', "dryrun", NULL, G_TYPE_BOOL },
 		{ 'd', "detach", NULL, G_TYPE_BOOL },
 		{ 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
 		{ 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
+		{ 'n', "keyno", "-1", G_TYPE_NUMBER },
 		{ 'p', "nopassphrase", NULL, G_TYPE_BOOL },
 		{ 'r', "readonly", NULL, G_TYPE_BOOL },
 		G_OPT_SENTINEL
 	    },
-	    "[-dprv] [-j passfile] [-k keyfile] prov"
+	    "[-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov"
 	},
 	{ "detach", 0, NULL,
 	    {
@@ -1128,7 +1130,7 @@ eli_setkey_detached(struct gctl_req *req, const char *
 	}
 
 	/* Decrypt Master Key. */
-	error = g_eli_mkey_decrypt(md, key, mkey, &nkey);
+	error = g_eli_mkey_decrypt_any(md, key, mkey, &nkey);
 	bzero(key, sizeof(key));
 	if (error != 0) {
 		bzero(md, sizeof(*md));

Modified: stable/11/stand/libsa/geli/geliboot.c
==============================================================================
--- stable/11/stand/libsa/geli/geliboot.c	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/stand/libsa/geli/geliboot.c	Wed Feb 20 23:42:03 2019	(r344397)
@@ -121,14 +121,14 @@ geli_findkey(struct geli_entry *ge, struct dsk *dskp, 
 	int i;
 
 	if (ge->keybuf_slot >= 0) {
-		if (g_eli_mkey_decrypt(&ge->md, saved_keys[ge->keybuf_slot],
+		if (g_eli_mkey_decrypt_any(&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,
+		if (g_eli_mkey_decrypt_any(&ge->md, saved_keys[i], mkey,
 		    &keynum) == 0) {
 			ge->keybuf_slot = i;
 			return (0);
@@ -266,7 +266,7 @@ geli_attach(struct geli_entry *ge, struct dsk *dskp, c
 
 	g_eli_crypto_hmac_final(&ctx, key, 0);
 
-	error = g_eli_mkey_decrypt(&geli_e->md, key, mkey, &keynum);
+	error = g_eli_mkey_decrypt_any(&geli_e->md, key, mkey, &keynum);
 	if (error == -1) {
 		explicit_bzero(mkey, sizeof(mkey));
 		explicit_bzero(key, sizeof(key));

Modified: stable/11/sys/geom/eli/g_eli.c
==============================================================================
--- stable/11/sys/geom/eli/g_eli.c	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/sys/geom/eli/g_eli.c	Wed Feb 20 23:42:03 2019	(r344397)
@@ -1086,7 +1086,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp,
                                  memcpy(key, keybuf->kb_ents[i].ke_data,
                                      sizeof(key));
 
-                                 if (g_eli_mkey_decrypt(&md, key,
+                                 if (g_eli_mkey_decrypt_any(&md, key,
                                      mkey, &nkey) == 0 ) {
                                          explicit_bzero(key, sizeof(key));
                                          goto have_key;
@@ -1161,7 +1161,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp,
                 /*
                  * Decrypt Master-Key.
                  */
-                error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
+                error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
                 bzero(key, sizeof(key));
                 if (error == -1) {
                         if (i == tries) {

Modified: stable/11/sys/geom/eli/g_eli.h
==============================================================================
--- stable/11/sys/geom/eli/g_eli.h	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/sys/geom/eli/g_eli.h	Wed Feb 20 23:42:03 2019	(r344397)
@@ -686,6 +686,8 @@ void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t 
 
 void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key);
 int g_eli_mkey_decrypt(const struct g_eli_metadata *md,
+    const unsigned char *key, unsigned char *mkey, unsigned keyp);
+int g_eli_mkey_decrypt_any(const struct g_eli_metadata *md,
     const unsigned char *key, unsigned char *mkey, unsigned *nkeyp);
 int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
     unsigned char *mkey);

Modified: stable/11/sys/geom/eli/g_eli_ctl.c
==============================================================================
--- stable/11/sys/geom/eli/g_eli_ctl.c	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/sys/geom/eli/g_eli_ctl.c	Wed Feb 20 23:42:03 2019	(r344397)
@@ -57,9 +57,9 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class 
 	struct g_provider *pp;
 	const char *name;
 	u_char *key, mkey[G_ELI_DATAIVKEYLEN];
-	int *nargs, *detach, *readonly;
-	int keysize, error;
-	u_int nkey;
+	int *nargs, *detach, *readonly, *dryrunp;
+	int keysize, error, nkey, dryrun, dummy;
+	intmax_t *valp;
 
 	g_topology_assert();
 
@@ -79,12 +79,39 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class 
 		return;
 	}
 
+	/* "keyno" is optional for backward compatibility */
+	nkey = -1;
+	valp = gctl_get_param(req, "keyno", &dummy);
+	if (valp != NULL) {
+		valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
+		if (valp != NULL)
+			nkey = *valp;
+	}
+	if (nkey < -1 || nkey >= G_ELI_MAXMKEYS) {
+		gctl_error(req, "Invalid '%s' argument.", "keyno");
+		return;
+	}
+
 	readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
 	if (readonly == NULL) {
 		gctl_error(req, "No '%s' argument.", "readonly");
 		return;
 	}
 
+	/* "dryrun" is optional for backward compatibility */
+	dryrun = 0;
+	dryrunp = gctl_get_param(req, "dryrun", &dummy);
+	if (dryrunp != NULL) {
+		dryrunp = gctl_get_paraml(req, "dryrun", sizeof(*dryrunp));
+		if (dryrunp != NULL)
+			dryrun = *dryrunp;
+	}
+
+	if (*detach && *readonly) {
+		gctl_error(req, "Options -d and -r are mutually exclusive.");
+		return;
+	}
+
 	name = gctl_get_asciiparam(req, "arg0");
 	if (name == NULL) {
 		gctl_error(req, "No 'arg%u' argument.", 0);
@@ -104,44 +131,43 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class 
 		return;
 	}
 	if (md.md_keys == 0x00) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "No valid keys on %s.", pp->name);
 		return;
 	}
 
 	key = gctl_get_param(req, "key", &keysize);
 	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "No '%s' argument.", "key");
 		return;
 	}
 
-	error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
-	bzero(key, keysize);
+	if (nkey == -1)
+		error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
+	else
+		error = g_eli_mkey_decrypt(&md, key, mkey, nkey);
+	explicit_bzero(key, keysize);
 	if (error == -1) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "Wrong key for %s.", pp->name);
 		return;
 	} else if (error > 0) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
 		    pp->name, error);
 		return;
 	}
 	G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
 
-	if (*detach && *readonly) {
-		bzero(&md, sizeof(md));
-		gctl_error(req, "Options -d and -r are mutually exclusive.");
-		return;
-	}
 	if (*detach)
 		md.md_flags |= G_ELI_FLAG_WO_DETACH;
 	if (*readonly)
 		md.md_flags |= G_ELI_FLAG_RO;
-	g_eli_create(req, mp, pp, &md, mkey, nkey);
-	bzero(mkey, sizeof(mkey));
-	bzero(&md, sizeof(md));
+	if (!dryrun)
+		g_eli_create(req, mp, pp, &md, mkey, nkey);
+	explicit_bzero(mkey, sizeof(mkey));
+	explicit_bzero(&md, sizeof(md));
 }
 
 static struct g_eli_softc *
@@ -362,8 +388,8 @@ g_eli_ctl_onetime(struct gctl_req *req, struct g_class
 	}
 
 	g_eli_create(req, mp, pp, &md, mkey, -1);
-	bzero(mkey, sizeof(mkey));
-	bzero(&md, sizeof(md));
+	explicit_bzero(mkey, sizeof(mkey));
+	explicit_bzero(&md, sizeof(md));
 }
 
 static void
@@ -582,8 +608,8 @@ g_eli_ctl_configure(struct gctl_req *req, struct g_cla
 			    "Cannot store metadata on %s (error=%d).",
 			    prov, error);
 		}
-		bzero(&md, sizeof(md));
-		bzero(sector, pp->sectorsize);
+		explicit_bzero(&md, sizeof(md));
+		explicit_bzero(sector, pp->sectorsize);
 		free(sector, M_ELI);
 	}
 }
@@ -607,6 +633,11 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class 
 		gctl_error(req, "No 'arg%u' argument.", 0);
 		return;
 	}
+	key = gctl_get_param(req, "key", &keysize);
+	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
+		gctl_error(req, "No '%s' argument.", "key");
+		return;
+	}
 	sc = g_eli_find_device(mp, name);
 	if (sc == NULL) {
 		gctl_error(req, "Provider %s is invalid.", name);
@@ -662,13 +693,6 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class 
 		md.md_iterations = *valp;
 	}
 
-	key = gctl_get_param(req, "key", &keysize);
-	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
-		bzero(&md, sizeof(md));
-		gctl_error(req, "No '%s' argument.", "key");
-		return;
-	}
-
 	mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN;
 	md.md_keys |= (1 << nkey);
 
@@ -676,9 +700,9 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class 
 
 	/* Encrypt Master Key with the new key. */
 	error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst);
-	bzero(key, keysize);
+	explicit_bzero(key, keysize);
 	if (error != 0) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "Cannot encrypt Master Key (error=%d).", error);
 		return;
 	}
@@ -686,10 +710,10 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class 
 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
 	/* Store metadata with fresh key. */
 	eli_metadata_encode(&md, sector);
-	bzero(&md, sizeof(md));
+	explicit_bzero(&md, sizeof(md));
 	error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
 	    pp->sectorsize);
-	bzero(sector, pp->sectorsize);
+	explicit_bzero(sector, pp->sectorsize);
 	free(sector, M_ELI);
 	if (error != 0) {
 		gctl_error(req, "Cannot store metadata on %s (error=%d).",
@@ -787,7 +811,7 @@ g_eli_ctl_delkey(struct gctl_req *req, struct g_class 
 	sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
 	for (i = 0; i <= g_eli_overwrites; i++) {
 		if (i == g_eli_overwrites)
-			bzero(mkeydst, keysize);
+			explicit_bzero(mkeydst, keysize);
 		else
 			arc4rand(mkeydst, keysize, 0);
 		/* Store metadata with destroyed key. */
@@ -804,8 +828,8 @@ g_eli_ctl_delkey(struct gctl_req *req, struct g_class 
 		 */
 		(void)g_io_flush(cp);
 	}
-	bzero(&md, sizeof(md));
-	bzero(sector, pp->sectorsize);
+	explicit_bzero(&md, sizeof(md));
+	explicit_bzero(sector, pp->sectorsize);
 	free(sector, M_ELI);
 	if (*all)
 		G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
@@ -852,12 +876,12 @@ g_eli_suspend_one(struct g_eli_softc *sc, struct gctl_
 	/*
 	 * Clear sensitive data on suspend, they will be recovered on resume.
 	 */
-	bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
+	explicit_bzero(sc->sc_mkey, sizeof(sc->sc_mkey));
 	g_eli_key_destroy(sc);
-	bzero(sc->sc_akey, sizeof(sc->sc_akey));
-	bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
-	bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
-	bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
+	explicit_bzero(sc->sc_akey, sizeof(sc->sc_akey));
+	explicit_bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx));
+	explicit_bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey));
+	explicit_bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx));
 	mtx_unlock(&sc->sc_queue_mtx);
 	G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name);
 }
@@ -950,6 +974,11 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class 
 		gctl_error(req, "No 'arg%u' argument.", 0);
 		return;
 	}
+	key = gctl_get_param(req, "key", &keysize);
+	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
+		gctl_error(req, "No '%s' argument.", "key");
+		return;
+	}
 	sc = g_eli_find_device(mp, name);
 	if (sc == NULL) {
 		gctl_error(req, "Provider %s is invalid.", name);
@@ -964,26 +993,19 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class 
 		return;
 	}
 	if (md.md_keys == 0x00) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "No valid keys on %s.", pp->name);
 		return;
 	}
 
-	key = gctl_get_param(req, "key", &keysize);
-	if (key == NULL || keysize != G_ELI_USERKEYLEN) {
-		bzero(&md, sizeof(md));
-		gctl_error(req, "No '%s' argument.", "key");
-		return;
-	}
-
-	error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
-	bzero(key, keysize);
+	error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
+	explicit_bzero(key, keysize);
 	if (error == -1) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "Wrong key for %s.", pp->name);
 		return;
 	} else if (error > 0) {
-		bzero(&md, sizeof(md));
+		explicit_bzero(&md, sizeof(md));
 		gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).",
 		    pp->name, error);
 		return;
@@ -1001,8 +1023,8 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class 
 		wakeup(sc);
 	}
 	mtx_unlock(&sc->sc_queue_mtx);
-	bzero(mkey, sizeof(mkey));
-	bzero(&md, sizeof(md));
+	explicit_bzero(mkey, sizeof(mkey));
+	explicit_bzero(&md, sizeof(md));
 }
 
 static int

Modified: stable/11/sys/geom/eli/g_eli_key.c
==============================================================================
--- stable/11/sys/geom/eli/g_eli_key.c	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/sys/geom/eli/g_eli_key.c	Wed Feb 20 23:42:03 2019	(r344397)
@@ -69,7 +69,7 @@ g_eli_mkey_verify(const unsigned char *mkey, const uns
 	g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
 	    chmac, 0);
 
-	bzero(hmkey, sizeof(hmkey));
+	explicit_bzero(hmkey, sizeof(hmkey));
 
 	/*
 	 * Compare calculated HMAC with HMAC from metadata.
@@ -97,56 +97,81 @@ g_eli_mkey_hmac(unsigned char *mkey, const unsigned ch
 	g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
 	    odhmac, 0);
 
-	bzero(hmkey, sizeof(hmkey));
+	explicit_bzero(hmkey, sizeof(hmkey));
 }
 
 /*
- * Find and decrypt Master Key encrypted with 'key'.
- * Return decrypted Master Key number in 'nkeyp' if not NULL.
+ * Find and decrypt Master Key encrypted with 'key' at slot 'nkey'.
  * Return 0 on success, > 0 on failure, -1 on bad key.
  */
 int
 g_eli_mkey_decrypt(const struct g_eli_metadata *md, const unsigned char *key,
-    unsigned char *mkey, unsigned *nkeyp)
+    unsigned char *mkey, unsigned nkey)
 {
 	unsigned char tmpmkey[G_ELI_MKEYLEN];
 	unsigned char enckey[SHA512_MDLEN];	/* Key for encryption. */
 	const unsigned char *mmkey;
-	int bit, error, nkey;
+	int bit, error;
 
-	if (nkeyp != NULL)
-		*nkeyp = -1;
+	if (nkey > G_ELI_MKEYLEN)
+		return (-1);
 
 	/*
 	 * The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
 	 */
 	g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
 
-	mmkey = md->md_mkeys;
-	for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++, mmkey += G_ELI_MKEYLEN) {
-		bit = (1 << nkey);
-		if (!(md->md_keys & bit))
-			continue;
-		bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
-		error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey,
-		    G_ELI_MKEYLEN, enckey, md->md_keylen);
-		if (error != 0) {
-			bzero(tmpmkey, sizeof(tmpmkey));
-			bzero(enckey, sizeof(enckey));
-			return (error);
-		}
-		if (g_eli_mkey_verify(tmpmkey, key)) {
-			bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN);
-			bzero(tmpmkey, sizeof(tmpmkey));
-			bzero(enckey, sizeof(enckey));
+	mmkey = md->md_mkeys + G_ELI_MKEYLEN * nkey;
+	bit = (1 << nkey);
+	if (!(md->md_keys & bit))
+		return (-1);
+	bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
+	error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey,
+	    G_ELI_MKEYLEN, enckey, md->md_keylen);
+	if (error != 0) {
+		explicit_bzero(tmpmkey, sizeof(tmpmkey));
+		explicit_bzero(enckey, sizeof(enckey));
+		return (error);
+	}
+	if (g_eli_mkey_verify(tmpmkey, key)) {
+		bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN);
+		explicit_bzero(tmpmkey, sizeof(tmpmkey));
+		explicit_bzero(enckey, sizeof(enckey));
+		return (0);
+	}
+	explicit_bzero(enckey, sizeof(enckey));
+	explicit_bzero(tmpmkey, sizeof(tmpmkey));
+
+	return (-1);
+}
+
+/*
+ * Find and decrypt Master Key encrypted with 'key'.
+ * Return decrypted Master Key number in 'nkeyp' if not NULL.
+ * Return 0 on success, > 0 on failure, -1 on bad key.
+ */
+int
+g_eli_mkey_decrypt_any(const struct g_eli_metadata *md,
+    const unsigned char *key, unsigned char *mkey, unsigned *nkeyp)
+{
+	int error, nkey;
+
+	if (nkeyp != NULL)
+		*nkeyp = -1;
+
+	error = -1;
+	for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++) {
+		error = g_eli_mkey_decrypt(md, key, mkey, nkey);
+		if (error == 0) {
 			if (nkeyp != NULL)
 				*nkeyp = nkey;
-			return (0);
+			break;
+		} else if (error > 0) {
+			break;
 		}
 	}
-	bzero(enckey, sizeof(enckey));
-	bzero(tmpmkey, sizeof(tmpmkey));
-	return (-1);
+
+	return (error);
 }
 
 /*
@@ -175,7 +200,7 @@ g_eli_mkey_encrypt(unsigned algo, const unsigned char 
 	 */
 	error = g_eli_crypto_encrypt(algo, mkey, G_ELI_MKEYLEN, enckey, keylen);
 
-	bzero(enckey, sizeof(enckey));
+	explicit_bzero(enckey, sizeof(enckey));
 
 	return (error);
 }

Modified: stable/11/sys/geom/eli/g_eli_key_cache.c
==============================================================================
--- stable/11/sys/geom/eli/g_eli_key_cache.c	Wed Feb 20 23:05:17 2019	(r344396)
+++ stable/11/sys/geom/eli/g_eli_key_cache.c	Wed Feb 20 23:42:03 2019	(r344397)
@@ -117,7 +117,7 @@ g_eli_key_allocate(struct g_eli_softc *sc, uint64_t ke
 	keysearch.gek_keyno = keyno;
 	ekey = RB_FIND(g_eli_key_tree, &sc->sc_ekeys_tree, &keysearch);
 	if (ekey != NULL) {
-		bzero(key, sizeof(*key));
+		explicit_bzero(key, sizeof(*key));
 		free(key, M_ELI);
 		key = ekey;
 		TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next);
@@ -174,7 +174,7 @@ g_eli_key_remove(struct g_eli_softc *sc, struct g_eli_
 	RB_REMOVE(g_eli_key_tree, &sc->sc_ekeys_tree, key);
 	TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next);
 	sc->sc_ekeys_allocated--;
-	bzero(key, sizeof(*key));
+	explicit_bzero(key, sizeof(*key));
 	free(key, M_ELI);
 }
 
@@ -239,7 +239,7 @@ g_eli_key_destroy(struct g_eli_softc *sc)
 
 	mtx_lock(&sc->sc_ekeys_lock);
 	if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0) {
-		bzero(sc->sc_ekey, sizeof(sc->sc_ekey));
+		explicit_bzero(sc->sc_ekey, sizeof(sc->sc_ekey));
 	} else {
 		struct g_eli_key *key;
 



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