Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 25 Oct 2011 13:57:50 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r226733 - in head: sbin/geom/class/eli sys/geom/eli
Message-ID:  <201110251357.p9PDvoHG098640@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Tue Oct 25 13:57:50 2011
New Revision: 226733
URL: http://svn.freebsd.org/changeset/base/226733

Log:
  Add support for creating GELI devices with older metadata version for use
  with older FreeBSD versions:
  - Add -V option to 'geli init' to specify version number. If no -V is given
    the most recent version is used.
  - If -V is given don't allow to use features not supported by this version.
  - Print version in 'geli list' output.
  - Update manual page and add table describing which GELI version is
    supported by which FreeBSD version, so one can use it when preparing GELI
    device for older FreeBSD version.
  
  Inspired by:	Garrett Cooper <yanegomi@gmail.com>
  MFC after:	3 days

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

Modified: head/sbin/geom/class/eli/geli.8
==============================================================================
--- head/sbin/geom/class/eli/geli.8	Tue Oct 25 13:52:38 2011	(r226732)
+++ head/sbin/geom/class/eli/geli.8	Tue Oct 25 13:57:50 2011	(r226733)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 9, 2011
+.Dd October 25, 2011
 .Dt GELI 8
 .Os
 .Sh NAME
@@ -60,6 +60,7 @@ utility:
 .Op Fl K Ar newkeyfile
 .Op Fl l Ar keylen
 .Op Fl s Ar sectorsize
+.Op Fl V Ar version
 .Ar prov
 .Nm
 .Cm label - an alias for
@@ -322,6 +323,15 @@ Change decrypted provider's sector size.
 Increasing sector size allows to increase performance, because we need to
 generate an IV and do encrypt/decrypt for every single sector - less number
 of sectors means less work to do.
+.It Fl V Ar version
+Metadata version to use.
+This option is helpful when creating provider that may be used by older
+.Nm FreeBSD/GELI
+versions.
+Consult the
+.Sx HISTORY
+section to find which metadata version is supported by which FreeBSD version.
+Note that using older metadata version may limit numer of features available.
 .El
 .It Cm attach
 Attach the given provider.
@@ -931,5 +941,33 @@ Support for 
 .Nm Camellia
 block cipher is implemented by Yoshisato Yanagisawa in
 .Fx 7.0 .
+.Pp
+Highest
+.Nm GELI
+metadata version supported by the given FreeBSD version:
+.Pp
+.Bl -column -offset indent ".Sy FreeBSD" ".Sy version"
+.It Sy FreeBSD Ta Sy GELI
+.It Sy version Ta Sy version
+.Pp
+.It Li 6.0 Ta 0
+.It Li 6.1 Ta 0
+.It Li 6.2 Ta 3
+.It Li 6.3 Ta 3
+.It Li 6.4 Ta 3
+.Pp
+.It Li 7.0 Ta 3
+.It Li 7.1 Ta 3
+.It Li 7.2 Ta 3
+.It Li 7.3 Ta 3
+.It Li 7.4 Ta 3
+.Pp
+.It Li 8.0 Ta 3
+.It Li 8.1 Ta 3
+.It Li 8.2 Ta 5
+.Pp
+.It Li 9.0 Ta 6
+.El
+.Pp
 .Sh AUTHORS
 .An Pawel Jakub Dawidek Aq pjd@FreeBSD.org

