Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 May 2013 01:50:03 GMT
From:      Mark Linimon <linimon@lonesome.com>
To:        freebsd-geom@FreeBSD.org
Subject:   Re: kern/178359: [geom] [patch] geom_eli: support external metadata
Message-ID:  <201305070150.r471o36x005436@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/178359; it has been noted by GNATS.

From: Mark Linimon <linimon@lonesome.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata
Date: Mon, 6 May 2013 20:40:48 -0500

 ----- Forwarded message from Andrew Romanenko <melanhit@gmail.com> -----
 
 Date: Mon, 06 May 2013 14:29:11 +0300
 From: Andrew Romanenko <melanhit@gmail.com>
 To: Scot Hetzel <swhetzel@gmail.com>
 Cc: freebsd-bugs@freebsd.org, freebsd-geom@freebsd.org
 Subject: Re: kern/178359: [geom] [patch] geom_eli: support external metadata
 User-Agent: Mozilla/5.0 (X11; Linux i686;
 	rv:17.0) Gecko/20130407 Thunderbird/17.0.5
 
 Fixed, using '-H' for all methods
 (updated patch in the attachment)
 
 
 --- 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);
 
 ----- End forwarded message -----



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