Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 May 2018 20:53:38 +0000 (UTC)
From:      Mariusz Zaborski <oshogbo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r333439 - in head: sbin/geom/class/eli stand/geli sys/geom/eli
Message-ID:  <201805092053.w49Krc3S081535@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: oshogbo
Date: Wed May  9 20:53:38 2018
New Revision: 333439
URL: https://svnweb.freebsd.org/changeset/base/333439

Log:
  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.
  
  Reviewed by:	allanjude
  Differential Revision:	https://reviews.freebsd.org/D15309

Modified:
  head/sbin/geom/class/eli/geli.8
  head/sbin/geom/class/eli/geom_eli.c
  head/stand/geli/geliboot.c
  head/sys/geom/eli/g_eli.c
  head/sys/geom/eli/g_eli.h
  head/sys/geom/eli/g_eli_ctl.c
  head/sys/geom/eli/g_eli_key.c

Modified: head/sbin/geom/class/eli/geli.8
==============================================================================
--- head/sbin/geom/class/eli/geli.8	Wed May  9 20:51:16 2018	(r333438)
+++ head/sbin/geom/class/eli/geli.8	Wed May  9 20:53:38 2018	(r333439)
@@ -68,6 +68,7 @@ utility:
 .Nm
 .Cm attach
 .Op Fl Cdprv
+.Op Fl n Ar keyno
 .Op Fl j Ar passfile
 .Op Fl k Ar keyfile
 .Ar prov
@@ -407,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: head/sbin/geom/class/eli/geom_eli.c
==============================================================================
--- head/sbin/geom/class/eli/geom_eli.c	Wed May  9 20:51:16 2018	(r333438)
+++ head/sbin/geom/class/eli/geom_eli.c	Wed May  9 20:53:38 2018	(r333439)
@@ -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 [-Cdprv] [-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
@@ -149,11 +149,12 @@ struct g_command class_commands[] = {
 		{ '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
 	    },
-	    "[-Cdprv] [-j passfile] [-k keyfile] prov"
+	    "[-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov"
 	},
 	{ "detach", 0, NULL,
 	    {
@@ -1129,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: head/stand/geli/geliboot.c
==============================================================================
--- head/stand/geli/geliboot.c	Wed May  9 20:51:16 2018	(r333438)
+++ head/stand/geli/geliboot.c	Wed May  9 20:53:38 2018	(r333439)
@@ -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: head/sys/geom/eli/g_eli.c
==============================================================================
--- head/sys/geom/eli/g_eli.c	Wed May  9 20:51:16 2018	(r333438)
+++ head/sys/geom/eli/g_eli.c	Wed May  9 20:53:38 2018	(r333439)
@@ -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: head/sys/geom/eli/g_eli.h
==============================================================================
--- head/sys/geom/eli/g_eli.h	Wed May  9 20:51:16 2018	(r333438)
+++ head/sys/geom/eli/g_eli.h	Wed May  9 20:53:38 2018	(r333439)
@@ -688,6 +688,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: head/sys/geom/eli/g_eli_ctl.c
==============================================================================
--- head/sys/geom/eli/g_eli_ctl.c	Wed May  9 20:51:16 2018	(r333438)
+++ head/sys/geom/eli/g_eli_ctl.c	Wed May  9 20:53:38 2018	(r333439)
@@ -60,8 +60,8 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class 
 	const char *name;
 	u_char *key, mkey[G_ELI_DATAIVKEYLEN];
 	int *nargs, *detach, *readonly, *dryrun;
-	int keysize, error;
-	u_int nkey;
+	int keysize, error, nkey;
+	intmax_t *valp;
 
 	g_topology_assert();
 
@@ -81,6 +81,17 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class 
 		return;
 	}
 
+	valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
+	if (valp == NULL) {
+		gctl_error(req, "No '%s' argument.", "keyno");
+		return;
+	}
+	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");
@@ -129,7 +140,10 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class 
 		return;
 	}
 
-	error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
+	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) {
 		explicit_bzero(&md, sizeof(md));
@@ -981,7 +995,7 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class 
 		return;
 	}
 
-	error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
+	error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
 	explicit_bzero(key, keysize);
 	if (error == -1) {
 		explicit_bzero(&md, sizeof(md));

Modified: head/sys/geom/eli/g_eli_key.c
==============================================================================
--- head/sys/geom/eli/g_eli_key.c	Wed May  9 20:51:16 2018	(r333438)
+++ head/sys/geom/eli/g_eli_key.c	Wed May  9 20:53:38 2018	(r333439)
@@ -103,52 +103,77 @@ g_eli_mkey_hmac(unsigned char *mkey, const unsigned ch
 }
 
 /*
- * 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) {
-			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));
-			if (nkeyp != NULL)
-				*nkeyp = nkey;
-			return (0);
-		}
+	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;
+			break;
+		} else if (error > 0) {
+			break;
+		}
+	}
+
+	return (error);
 }
 
 /*



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