Modified: head/sbin/geom/class/eli/geom_eli.c
==============================================================================
--- head/sbin/geom/class/eli/geom_eli.c	Tue Oct 25 13:52:38 2011	(r226732)
+++ head/sbin/geom/class/eli/geom_eli.c	Tue Oct 25 13:57:50 2011	(r226733)
@@ -82,7 +82,7 @@ static int eli_backup_create(struct gctl
 /*
  * Available commands:
  *
- * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov
+ * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-V version] prov
  * label - alias for 'init'
  * attach [-dprv] [-j passfile] [-k keyfile] prov
  * detach [-fl] prov ...
@@ -107,29 +107,31 @@ struct g_command class_commands[] = {
 		{ 'a', "aalgo", "", G_TYPE_STRING },
 		{ 'b', "boot", NULL, G_TYPE_BOOL },
 		{ 'B', "backupfile", "", G_TYPE_STRING },
-		{ 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING },
+		{ 'e', "ealgo", "", G_TYPE_STRING },
 		{ 'i', "iterations", "-1", G_TYPE_NUMBER },
 		{ 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
 		{ 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
 		{ 'l', "keylen", "0", G_TYPE_NUMBER },
 		{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
 		{ 's', "sectorsize", "0", G_TYPE_NUMBER },
+		{ 'V', "mdversion", "-1", G_TYPE_NUMBER },
 		G_OPT_SENTINEL
 	    },
-	    "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov"
+	    "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov"
 	},
 	{ "label", G_FLAG_VERBOSE, eli_main,
 	    {
 		{ 'a', "aalgo", "", G_TYPE_STRING },
 		{ 'b', "boot", NULL, G_TYPE_BOOL },
 		{ 'B', "backupfile", "", G_TYPE_STRING },
-		{ 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING },
+		{ 'e', "ealgo", "", G_TYPE_STRING },
 		{ 'i', "iterations", "-1", G_TYPE_NUMBER },
 		{ 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
 		{ 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
 		{ 'l', "keylen", "0", G_TYPE_NUMBER },
 		{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
 		{ 's', "sectorsize", "0", G_TYPE_NUMBER },
+		{ 'V', "mdversion", "-1", G_TYPE_NUMBER },
 		G_OPT_SENTINEL
 	    },
 	    "- an alias for 'init'"
@@ -672,7 +674,7 @@ eli_init(struct gctl_req *req)
 	unsigned char key[G_ELI_USERKEYLEN];
 	char backfile[MAXPATHLEN];
 	const char *str, *prov;
-	unsigned secsize;
+	unsigned int secsize, version;
 	off_t mediasize;
 	intmax_t val;
 	int error, nargs;
@@ -693,13 +695,30 @@ eli_init(struct gctl_req *req)
 
 	bzero(&md, sizeof(md));
 	strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
-	md.md_version = G_ELI_VERSION;
+	val = gctl_get_intmax(req, "mdversion");
+	if (val == -1) {
+		version = G_ELI_VERSION;
+	} else if (val < 0 || val > G_ELI_VERSION) {
+		gctl_error(req,
+		    "Invalid version specified should be between %u and %u.",
+		    G_ELI_VERSION_00, G_ELI_VERSION);
+		return;
+	} else {
+		version = val;
+	}
+	md.md_version = version;
 	md.md_flags = 0;
 	if (gctl_get_int(req, "boot"))
 		md.md_flags |= G_ELI_FLAG_BOOT;
 	md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
 	str = gctl_get_ascii(req, "aalgo");
 	if (*str != '\0') {
+		if (version < G_ELI_VERSION_01) {
+			gctl_error(req,
+			    "Data authentication is supported starting from version %u.",
+			    G_ELI_VERSION_01);
+			return;
+		}
 		md.md_aalgo = g_eli_str2aalgo(str);
 		if (md.md_aalgo >= CRYPTO_ALGORITHM_MIN &&
 		    md.md_aalgo <= CRYPTO_ALGORITHM_MAX) {
@@ -725,12 +744,32 @@ eli_init(struct gctl_req *req)
 	if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
 	    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
 		str = gctl_get_ascii(req, "ealgo");
+		if (*str == '\0') {
+			if (version < G_ELI_VERSION_05)
+				str = "aes-cbc";
+			else
+				str = GELI_ENC_ALGO;
+		}
 		md.md_ealgo = g_eli_str2ealgo(str);
 		if (md.md_ealgo < CRYPTO_ALGORITHM_MIN ||
 		    md.md_ealgo > CRYPTO_ALGORITHM_MAX) {
 			gctl_error(req, "Invalid encryption algorithm.");
 			return;
 		}
+		if (md.md_ealgo == CRYPTO_CAMELLIA_CBC &&
+		    version < G_ELI_VERSION_04) {
+			gctl_error(req,
+			    "Camellia-CBC algorithm is supported starting from version %u.",
+			    G_ELI_VERSION_04);
+			return;
+		}
+		if (md.md_ealgo == CRYPTO_AES_XTS &&
+		    version < G_ELI_VERSION_05) {
+			gctl_error(req,
+			    "AES-XTS algorithm is supported starting from version %u.",
+			    G_ELI_VERSION_05);
+			return;
+		}
 	}
 	val = gctl_get_intmax(req, "keylen");
 	md.md_keylen = val;

Modified: head/sys/geom/eli/g_eli.c
==============================================================================
--- head/sys/geom/eli/g_eli.c	Tue Oct 25 13:52:38 2011	(r226732)
+++ head/sys/geom/eli/g_eli.c	Tue Oct 25 13:57:50 2011	(r226733)
@@ -713,6 +713,7 @@ g_eli_create(struct gctl_req *req, struc
 	else
 		gp->access = g_std_access;
 
+	sc->sc_version = md->md_version;
 	sc->sc_inflight = 0;
 	sc->sc_crypto = G_ELI_CRYPTO_UNKNOWN;
 	sc->sc_flags = md->md_flags;
@@ -1210,6 +1211,7 @@ g_eli_dumpconf(struct sbuf *sb, const ch
 		sbuf_printf(sb, "%s<UsedKey>%u</UsedKey>\n", indent,
 		    sc->sc_nkey);
 	}
+	sbuf_printf(sb, "%s<Version>%u</Version>\n", indent, sc->sc_version);
 	sbuf_printf(sb, "%s<Crypto>", indent);
 	switch (sc->sc_crypto) {
 	case G_ELI_CRYPTO_HW:

Modified: head/sys/geom/eli/g_eli.h
==============================================================================
--- head/sys/geom/eli/g_eli.h	Tue Oct 25 13:52:38 2011	(r226732)
+++ head/sys/geom/eli/g_eli.h	Tue Oct 25 13:57:50 2011	(r226733)
@@ -43,6 +43,7 @@
 #include <sys/tree.h>
 #include <geom/geom.h>
 #else
+#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 #include <strings.h>
@@ -166,6 +167,7 @@ struct g_eli_worker {
 
 struct g_eli_softc {
 	struct g_geom	*sc_geom;
+	u_int		 sc_version;
 	u_int		 sc_crypto;
 	uint8_t		 sc_mkey[G_ELI_DATAIVKEYLEN];
 	uint8_t		 sc_ekey[G_ELI_DATAKEYLEN];
@@ -217,14 +219,28 @@ struct g_eli_metadata {
 } __packed;
 #ifndef _OpenSSL_
 static __inline void
-eli_metadata_encode(struct g_eli_metadata *md, u_char *data)
+eli_metadata_encode_v0(struct g_eli_metadata *md, u_char **datap)
 {
-	MD5_CTX ctx;
 	u_char *p;
 
-	p = data;
-	bcopy(md->md_magic, p, sizeof(md->md_magic)); p += sizeof(md->md_magic);
-	le32enc(p, md->md_version);	p += sizeof(md->md_version);
+	p = *datap;
+	le32enc(p, md->md_flags);	p += sizeof(md->md_flags);
+	le16enc(p, md->md_ealgo);	p += sizeof(md->md_ealgo);
+	le16enc(p, md->md_keylen);	p += sizeof(md->md_keylen);
+	le64enc(p, md->md_provsize);	p += sizeof(md->md_provsize);
+	le32enc(p, md->md_sectorsize);	p += sizeof(md->md_sectorsize);
+	*p = md->md_keys;		p += sizeof(md->md_keys);
+	le32enc(p, md->md_iterations);	p += sizeof(md->md_iterations);
+	bcopy(md->md_salt, p, sizeof(md->md_salt)); p += sizeof(md->md_salt);
+	bcopy(md->md_mkeys, p, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
+	*datap = p;
+}
+static __inline void
+eli_metadata_encode_v1v2v3v4v5v6(struct g_eli_metadata *md, u_char **datap)
+{
+	u_char *p;
+
+	p = *datap;
 	le32enc(p, md->md_flags);	p += sizeof(md->md_flags);
 	le16enc(p, md->md_ealgo);	p += sizeof(md->md_ealgo);
 	le16enc(p, md->md_keylen);	p += sizeof(md->md_keylen);
@@ -235,6 +251,39 @@ eli_metadata_encode(struct g_eli_metadat
 	le32enc(p, md->md_iterations);	p += sizeof(md->md_iterations);
 	bcopy(md->md_salt, p, sizeof(md->md_salt)); p += sizeof(md->md_salt);
 	bcopy(md->md_mkeys, p, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
+	*datap = p;
+}
+static __inline void
+eli_metadata_encode(struct g_eli_metadata *md, u_char *data)
+{
+	MD5_CTX ctx;
+	u_char *p;
+
+	p = data;
+	bcopy(md->md_magic, p, sizeof(md->md_magic));
+	p += sizeof(md->md_magic);
+	le32enc(p, md->md_version);
+	p += sizeof(md->md_version);
+	switch (md->md_version) {
+	case G_ELI_VERSION_00:
+		eli_metadata_encode_v0(md, &p);
+		break;
+	case G_ELI_VERSION_01:
+	case G_ELI_VERSION_02:
+	case G_ELI_VERSION_03:
+	case G_ELI_VERSION_04:
+	case G_ELI_VERSION_05:
+	case G_ELI_VERSION_06:
+		eli_metadata_encode_v1v2v3v4v5v6(md, &p);
+		break;
+	default:
+#ifdef _KERNEL
+		panic("%s: Unsupported version %u.", __func__,
+		    (u_int)md->md_version);
+#else
+		assert(!"Unsupported metadata version.");
+#endif
+	}
 	MD5Init(&ctx);
 	MD5Update(&ctx, data, p - data);
 	MD5Final(md->md_hash, &ctx);



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