Page MenuHomeFreeBSD

D16115.id44820.diff
No OneTemporary

D16115.id44820.diff

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

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)

Event Timeline