Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F132937306
D16115.id44820.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D16115.id44820.diff
View Options
Index: lib/geom/eli/geli.8
===================================================================
--- lib/geom/eli/geli.8
+++ lib/geom/eli/geli.8
@@ -61,7 +61,7 @@
.Op Fl l Ar keylen
.Op Fl s Ar sectorsize
.Op Fl V Ar version
-.Ar prov
+.Ar prov ...
.Nm
.Cm label - an alias for
.Cm init
@@ -233,10 +233,14 @@
indicates an action to be performed:
.Bl -tag -width ".Cm configure"
.It Cm init
-Initialize the provider which needs to be encrypted.
+Initialize providers which need to be encrypted.
+If multiple providers are listed as arguments, they will all be initialized
+with the same passphrase and/or User Key.
+Unique salt will be randomly generated for each provider to ensure the
+Master Key for each is unique.
Here you can set up the cryptographic algorithm to use, Data Key length,
etc.
-The last sector of the provider is used to store metadata.
+The last sector of the providers is used to store metadata.
The
.Cm init
subcommand also automatically writes metadata backups to
@@ -279,6 +283,16 @@
.Pa none
as the
.Ar backupfile .
+If multiple providers were initialized in the one command, you can use
+.Pa PROV
+(all upper-case) in the file name, and it will be replaced with the provider
+name.
+If
+.Pa PROV
+is not found in the file name and multiple providers were initialized in the
+one command,
+.Pa -<prov>
+will be appended to the end of the file name specified.
.It Fl d
When entering the passphrase to boot from this encrypted root filesystem, echo
.Ql *
Index: lib/geom/eli/geom_eli.c
===================================================================
--- lib/geom/eli/geom_eli.c
+++ lib/geom/eli/geom_eli.c
@@ -91,7 +91,7 @@
/*
* Available commands:
*
- * init [-bdgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov
+ * 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] [-n keyno] [-j passfile] [-k keyfile] prov ...
* detach [-fl] prov ...
@@ -129,7 +129,7 @@
{ 'V', "mdversion", "-1", G_TYPE_NUMBER },
G_OPT_SENTINEL
},
- "[-bdgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov"
+ "[-bdgPTv] [-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,
{
@@ -695,6 +695,7 @@
eli_init(struct gctl_req *req)
{
struct g_eli_metadata md;
+ struct gctl_req *r;
unsigned char sector[sizeof(struct g_eli_metadata)] __aligned(4);
unsigned char key[G_ELI_USERKEYLEN];
char backfile[MAXPATHLEN];
@@ -702,21 +703,14 @@
unsigned int secsize, version;
off_t mediasize;
intmax_t val;
- int error, nargs;
+ int error, i, nargs, nparams, param;
+ const int one = 1;
nargs = gctl_get_int(req, "nargs");
- if (nargs != 1) {
- gctl_error(req, "Invalid number of arguments.");
+ if (nargs == 0) {
+ gctl_error(req, "Too few arguments.");
return;
}
- prov = gctl_get_ascii(req, "arg0");
- mediasize = g_get_mediasize(prov);
- secsize = g_get_sectorsize(prov);
- if (mediasize == 0 || secsize == 0) {
- gctl_error(req, "Cannot get informations about %s: %s.", prov,
- strerror(errno));
- return;
- }
explicit_bzero(&md, sizeof(md));
strlcpy(md.md_magic, G_ELI_MAGIC, sizeof(md.md_magic));
@@ -809,7 +803,6 @@
gctl_error(req, "Invalid key length.");
return;
}
- md.md_provsize = mediasize;
val = gctl_get_intmax(req, "iterations");
if (val != -1) {
@@ -829,78 +822,149 @@
md.md_iterations = val;
val = gctl_get_intmax(req, "sectorsize");
- if (val == 0)
- md.md_sectorsize = secsize;
- else {
- if (val < 0 || (val % secsize) != 0 || !powerof2(val)) {
- gctl_error(req, "Invalid sector size.");
- return;
- }
- if (val > sysconf(_SC_PAGE_SIZE)) {
- fprintf(stderr,
- "warning: Using sectorsize bigger than the page size!\n");
- }
- md.md_sectorsize = val;
+ if (val > sysconf(_SC_PAGE_SIZE)) {
+ fprintf(stderr,
+ "warning: Using sectorsize bigger than the page size!\n");
}
md.md_keys = 0x01;
- arc4random_buf(md.md_salt, sizeof(md.md_salt));
- arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys));
- /* Generate user key. */
- if (eli_genkey(req, &md, key, true) == NULL) {
+ /*
+ * Determine number of parameters in the parent geom request before the
+ * nargs parameter and list of providers.
+ */
+ nparams = req->narg - nargs - 1;
+
+ /* Create new child geom request for each provider and issue to kernel */
+ for (i = 0; i < nargs; i++) {
+ r = gctl_get_handle();
+
+ /* Copy each parameter from the parent request to the child request */
+ for (param = 0; param < nparams; param++) {
+ gctl_ro_param(r, req->arg[param].name, req->arg[param].len, req->arg[param].value);
+ }
+
+ /* Add a single provider to the parameter list of the child */
+ gctl_ro_param(r, "nargs", sizeof(one), &one);
+ prov = gctl_get_ascii(req, "arg%d", i);
+ gctl_ro_param(r, "arg0", -1, prov);
+
+ mediasize = g_get_mediasize(prov);
+ secsize = g_get_sectorsize(prov);
+ if (mediasize == 0 || secsize == 0) {
+ gctl_error(r, "Cannot get information about %s: %s.", prov,
+ strerror(errno));
+ goto out;
+ }
+
+ md.md_provsize = mediasize;
+
+ val = gctl_get_intmax(r, "sectorsize");
+ if (val == 0) {
+ md.md_sectorsize = secsize;
+ } else {
+ if (val < 0 || (val % secsize) != 0 || !powerof2(val)) {
+ gctl_error(r, "Invalid sector size.");
+ goto out;
+ }
+ md.md_sectorsize = val;
+ }
+
+ /* Use different salt and Master Key for each provider. */
+ arc4random_buf(md.md_salt, sizeof(md.md_salt));
+ arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys));
+
+ /* Generate user key. */
+ if (eli_genkey(r, &md, key, true) == NULL) {
+ explicit_bzero(key, sizeof(key));
+ explicit_bzero(&md, sizeof(md));
+ goto out;
+ }
+
+ /* Encrypt the first and the only Master Key. */
+ error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, md.md_mkeys);
explicit_bzero(key, sizeof(key));
- explicit_bzero(&md, sizeof(md));
- return;
- }
+ if (error != 0) {
+ explicit_bzero(&md, sizeof(md));
+ gctl_error(r, "Cannot encrypt Master Key: %s.",
+ strerror(error));
+ goto out;
+ }
- /* Encrypt the first and the only Master Key. */
- error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, md.md_mkeys);
- explicit_bzero(key, sizeof(key));
- if (error != 0) {
- explicit_bzero(&md, sizeof(md));
- gctl_error(req, "Cannot encrypt Master Key: %s.",
- strerror(error));
- return;
- }
+ eli_metadata_encode(&md, sector);
+ explicit_bzero(&md.md_provsize, sizeof(md.md_provsize));
+ explicit_bzero(&md.md_sectorsize, sizeof(md.md_sectorsize));
+ explicit_bzero(&md.md_salt, sizeof(md.md_salt));
+ explicit_bzero(&md.md_mkeys, sizeof(md.md_mkeys));
+ error = g_metadata_store(prov, sector, sizeof(sector));
+ explicit_bzero(sector, sizeof(sector));
+ if (error != 0) {
+ gctl_error(r, "Cannot store metadata on %s: %s.", prov,
+ strerror(error));
+ goto out;
+ }
+ if (verbose)
+ printf("Metadata value stored on %s.\n", prov);
- eli_metadata_encode(&md, sector);
- explicit_bzero(&md, sizeof(md));
- error = g_metadata_store(prov, sector, sizeof(sector));
- explicit_bzero(sector, sizeof(sector));
- if (error != 0) {
- gctl_error(req, "Cannot store metadata on %s: %s.", prov,
- 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') {
- /* Backupfile given be the user, just copy it. */
- strlcpy(backfile, str, sizeof(backfile));
- } else {
- /* Generate file name automatically. */
+ /* Backup metadata to a file. */
const char *p = prov;
- unsigned int i;
+ unsigned int j;
if (strncmp(p, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
p += sizeof(_PATH_DEV) - 1;
- snprintf(backfile, sizeof(backfile), "%s%s.eli",
- GELI_BACKUP_DIR, p);
- /* Replace all / with _. */
- for (i = strlen(GELI_BACKUP_DIR); backfile[i] != '\0'; i++) {
- if (backfile[i] == '/')
- backfile[i] = '_';
+
+ str = gctl_get_ascii(r, "backupfile");
+ if (str[0] != '\0') {
+ /* Backupfile given by the user, just copy it. */
+ strlcpy(backfile, str, sizeof(backfile));
+
+ /* Make the backup filename unique if multiple providers
+ * initialized in one command. */
+ if (nargs > 1) {
+ /* Replace first occurrence of "PROV" with provider name. */
+ str = strnstr(backfile, "PROV", sizeof(backfile));
+ if (str != NULL) {
+ char suffix[MAXPATHLEN];
+ j = str - backfile;
+ strlcpy(suffix, &backfile[j+4], sizeof(suffix));
+ backfile[j] = '\0';
+ strlcat(backfile, p, sizeof(backfile));
+ strlcat(backfile, suffix, sizeof(backfile));
+ } else {
+ /* "PROV" not found in backfile, append provider name. */
+ strlcat(backfile, "-", sizeof(backfile));
+ strlcat(backfile, p, sizeof(backfile));
+ }
+ }
+ } else {
+ /* Generate file name automatically. */
+ snprintf(backfile, sizeof(backfile), "%s%s.eli",
+ GELI_BACKUP_DIR, p);
+ /* Replace all / with _. */
+ for (j = strlen(GELI_BACKUP_DIR); backfile[j] != '\0'; j++) {
+ if (backfile[j] == '/')
+ backfile[j] = '_';
+ }
}
+ if (strcmp(backfile, "none") != 0 &&
+ eli_backup_create(r, prov, backfile) == 0) {
+ printf("\nMetadata backup for provider %s can be found in %s\n", prov, backfile);
+ printf("and can be restored with the following command:\n");
+ printf("\n\t# geli restore %s %s\n\n", backfile, prov);
+ }
+
+out:
+ /* Print error for this request, and set parent request error message */
+ if (r->error != NULL && r->error[0] != '\0') {
+ warnx("%s", r->error);
+ gctl_error(req, "There was an error with at least one provider.");
+ }
+
+ gctl_free(r);
}
- if (strcmp(backfile, "none") != 0 &&
- eli_backup_create(req, prov, backfile) == 0) {
- printf("\nMetadata backup can be found in %s and\n", backfile);
- printf("can be restored with the following command:\n");
- printf("\n\t# geli restore %s %s\n\n", backfile, prov);
- }
+
+ /* Clear the cached metadata, including keys. */
+ explicit_bzero(&md, sizeof(md));
}
static void
@@ -963,10 +1027,10 @@
}
/* Print error for this request, and set parent request error message */
- if (r->error != NULL && r->error[0] != '\0') {
- warnx("%s", r->error);
+ if (r->error != NULL && r->error[0] != '\0') {
+ warnx("%s", r->error);
gctl_error(req, "At least one provider failed to attach.");
- }
+ }
gctl_free(r);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Oct 22, 8:04 AM (10 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24013385
Default Alt Text
D16115.id44820.diff (10 KB)
Attached To
Mode
D16115: geli init multiple providers
Attached
Detach File
Event Timeline
Log In to Comment