kern/178359: geom_eli: support external metadata
Andrew Romanenko
melanhit at gmail.com
Sun May 5 23:10:01 UTC 2013
>Number: 178359
>Category: kern
>Synopsis: geom_eli: support external metadata
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Sun May 05 23:10:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator: Andrew Romanenko
>Release: FreeBSD 9.1-STABLE i386
>Organization:
UA BSD
>Environment:
System: FreeBSD ion.uabsd.org 9.1-STABLE FreeBSD 9.1-STABLE #0 r250121: Wed May 1 23:38:36 EEST 2013 root at ion.uabsd.org:/usr/obj/usr/src/sys/GENERIC i386
>Description:
Add support external metadata for geom eli.
For i386 all works fine.
Need check manpage for grammatical errors (i don't spell english very well)
>How-To-Repeat:
>Fix:
--- geli.patch begins here ---
--- sbin/geom/class/eli/geom_eli.c.orig 2013-05-03 00:00:34.551720905 +0300
+++ sbin/geom/class/eli/geom_eli.c 2013-05-05 23:57:52.631347936 +0300
@@ -60,7 +60,6 @@
#define GELI_BACKUP_DIR "/var/backups/"
#define GELI_ENC_ALGO "aes"
-
static void eli_main(struct gctl_req *req, unsigned flags);
static void eli_init(struct gctl_req *req);
static void eli_attach(struct gctl_req *req);
@@ -81,23 +80,23 @@
/*
* Available commands:
*
- * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov
+ * init [-bPv] [-a aalgo] [-B backupfile] [-H headerfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov
* label - alias for 'init'
- * attach [-dprv] [-j passfile] [-k keyfile] prov
+ * attach [-dprv] [-h headerfile] [-j passfile] [-k keyfile] prov
* detach [-fl] prov ...
* stop - alias for 'detach'
* onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov
- * configure [-bB] prov ...
- * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov
- * delkey [-afv] [-n keyno] prov
+ * configure [-bB] [-h headerfile] prov ...
+ * setkey [-pPv] [-h headerfile] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov
+ * delkey [-afv] [-h headerfile] [-n keyno] prov
* suspend [-v] -a | prov ...
- * resume [-pv] [-j passfile] [-k keyfile] prov
+ * resume [-pv] [-h headerfile] [-j passfile] [-k keyfile] prov
* kill [-av] [prov ...]
* backup [-v] prov file
* restore [-fv] file prov
- * resize [-v] -s oldsize prov
+ * resize [-v] [-h headerfile] -s oldsize prov
* clear [-v] prov ...
- * dump [-v] prov ...
+ * dump [-v] [-h headerfile] prov ...
*/
struct g_command class_commands[] = {
{ "init", G_FLAG_VERBOSE, eli_main,
@@ -112,9 +111,10 @@
{ 'l', "keylen", "0", G_TYPE_NUMBER },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
{ 's', "sectorsize", "0", G_TYPE_NUMBER },
+ { 'H', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
- "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov"
+ "[-bPv] [-H headerfile] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov"
},
{ "label", G_FLAG_VERBOSE, eli_main,
{
@@ -128,6 +128,7 @@
{ 'l', "keylen", "0", G_TYPE_NUMBER },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
{ 's', "sectorsize", "0", G_TYPE_NUMBER },
+ { 'h', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
"- an alias for 'init'"
@@ -139,9 +140,10 @@
{ 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL },
{ 'r', "readonly", NULL, G_TYPE_BOOL },
+ { 'h', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
- "[-dprv] [-j passfile] [-k keyfile] prov"
+ "[-dprv] [-h headerfile] [-j passfile] [-k keyfile] prov"
},
{ "detach", 0, NULL,
{
@@ -174,9 +176,10 @@
{
{ 'b', "boot", NULL, G_TYPE_BOOL },
{ 'B', "noboot", NULL, G_TYPE_BOOL },
+ { 'h', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
- "[-bB] prov ..."
+ "[-bB] [-h headerfile] prov ..."
},
{ "setkey", G_FLAG_VERBOSE, eli_main,
{
@@ -188,18 +191,20 @@
{ 'n', "keyno", "-1", G_TYPE_NUMBER },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
+ { 'h', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
- "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov"
+ "[-pPv] [-h headerfile] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov"
},
{ "delkey", G_FLAG_VERBOSE, eli_main,
{
{ 'a', "all", NULL, G_TYPE_BOOL },
{ 'f', "force", NULL, G_TYPE_BOOL },
{ 'n', "keyno", "-1", G_TYPE_NUMBER },
+ { 'h', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
- "[-afv] [-n keyno] prov"
+ "[-afv] [-h headerfile] [-n keyno] prov"
},
{ "suspend", G_FLAG_VERBOSE, NULL,
{
@@ -213,9 +218,10 @@
{ 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL },
+ { 'h', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
- "[-pv] [-j passfile] [-k keyfile] prov"
+ "[-pv] [-h headerfile] [-j passfile] [-k keyfile] prov"
},
{ "kill", G_FLAG_VERBOSE, eli_main,
{
@@ -237,15 +243,20 @@
{ "resize", G_FLAG_VERBOSE, eli_main,
{
{ 's', "oldsize", NULL, G_TYPE_NUMBER },
+ { 'h', "header", "", G_TYPE_STRING },
G_OPT_SENTINEL
},
- "[-v] -s oldsize prov"
+ "[-v] [-h headerfile] -s oldsize prov"
},
{ "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS,
"[-v] prov ..."
},
- { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS,
- "[-v] prov ..."
+ { "dump", G_FLAG_VERBOSE, eli_main,
+ {
+ { 'h', "header", "", G_TYPE_STRING },
+ G_OPT_SENTINEL
+ },
+ "[-v] [-h headerfile] prov ..."
},
G_CMD_SENTINEL
};
@@ -653,7 +664,7 @@
unsigned char sector[sizeof(struct g_eli_metadata)];
unsigned char key[G_ELI_USERKEYLEN];
char backfile[MAXPATHLEN];
- const char *str, *prov;
+ const char *str, *prov, *header;
unsigned secsize;
off_t mediasize;
intmax_t val;
@@ -776,17 +787,39 @@
return;
}
+ header = gctl_get_ascii(req, "header");
+
+ /* Store header if it present */
+ if(header[0] != '\0') {
+ error = eli_metadata_store(req, header, &md);
+
+ if(error != 0) {
+ gctl_error(req, "Cannot store header %s: %s.", header,
+ strerror(error));
+ return;
+ }
+
+ str = gctl_get_ascii(req, "backupfile");
+ if(str[0] != '\0')
+ if(strcmp(str, "none") != 0)
+ printf("Warning: options -B and -h are mutualy exlusive\n");
+
+ return;
+ }
+
eli_metadata_encode(&md, sector);
bzero(&md, sizeof(md));
+
error = g_metadata_store(prov, sector, sizeof(sector));
bzero(sector, sizeof(sector));
if (error != 0) {
gctl_error(req, "Cannot store metadata on %s: %s.", prov,
- strerror(error));
+ strerror(error));
return;
}
if (verbose)
printf("Metadata value stored on %s.\n", prov);
+
/* Backup metadata to a file. */
str = gctl_get_ascii(req, "backupfile");
if (str[0] != '\0') {
@@ -820,10 +853,14 @@
{
struct g_eli_metadata md;
unsigned char key[G_ELI_USERKEYLEN];
- const char *prov;
+ unsigned char *hd;
+ const char *prov, *str, *header;
off_t mediasize;
+ ssize_t hdsize;
int nargs;
+ hd = NULL;
+
nargs = gctl_get_int(req, "nargs");
if (nargs != 1) {
gctl_error(req, "Invalid number of arguments.");
@@ -831,9 +868,16 @@
}
prov = gctl_get_ascii(req, "arg0");
- if (eli_metadata_read(req, prov, &md) == -1)
+ header = gctl_get_ascii(req, "header");
+ if (header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
+ if (eli_metadata_read(req, str, &md) == -1)
return;
+ hdsize = g_get_sectorsize(prov);
mediasize = g_get_mediasize(prov);
if (md.md_provsize != (uint64_t)mediasize) {
gctl_error(req, "Provider size mismatch.");
@@ -845,20 +889,43 @@
return;
}
+ if(header[0] != '\0') {
+ hd = malloc(hdsize);
+ if(hd == NULL) {
+ gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
+ return;
+ }
+
+ bzero(hd, hdsize);
+ eli_metadata_encode(&md, hd);
+ } else {
+ hdsize = sizeof(hd);
+ }
+
+ gctl_ro_param(req, "hd", hdsize, hd);
gctl_ro_param(req, "key", sizeof(key), key);
if (gctl_issue(req) == NULL) {
if (verbose)
printf("Attached to %s.\n", prov);
}
bzero(key, sizeof(key));
+ if(hd != NULL)
+ free(hd);
}
static void
eli_configure_detached(struct gctl_req *req, const char *prov, bool boot)
{
struct g_eli_metadata md;
+ const char *str, *header;
- if (eli_metadata_read(req, prov, &md) == -1)
+ header = gctl_get_ascii(req, "header");
+ if (header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
+ if (eli_metadata_read(req, str, &md) == -1)
return;
if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) {
@@ -872,7 +939,13 @@
md.md_flags |= G_ELI_FLAG_BOOT;
else
md.md_flags &= ~G_ELI_FLAG_BOOT;
- eli_metadata_store(req, prov, &md);
+
+ if(header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
+ eli_metadata_store(req, str, &md);
}
bzero(&md, sizeof(md));
}
@@ -880,7 +953,7 @@
static void
eli_configure(struct gctl_req *req)
{
- const char *prov;
+ const char *prov, *header;
bool boot, noboot;
int i, nargs;
@@ -902,14 +975,29 @@
return;
}
+ header = gctl_get_ascii(req, "header");
+
/* First attached providers. */
- gctl_issue(req);
+ if(header[0] != '\0') {
+ if(nargs != 1) {
+ gctl_error(req, "Too many arguments.");
+ return;
+ }
+
+ prov = gctl_get_ascii(req, "arg0");
+ eli_configure_detached(req, prov, boot);
+ return;
+ } else {
+ gctl_issue(req);
+ }
+
/* Now the rest. */
for (i = 0; i < nargs; i++) {
prov = gctl_get_ascii(req, "arg%d", i);
if (!eli_is_attached(prov))
eli_configure_detached(req, prov, boot);
}
+
}
static void
@@ -950,6 +1038,7 @@
eli_setkey_detached(struct gctl_req *req, const char *prov,
struct g_eli_metadata *md)
{
+ const char *header, *str;
unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN];
unsigned char *mkeydst;
unsigned int nkey;
@@ -1035,7 +1124,14 @@
}
/* Store metadata with fresh key. */
- eli_metadata_store(req, prov, md);
+ header = gctl_get_ascii(req, "header");
+ if(header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
+ eli_metadata_store(req, str, md);
+
bzero(md, sizeof(*md));
}
@@ -1043,7 +1139,7 @@
eli_setkey(struct gctl_req *req)
{
struct g_eli_metadata md;
- const char *prov;
+ const char *prov, *header, *str;
int nargs;
nargs = gctl_get_int(req, "nargs");
@@ -1053,10 +1149,16 @@
}
prov = gctl_get_ascii(req, "arg0");
- if (eli_metadata_read(req, prov, &md) == -1)
+ header = gctl_get_ascii(req, "header");
+ if(header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
+ if (eli_metadata_read(req, str, &md) == -1)
return;
- if (eli_is_attached(prov))
+ if (eli_is_attached(prov) && header[0] == '\0')
eli_setkey_attached(req, &md);
else
eli_setkey_detached(req, prov, &md);
@@ -1079,12 +1181,19 @@
eli_delkey_detached(struct gctl_req *req, const char *prov)
{
struct g_eli_metadata md;
+ const char *header, *str;
unsigned char *mkeydst;
unsigned int nkey;
intmax_t val;
bool all, force;
- if (eli_metadata_read(req, prov, &md) == -1)
+ header = gctl_get_ascii(req, "header");
+ if(header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
+ if (eli_metadata_read(req, str, &md) == -1)
return;
all = gctl_get_int(req, "all");
@@ -1116,6 +1225,11 @@
arc4rand(mkeydst, G_ELI_MKEYLEN);
}
+ if(header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
eli_metadata_store(req, prov, &md);
bzero(&md, sizeof(md));
}
@@ -1123,7 +1237,7 @@
static void
eli_delkey(struct gctl_req *req)
{
- const char *prov;
+ const char *prov, *header;
int nargs;
nargs = gctl_get_int(req, "nargs");
@@ -1133,7 +1247,9 @@
}
prov = gctl_get_ascii(req, "arg0");
- if (eli_is_attached(prov))
+ header = gctl_get_ascii(req, "header");
+
+ if (eli_is_attached(prov) && header[0] == '\0')
eli_delkey_attached(req, prov);
else
eli_delkey_detached(req, prov);
@@ -1144,10 +1260,14 @@
{
struct g_eli_metadata md;
unsigned char key[G_ELI_USERKEYLEN];
- const char *prov;
+ unsigned char *hd;
+ const char *prov, *str, *header;
off_t mediasize;
+ ssize_t hdsize;
int nargs;
+ hd = NULL;
+
nargs = gctl_get_int(req, "nargs");
if (nargs != 1) {
gctl_error(req, "Invalid number of arguments.");
@@ -1155,10 +1275,18 @@
}
prov = gctl_get_ascii(req, "arg0");
- if (eli_metadata_read(req, prov, &md) == -1)
+ header = gctl_get_ascii(req, "header");
+ if (header[0] != '\0')
+ str = header;
+ else
+ str = prov;
+
+ if (eli_metadata_read(req, str, &md) == -1)
return;
mediasize = g_get_mediasize(prov);
+ hdsize = g_get_sectorsize(prov);
+
if (md.md_provsize != (uint64_t)mediasize) {
gctl_error(req, "Provider size mismatch.");
return;
@@ -1169,12 +1297,30 @@
return;
}
+ if(header[0] != '\0') {
+ hd = malloc(hdsize);
+ if(hd == NULL) {
+ gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
+ return;
+ }
+
+ bzero(hd, hdsize);
+ eli_metadata_encode(&md, hd);
+ } else {
+ hdsize = sizeof(hd);
+ }
+
+ gctl_ro_param(req, "hd", hdsize, hd);
gctl_ro_param(req, "key", sizeof(key), key);
+
if (gctl_issue(req) == NULL) {
if (verbose)
printf("Resumed %s.\n", prov);
}
bzero(key, sizeof(key));
+
+ if(hd != NULL)
+ free(hd);
}
static int
@@ -1469,11 +1615,11 @@
eli_resize(struct gctl_req *req)
{
struct g_eli_metadata md;
- const char *prov;
+ const char *prov, *header;
unsigned char *sector;
ssize_t secsize;
off_t mediasize, oldsize;
- int nargs, provfd;
+ int nargs, provfd, error;
nargs = gctl_get_int(req, "nargs");
if (nargs != 1) {
@@ -1486,14 +1632,18 @@
sector = NULL;
secsize = 0;
- provfd = g_open(prov, 1);
- if (provfd == -1) {
- gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno));
- goto out;
+ header = gctl_get_ascii(req, "header");
+
+ if(header[0] == '\0') {
+ provfd = g_open(prov, 1);
+ if (provfd == -1) {
+ gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno));
+ goto out;
+ }
}
- mediasize = g_mediasize(provfd);
- secsize = g_sectorsize(provfd);
+ mediasize = g_get_mediasize(prov);
+ secsize = g_get_sectorsize(prov);
if (mediasize == -1 || secsize == -1) {
gctl_error(req, "Cannot get information about %s: %s.", prov,
strerror(errno));
@@ -1517,16 +1667,24 @@
}
/* Read metadata from the 'oldsize' offset. */
- if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) {
- gctl_error(req, "Cannot read old metadata: %s.",
- strerror(errno));
- goto out;
- }
+ if(header[0] != '\0') {
+ if (eli_metadata_read(req, header, &md) == -1) {
+ gctl_error(req, "Cannot read old metadata: %s.",
+ header);
+ goto out;
+ }
+ } else {
+ if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) {
+ gctl_error(req, "Cannot read old metadata: %s.",
+ strerror(errno));
+ goto out;
+ }
- /* Check if this sector contains geli metadata. */
- if (eli_metadata_decode(sector, &md) != 0) {
- gctl_error(req, "MD5 hash mismatch: no metadata for oldsize.");
- goto out;
+ /* Check if this sector contains geli metadata. */
+ if (eli_metadata_decode(sector, &md) != 0) {
+ gctl_error(req, "MD5 hash mismatch: no metadata for oldsize.");
+ goto out;
+ }
}
/*
@@ -1544,15 +1702,25 @@
*/
md.md_provsize = mediasize;
eli_metadata_encode(&md, sector);
- if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) {
- gctl_error(req, "Cannot write metadata: %s.", strerror(errno));
- goto out;
- }
- (void)g_flush(provfd);
- /* Now trash the old metadata. */
- if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1)
- goto out;
+ if(header[0] != '\0') {
+ error = eli_metadata_store(req, header, &md);
+ if(error != 0) {
+ gctl_error(req, "Cannot store header %s: %s.", header,
+ strerror(error));
+ goto out;
+ }
+ } else {
+ if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) {
+ gctl_error(req, "Cannot write metadata: %s.", strerror(errno));
+ goto out;
+ }
+ (void)g_flush(provfd);
+
+ /* Now trash the old metadata. */
+ if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1)
+ goto out;
+ }
out:
if (provfd >= 0)
(void)g_close(provfd);
@@ -1592,7 +1760,7 @@
eli_dump(struct gctl_req *req)
{
struct g_eli_metadata md, tmpmd;
- const char *name;
+ const char *name, *header;
int error, i, nargs;
nargs = gctl_get_int(req, "nargs");
@@ -1601,15 +1769,40 @@
return;
}
- for (i = 0; i < nargs; i++) {
- name = gctl_get_ascii(req, "arg%d", i);
- error = g_metadata_read(name, (unsigned char *)&tmpmd,
- sizeof(tmpmd), G_ELI_MAGIC);
- if (error != 0) {
+ header = gctl_get_ascii(req, "header");
+ if(header[0] != '\0') {
+ if(nargs != 1) {
+ gctl_error(req, "Too many arguments.");
+ return;
+ }
+
+ if (eli_metadata_read(req, header, &tmpmd) == -1)
+ return;
+
+ name = gctl_get_ascii(req, "arg0");
+
+ if (strcmp(tmpmd.md_magic, G_ELI_MAGIC) != 0) {
+ error = EINVAL;
fprintf(stderr, "Cannot read metadata from %s: %s.\n",
- name, strerror(error));
+ name, strerror(error));
gctl_error(req, "Not fully done.");
- continue;
+ return;
+ }
+
+ name = header;
+ }
+
+ for (i = 0; i < nargs; i++) {
+ if(header[0] == '\0') {
+ name = gctl_get_ascii(req, "arg%d", i);
+ error = g_metadata_read(name, (unsigned char *)&tmpmd,
+ sizeof(tmpmd), G_ELI_MAGIC);
+ if (error != 0) {
+ fprintf(stderr, "Cannot read metadata from %s: %s.\n",
+ name, strerror(error));
+ gctl_error(req, "Not fully done.");
+ continue;
+ }
}
if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) {
fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n",
--- sbin/geom/class/eli/geli.8.orig 2013-04-29 01:45:56.000000000 +0300
+++ sbin/geom/class/eli/geli.8 2013-05-05 16:49:57.642188841 +0300
@@ -52,6 +52,7 @@
.Nm
.Cm init
.Op Fl bPv
+.Op Fl H Ar headerfile
.Op Fl a Ar aalgo
.Op Fl B Ar backupfile
.Op Fl e Ar ealgo
@@ -67,6 +68,7 @@
.Nm
.Cm attach
.Op Fl dprv
+.Op Fl h Ar headerfile
.Op Fl j Ar passfile
.Op Fl k Ar keyfile
.Ar prov
@@ -88,10 +90,12 @@
.Nm
.Cm configure
.Op Fl bB
+.Op Fl h Ar headerfile
.Ar prov ...
.Nm
.Cm setkey
.Op Fl pPv
+.Op Fl h Ar headerfile
.Op Fl i Ar iterations
.Op Fl j Ar passfile
.Op Fl J Ar newpassfile
@@ -102,6 +106,7 @@
.Nm
.Cm delkey
.Op Fl afv
+.Op Fl h Ar headerfile
.Op Fl n Ar keyno
.Ar prov
.Nm
@@ -125,12 +130,14 @@
.Nm
.Cm resume
.Op Fl pv
+.Op Fl h Ar headerfile
.Op Fl j Ar passfile
.Op Fl k Ar keyfile
.Ar prov
.Nm
.Cm resize
.Op Fl v
+.Op Fl h Ar headerfile
.Fl s Ar oldsize
.Ar prov
.Nm
@@ -140,6 +147,7 @@
.Nm
.Cm dump
.Op Fl v
+.Op Fl h Ar headerfile
.Ar prov ...
.Nm
.Cm list
@@ -240,6 +248,8 @@
.Pp
Additional options include:
.Bl -tag -width ".Fl J Ar newpassfile"
+.It Fl h Ar headerfile
+Store GELI metadata (header) in the external file
.It Fl a Ar aalgo
Enable data integrity verification (authentication) using the given algorithm.
This will reduce size of available storage and also reduce speed.
@@ -341,6 +351,8 @@
option for the
.Cm detach
subcommand.
+.It Fl h Ar headerfile
+Read metadata from a file instead from a provider
.It Fl j Ar passfile
Specifies a file which contains the passphrase or its part.
For more information see the description of the
@@ -415,7 +427,9 @@
Change configuration of the given providers.
.Pp
Additional options include:
-.Bl -tag -width ".Fl b"
+.Bl -tag -width ".Fl h Ar headerfile"
+.It Fl h Ar headerfile
+Handle external metadata
.It Fl b
Set the BOOT flag on the given providers.
For more information, see the description of the
@@ -437,6 +451,8 @@
.Pp
Additional options include:
.Bl -tag -width ".Fl J Ar newpassfile"
+.It Fl h Ar headerfile
+Handle external metadata
.It Fl i Ar iterations
Number of iterations to use with PKCS#5v2.
If 0 is given, PKCS#5v2 will not be used.
@@ -472,7 +488,9 @@
subcommand.
.Pp
Additional options include:
-.Bl -tag -width ".Fl a Ar keyno"
+.Bl -tag -width ".Fl h Ar headerfile"
+.It Fl h Ar headerfile
+Handle external metadata
.It Fl a
Destroy all keys (does not need
.Fl f
@@ -567,7 +585,9 @@
utility is stored is bad idea.
.Pp
Additional options include:
-.Bl -tag -width ".Fl j Ar passfile"
+.Bl -tag -width ".Fl h Ar headerfile"
+.It Fl h Ar headerfile
+Handle external metadata
.It Fl j Ar passfile
Specifies a file which contains the passphrase or its part.
For more information see the description of the
@@ -593,7 +613,9 @@
provider and the provider size is updated.
.Pp
Additional options include:
-.Bl -tag -width ".Fl s Ar oldsize"
+.Bl -tag -width ".Fl h Ar headerfile"
+.It Fl h Ar headerfile
+Handle external metadata
.It Fl s Ar oldsize
The size of the provider before it was resized.
.El
@@ -764,6 +786,9 @@
# dd if=/dev/random of=/dev/da1s3a bs=1m
# dd if=/dev/random of=/boot/keys/da1s3a.key bs=128k count=1
# geli init -b -P -K /boot/keys/da1s3a.key da1s3a
+# dd if=/dev/random of=/dev/ada1 bs=1m
+# dd if=/dev/random of=/boot/keys/ada1.key bs=8 count=8
+# geli init -b -H /boot/hd/ada1.hd -P -K /boot/keys/ada1.key ada1
.Ed
.Pp
The providers are initialized, now we have to add those lines to
@@ -782,6 +807,13 @@
geli_da1s3a_keyfile0_load="YES"
geli_da1s3a_keyfile0_type="da1s3a:geli_keyfile0"
geli_da1s3a_keyfile0_name="/boot/keys/da1s3a.key"
+
+geli_ada1_header_load="YES"
+geli_ada1_header_type="ada1:geli_header"
+geli_ada1_header_name="/boot/hd/ada1.hd"
+geli_ada1_keyfile0_load="YES"
+geli_ada1_keyfile0_type="ada1:geli_keyfile0"
+geli_ada1_keyfile0_name="/boot/keys/ada1.key"
.Ed
.Pp
Not only configure encryption, but also data integrity verification using
--- sys/geom/eli/g_eli_ctl.c.orig 2013-05-04 01:21:45.381136674 +0300
+++ sys/geom/eli/g_eli_ctl.c 2013-05-05 03:20:20.180243224 +0300
@@ -56,10 +56,11 @@
struct g_eli_metadata md;
struct g_provider *pp;
const char *name;
- u_char *key, mkey[G_ELI_DATAIVKEYLEN];
+ u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN];
int *nargs, *detach, *readonly;
int keysize, error;
u_int nkey;
+ ssize_t hdsize;
g_topology_assert();
@@ -97,11 +98,18 @@
gctl_error(req, "Provider %s is invalid.", name);
return;
}
- error = g_eli_read_metadata(mp, pp, &md);
- if (error != 0) {
- gctl_error(req, "Cannot read metadata from %s (error=%d).",
- name, error);
- return;
+
+ hd = gctl_get_param(req, "hd", &hdsize);
+
+ if(hdsize == pp->sectorsize) {
+ eli_metadata_decode(hd, &md);
+ } else {
+ error = g_eli_read_metadata(mp, pp, &md);
+ if (error != 0) {
+ gctl_error(req, "Cannot read metadata from %s (error=%d).",
+ name, error);
+ return;
+ }
}
if (md.md_keys == 0x00) {
bzero(&md, sizeof(md));
@@ -448,8 +456,8 @@
error = g_eli_read_metadata(mp, pp, &md);
if (error != 0) {
gctl_error(req,
- "Cannot read metadata from %s (error=%d).",
- prov, error);
+ "Cannot read metadata from %s (error=%d).",
+ prov, error);
continue;
}
@@ -464,12 +472,13 @@
sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
eli_metadata_encode(&md, sector);
error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
- pp->sectorsize);
+ pp->sectorsize);
if (error != 0) {
gctl_error(req,
- "Cannot store metadata on %s (error=%d).",
- prov, error);
+ "Cannot store metadata on %s (error=%d).",
+ prov, error);
}
+
bzero(&md, sizeof(md));
bzero(sector, sizeof(sector));
free(sector, M_ELI);
@@ -815,9 +824,10 @@
struct g_provider *pp;
struct g_consumer *cp;
const char *name;
- u_char *key, mkey[G_ELI_DATAIVKEYLEN];
+ u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN];
int *nargs, keysize, error;
u_int nkey;
+ ssize_t hdsize;
g_topology_assert();
@@ -843,12 +853,20 @@
}
cp = LIST_FIRST(&sc->sc_geom->consumer);
pp = cp->provider;
- error = g_eli_read_metadata(mp, pp, &md);
- if (error != 0) {
- gctl_error(req, "Cannot read metadata from %s (error=%d).",
- name, error);
- return;
+
+ hd = gctl_get_param(req, "hd", &hdsize);
+
+ if(hdsize == pp->sectorsize) {
+ eli_metadata_decode(hd, &md);
+ } else {
+ error = g_eli_read_metadata(mp, pp, &md);
+ if (error != 0) {
+ gctl_error(req, "Cannot read metadata from %s (error=%d).",
+ name, error);
+ return;
+ }
}
+
if (md.md_keys == 0x00) {
bzero(&md, sizeof(md));
gctl_error(req, "No valid keys on %s.", pp->name);
--- geli.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list