summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/geom/class/eli/geli.840
-rw-r--r--sbin/geom/class/eli/geom_eli.c51
-rw-r--r--sys/geom/eli/g_eli.c2
-rw-r--r--sys/geom/eli/g_eli.h59
4 files changed, 140 insertions, 12 deletions
diff --git a/sbin/geom/class/eli/geli.8 b/sbin/geom/class/eli/geli.8
index 59361ec..d6b607f 100644
--- a/sbin/geom/class/eli/geli.8
+++ b/sbin/geom/class/eli/geli.8
@@ -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
diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c
index f3553c5..f209800 100644
--- a/sbin/geom/class/eli/geom_eli.c
+++ b/sbin/geom/class/eli/geom_eli.c
@@ -82,7 +82,7 @@ static int eli_backup_create(struct gctl_req *req, const char *prov,
/*
* 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;
diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c
index fce52ae..b5e4f7b 100644
--- a/sys/geom/eli/g_eli.c
+++ b/sys/geom/eli/g_eli.c
@@ -713,6 +713,7 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
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 char *indent, struct g_geom *gp,
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:
diff --git a/sys/geom/eli/g_eli.h b/sys/geom/eli/g_eli.h
index 0f35cd6..0b48db2 100644
--- a/sys/geom/eli/g_eli.h
+++ b/sys/geom/eli/g_eli.h
@@ -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_metadata *md, u_char *data)
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);
OpenPOWER on IntegriCloud