diff options
Diffstat (limited to 'sbin/geom')
-rw-r--r-- | sbin/geom/class/eli/geli.8 | 44 | ||||
-rw-r--r-- | sbin/geom/class/eli/geom_eli.c | 83 |
2 files changed, 110 insertions, 17 deletions
diff --git a/sbin/geom/class/eli/geli.8 b/sbin/geom/class/eli/geli.8 index 280962a..a39a601 100644 --- a/sbin/geom/class/eli/geli.8 +++ b/sbin/geom/class/eli/geli.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> +.\" Copyright (c) 2005-2008 Pawel Jakub Dawidek <pjd@FreeBSD.org> .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 16, 2006 +.Dd August 29, 2008 .Dt GELI 8 .Os .Sh NAME @@ -53,6 +53,7 @@ utility: .Cm init .Op Fl bPv .Op Fl a Ar aalgo +.Op Fl B Ar backupfile .Op Fl e Ar ealgo .Op Fl i Ar iterations .Op Fl K Ar newkeyfile @@ -206,6 +207,14 @@ indicates an action to be performed: Initialize provider which needs to be encrypted. Here you can set up the cryptographic algorithm to use, key length, etc. The last provider's sector is used to store metadata. +The +.Cm init +subcommand also automatically backups metadata in +.Pa /var/backups/<prov>.eli +file. +The metadata can be recovered with the +.Cm restore +subcommand described below. .Pp Additional options include: .Bl -tag -width ".Fl a Ar aalgo" @@ -233,6 +242,13 @@ One will still need bootable unencrypted storage with a .Pa /boot/ directory, which can be a CD-ROM disc or USB pen-drive, that can be removed after boot. +.It Fl B Ar backupfile +File name to use for metadata backup instead of the default +.Pa /var/backups/<prov>.eli . +To inhibit backups, you can use +.Pa none +as the +.Ar backupfile . .It Fl e Ar ealgo Encryption algorithm to use. Currently supported algorithms are: @@ -625,6 +641,30 @@ Enter passphrase: # newfs /dev/da0.eli # mount /dev/da0.eli /mnt/secret .Ed +.Pp +.Cm geli +backups metadata by default to the +.Pa /var/backups/<prov>.eli +file. +If metadata is lost in any way (eg. by accidental overwrite), it can be restored. +Consider the following situation: +.Bd -literal -offset indent +# geli init /dev/da0 +Enter new passphrase: +Reenter new passphrase: + +Metadata backup can be found in /var/backups/da0.eli and +can be restored with the following command: + + # geli restore /var/backups/da0.eli /dev/da0 + +# geli clear /dev/da0 +# geli attach /dev/da0 +geli: Cannot read metadata from /dev/da0: Invalid argument. +# geli restore /var/backups/da0.eli /dev/da0 +# geli attach /dev/da0 +Enter passphrase: +.Ed .Sh DATA AUTHENTICATION .Nm can verify data integrity when an authentication algorithm is specified. diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c index 2e16103..d772a9a 100644 --- a/sbin/geom/class/eli/geom_eli.c +++ b/sbin/geom/class/eli/geom_eli.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> + * Copyright (c) 2004-2008 Pawel Jakub Dawidek <pjd@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$"); uint32_t lib_version = G_LIB_VERSION; uint32_t version = G_ELI_VERSION; +#define GELI_BACKUP_DIR "/var/backups/" + static char aalgo[] = "none"; static char ealgo[] = "aes"; static intmax_t keylen = 0; @@ -61,6 +63,7 @@ static intmax_t keyno = -1; static intmax_t iterations = -1; static intmax_t sectorsize = 0; static char keyfile[] = "", newkeyfile[] = ""; +static char backupfile[] = ""; static void eli_main(struct gctl_req *req, unsigned flags); static void eli_init(struct gctl_req *req); @@ -74,10 +77,13 @@ static void eli_restore(struct gctl_req *req); static void eli_clear(struct gctl_req *req); static void eli_dump(struct gctl_req *req); +static int eli_backup_create(struct gctl_req *req, const char *prov, + const char *file); + /* * Available commands: * - * init [-bhPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov + * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov * label - alias for 'init' * attach [-dprv] [-k keyfile] prov * detach [-fl] prov ... @@ -97,6 +103,7 @@ struct g_command class_commands[] = { { { 'a', "aalgo", aalgo, G_TYPE_STRING }, { 'b', "boot", NULL, G_TYPE_BOOL }, + { 'B', "backupfile", backupfile, G_TYPE_STRING }, { 'e', "ealgo", ealgo, G_TYPE_STRING }, { 'i', "iterations", &iterations, G_TYPE_NUMBER }, { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, @@ -105,12 +112,13 @@ struct g_command class_commands[] = { { 's', "sectorsize", §orsize, G_TYPE_NUMBER }, G_OPT_SENTINEL }, - NULL, "[-bPv] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov" + NULL, "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov" }, { "label", G_FLAG_VERBOSE, eli_main, { { 'a', "aalgo", aalgo, G_TYPE_STRING }, { 'b', "boot", NULL, G_TYPE_BOOL }, + { 'B', "backupfile", backupfile, G_TYPE_STRING }, { 'e', "ealgo", ealgo, G_TYPE_STRING }, { 'i', "iterations", &iterations, G_TYPE_NUMBER }, { 'K', "newkeyfile", newkeyfile, G_TYPE_STRING }, @@ -514,6 +522,7 @@ eli_init(struct gctl_req *req) struct g_eli_metadata md; unsigned char sector[sizeof(struct g_eli_metadata)]; unsigned char key[G_ELI_USERKEYLEN]; + char backfile[MAXPATHLEN]; const char *str, *prov; unsigned secsize; off_t mediasize; @@ -648,6 +657,32 @@ eli_init(struct gctl_req *req) } 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. */ + const char *p = prov; + unsigned int i; + + if (strncmp(p, _PATH_DEV, strlen(_PATH_DEV)) == 0) + p += strlen(_PATH_DEV); + 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] = '_'; + } + } + 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); + } } static void @@ -887,6 +922,12 @@ eli_setkey(struct gctl_req *req) eli_setkey_attached(req, &md); else eli_setkey_detached(req, prov, &md); + + if (req->error == NULL || req->error[0] == '\0') { + printf("Note, that the master key encrypted with old keys " + "and/or passphrase may still exists in a metadata backup " + "file.\n"); + } } static void @@ -1022,24 +1063,16 @@ eli_kill(struct gctl_req *req) gctl_issue(req); } -static void -eli_backup(struct gctl_req *req) +static int +eli_backup_create(struct gctl_req *req, const char *prov, const char *file) { struct g_eli_metadata md; - const char *file, *prov; unsigned secsize; unsigned char *sector; off_t mediasize; - int nargs, filefd, provfd; - - nargs = gctl_get_int(req, "nargs"); - if (nargs != 2) { - gctl_error(req, "Invalid number of arguments."); - return; - } - prov = gctl_get_ascii(req, "arg0"); - file = gctl_get_ascii(req, "arg1"); + int filefd, provfd, ret; + ret = -1; provfd = filefd = -1; sector = NULL; secsize = 0; @@ -1092,6 +1125,8 @@ eli_backup(struct gctl_req *req) strerror(errno)); goto out; } + /* Success. */ + ret = 0; out: if (provfd > 0) close(provfd); @@ -1101,6 +1136,24 @@ out: bzero(sector, secsize); free(sector); } + return (ret); +} + +static void +eli_backup(struct gctl_req *req) +{ + const char *file, *prov; + int nargs; + + nargs = gctl_get_int(req, "nargs"); + if (nargs != 2) { + gctl_error(req, "Invalid number of arguments."); + return; + } + prov = gctl_get_ascii(req, "arg0"); + file = gctl_get_ascii(req, "arg1"); + + eli_backup_create(req, prov, file); } static void |