Hide length of geli passphrase during boot.

Introduce additional flag to the geli which allows to restore previous
behavior.

Reviewed by:	AllanJude@, cem@ (previous version)
MFC:		1 month
Relnotes:	yes
Differential Revision:	https://reviews.freebsd.org/D11751
This commit is contained in:
Mariusz Zaborski 2017-08-26 14:07:24 +00:00
parent b92e8635f9
commit 3453dc72ad
9 changed files with 211 additions and 119 deletions

View File

@ -51,6 +51,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
****************************** SPECIAL WARNING: ****************************** ****************************** SPECIAL WARNING: ******************************
20170826:
During boot the geli passphrase will be hidden. To restore previous
behavior see geli(8) configuration options.
20170825: 20170825:
Move PMTUD blackhole counters to TCPSTATS and remove them from bare Move PMTUD blackhole counters to TCPSTATS and remove them from bare
sysctl values. Minor nit, but requires a rebuild of both world/kernel sysctl values. Minor nit, but requires a rebuild of both world/kernel

View File

@ -24,7 +24,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd August 3, 2016 .Dd August 26, 2017
.Dt GELI 8 .Dt GELI 8
.Os .Os
.Sh NAME .Sh NAME
@ -51,7 +51,7 @@ utility:
.Pp .Pp
.Nm .Nm
.Cm init .Cm init
.Op Fl bgPTv .Op Fl bdgPTv
.Op Fl a Ar aalgo .Op Fl a Ar aalgo
.Op Fl B Ar backupfile .Op Fl B Ar backupfile
.Op Fl e Ar ealgo .Op Fl e Ar ealgo
@ -88,7 +88,7 @@ utility:
.Ar prov .Ar prov
.Nm .Nm
.Cm configure .Cm configure
.Op Fl bBgGtT .Op Fl bBdDgGtT
.Ar prov ... .Ar prov ...
.Nm .Nm
.Cm setkey .Cm setkey
@ -279,6 +279,9 @@ To inhibit backups, you can use
.Pa none .Pa none
as the as the
.Ar backupfile . .Ar backupfile .
.It Fl d
While booting from this encrypted root filesystem enable visibility of
passphrase length.
.It Fl e Ar ealgo .It Fl e Ar ealgo
Encryption algorithm to use. Encryption algorithm to use.
Currently supported algorithms are: Currently supported algorithms are:
@ -490,6 +493,12 @@ For more information, see the description of the
subcommand. subcommand.
.It Fl B .It Fl B
Remove the BOOT flag from the given providers. Remove the BOOT flag from the given providers.
.It Fl d
While booting from this encrypted root filesystem enable visibility of
passphrase length.
.It Fl D
While booting from this encrypted root filesystem disable visibility of
passphrase length.
.It Fl g .It Fl g
Enable booting from this encrypted root filesystem. Enable booting from this encrypted root filesystem.
The boot loader prompts for the passphrase and loads The boot loader prompts for the passphrase and loads

View File

@ -82,7 +82,7 @@ static int eli_backup_create(struct gctl_req *req, const char *prov,
/* /*
* Available commands: * Available commands:
* *
* init [-bgPTv] [-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' * label - alias for 'init'
* attach [-dprv] [-j passfile] [-k keyfile] prov * attach [-dprv] [-j passfile] [-k keyfile] prov
* detach [-fl] prov ... * detach [-fl] prov ...
@ -107,6 +107,7 @@ struct g_command class_commands[] = {
{ 'a', "aalgo", "", G_TYPE_STRING }, { 'a', "aalgo", "", G_TYPE_STRING },
{ 'b', "boot", NULL, G_TYPE_BOOL }, { 'b', "boot", NULL, G_TYPE_BOOL },
{ 'B', "backupfile", "", G_TYPE_STRING }, { 'B', "backupfile", "", G_TYPE_STRING },
{ 'd', "displaypass", NULL, G_TYPE_BOOL },
{ 'e', "ealgo", "", G_TYPE_STRING }, { 'e', "ealgo", "", G_TYPE_STRING },
{ 'g', "geliboot", NULL, G_TYPE_BOOL }, { 'g', "geliboot", NULL, G_TYPE_BOOL },
{ 'i', "iterations", "-1", G_TYPE_NUMBER }, { 'i', "iterations", "-1", G_TYPE_NUMBER },
@ -119,13 +120,14 @@ struct g_command class_commands[] = {
{ 'V', "mdversion", "-1", G_TYPE_NUMBER }, { 'V', "mdversion", "-1", G_TYPE_NUMBER },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
"[-bgPTv] [-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, { "label", G_FLAG_VERBOSE, eli_main,
{ {
{ 'a', "aalgo", "", G_TYPE_STRING }, { 'a', "aalgo", "", G_TYPE_STRING },
{ 'b', "boot", NULL, G_TYPE_BOOL }, { 'b', "boot", NULL, G_TYPE_BOOL },
{ 'B', "backupfile", "", G_TYPE_STRING }, { 'B', "backupfile", "", G_TYPE_STRING },
{ 'd', "displaypass", NULL, G_TYPE_BOOL },
{ 'e', "ealgo", "", G_TYPE_STRING }, { 'e', "ealgo", "", G_TYPE_STRING },
{ 'g', "geliboot", NULL, G_TYPE_BOOL }, { 'g', "geliboot", NULL, G_TYPE_BOOL },
{ 'i', "iterations", "-1", G_TYPE_NUMBER }, { 'i', "iterations", "-1", G_TYPE_NUMBER },
@ -182,13 +184,15 @@ struct g_command class_commands[] = {
{ {
{ 'b', "boot", NULL, G_TYPE_BOOL }, { 'b', "boot", NULL, G_TYPE_BOOL },
{ 'B', "noboot", NULL, G_TYPE_BOOL }, { 'B', "noboot", NULL, G_TYPE_BOOL },
{ 'd', "displaypass", NULL, G_TYPE_BOOL },
{ 'D', "nodisplaypass", NULL, G_TYPE_BOOL },
{ 'g', "geliboot", NULL, G_TYPE_BOOL }, { 'g', "geliboot", NULL, G_TYPE_BOOL },
{ 'G', "nogeliboot", NULL, G_TYPE_BOOL }, { 'G', "nogeliboot", NULL, G_TYPE_BOOL },
{ 't', "trim", NULL, G_TYPE_BOOL }, { 't', "trim", NULL, G_TYPE_BOOL },
{ 'T', "notrim", NULL, G_TYPE_BOOL }, { 'T', "notrim", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
"[-bBgGtT] prov ..." "[-bBdDgGtT] prov ..."
}, },
{ "setkey", G_FLAG_VERBOSE, eli_main, { "setkey", G_FLAG_VERBOSE, eli_main,
{ {
@ -708,6 +712,8 @@ eli_init(struct gctl_req *req)
md.md_flags |= G_ELI_FLAG_BOOT; md.md_flags |= G_ELI_FLAG_BOOT;
if (gctl_get_int(req, "geliboot")) if (gctl_get_int(req, "geliboot"))
md.md_flags |= G_ELI_FLAG_GELIBOOT; md.md_flags |= G_ELI_FLAG_GELIBOOT;
if (gctl_get_int(req, "displaypass"))
md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
if (gctl_get_int(req, "notrim")) if (gctl_get_int(req, "notrim"))
md.md_flags |= G_ELI_FLAG_NODELETE; md.md_flags |= G_ELI_FLAG_NODELETE;
md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1;
@ -912,7 +918,7 @@ eli_attach(struct gctl_req *req)
static void static void
eli_configure_detached(struct gctl_req *req, const char *prov, int boot, eli_configure_detached(struct gctl_req *req, const char *prov, int boot,
int geliboot, int trim) int geliboot, int displaypass, int trim)
{ {
struct g_eli_metadata md; struct g_eli_metadata md;
bool changed = 0; bool changed = 0;
@ -948,6 +954,21 @@ eli_configure_detached(struct gctl_req *req, const char *prov, int boot,
changed = 1; changed = 1;
} }
if (displaypass == 1 && (md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
if (verbose)
printf("GELIDISPLAYPASS flag already configured for %s.\n", prov);
} else if (displaypass == 0 &&
!(md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
if (verbose)
printf("GELIDISPLAYPASS flag not configured for %s.\n", prov);
} else if (displaypass >= 0) {
if (displaypass)
md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
else
md.md_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS;
changed = 1;
}
if (trim == 0 && (md.md_flags & G_ELI_FLAG_NODELETE)) { if (trim == 0 && (md.md_flags & G_ELI_FLAG_NODELETE)) {
if (verbose) if (verbose)
printf("TRIM disable flag already configured for %s.\n", prov); printf("TRIM disable flag already configured for %s.\n", prov);
@ -971,8 +992,9 @@ static void
eli_configure(struct gctl_req *req) eli_configure(struct gctl_req *req)
{ {
const char *prov; const char *prov;
bool boot, noboot, geliboot, nogeliboot, trim, notrim; bool boot, noboot, geliboot, nogeliboot, displaypass, nodisplaypass;
int doboot, dogeliboot, dotrim; bool trim, notrim;
int doboot, dogeliboot, dodisplaypass, dotrim;
int i, nargs; int i, nargs;
nargs = gctl_get_int(req, "nargs"); nargs = gctl_get_int(req, "nargs");
@ -985,6 +1007,8 @@ eli_configure(struct gctl_req *req)
noboot = gctl_get_int(req, "noboot"); noboot = gctl_get_int(req, "noboot");
geliboot = gctl_get_int(req, "geliboot"); geliboot = gctl_get_int(req, "geliboot");
nogeliboot = gctl_get_int(req, "nogeliboot"); nogeliboot = gctl_get_int(req, "nogeliboot");
displaypass = gctl_get_int(req, "displaypass");
nodisplaypass = gctl_get_int(req, "nodisplaypass");
trim = gctl_get_int(req, "trim"); trim = gctl_get_int(req, "trim");
notrim = gctl_get_int(req, "notrim"); notrim = gctl_get_int(req, "notrim");
@ -1008,6 +1032,16 @@ eli_configure(struct gctl_req *req)
else if (nogeliboot) else if (nogeliboot)
dogeliboot = 0; dogeliboot = 0;
dodisplaypass = -1;
if (displaypass && nodisplaypass) {
gctl_error(req, "Options -d and -D are mutually exclusive.");
return;
}
if (displaypass)
dodisplaypass = 1;
else if (nodisplaypass)
dodisplaypass = 0;
dotrim = -1; dotrim = -1;
if (trim && notrim) { if (trim && notrim) {
gctl_error(req, "Options -t and -T are mutually exclusive."); gctl_error(req, "Options -t and -T are mutually exclusive.");
@ -1018,7 +1052,8 @@ eli_configure(struct gctl_req *req)
else if (notrim) else if (notrim)
dotrim = 0; dotrim = 0;
if (doboot == -1 && dogeliboot == -1 && dotrim == -1) { if (doboot == -1 && dogeliboot == -1 && dodisplaypass == -1 &&
dotrim == -1) {
gctl_error(req, "No option given."); gctl_error(req, "No option given.");
return; return;
} }
@ -1028,8 +1063,10 @@ eli_configure(struct gctl_req *req)
/* Now the rest. */ /* Now the rest. */
for (i = 0; i < nargs; i++) { for (i = 0; i < nargs; i++) {
prov = gctl_get_ascii(req, "arg%d", i); prov = gctl_get_ascii(req, "arg%d", i);
if (!eli_is_attached(prov)) if (!eli_is_attached(prov)) {
eli_configure_detached(req, prov, doboot, dogeliboot, dotrim); eli_configure_detached(req, prov, doboot, dogeliboot,
dodisplaypass, dotrim);
}
} }
} }

View File

@ -220,8 +220,9 @@ geli_taste(int read_func(void *vdev, void *priv, off_t off, void *buf,
/* /*
* Attempt to decrypt the device * Attempt to decrypt the device
*/ */
int static int
geli_attach(struct dsk *dskp, const char *passphrase, const u_char *mkeyp) geli_attach(struct geli_entry *ge, struct dsk *dskp, const char *passphrase,
const u_char *mkeyp)
{ {
u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN], *mkp; u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN], *mkp;
u_int keynum; u_int keynum;
@ -233,92 +234,83 @@ geli_attach(struct dsk *dskp, const char *passphrase, const u_char *mkeyp)
explicit_bzero(mkeyp, G_ELI_DATAIVKEYLEN); explicit_bzero(mkeyp, G_ELI_DATAIVKEYLEN);
} }
SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) { if (mkeyp != NULL || geli_findkey(ge, dskp, mkey) == 0) {
if (geli_same_device(geli_e, dskp) != 0) { goto found_key;
continue;
}
if (mkeyp != NULL || geli_findkey(geli_e, dskp, mkey) == 0) {
goto found_key;
}
g_eli_crypto_hmac_init(&ctx, NULL, 0);
/*
* Prepare Derived-Key from the user passphrase.
*/
if (geli_e->md.md_iterations < 0) {
/* XXX TODO: Support loading key files. */
return (1);
} else if (geli_e->md.md_iterations == 0) {
g_eli_crypto_hmac_update(&ctx, geli_e->md.md_salt,
sizeof(geli_e->md.md_salt));
g_eli_crypto_hmac_update(&ctx, passphrase,
strlen(passphrase));
} else if (geli_e->md.md_iterations > 0) {
printf("Calculating GELI Decryption Key disk%dp%d @ %d"
" iterations...\n", dskp->unit,
(dskp->slice > 0 ? dskp->slice : dskp->part),
geli_e->md.md_iterations);
u_char dkey[G_ELI_USERKEYLEN];
pkcs5v2_genkey(dkey, sizeof(dkey), geli_e->md.md_salt,
sizeof(geli_e->md.md_salt), passphrase,
geli_e->md.md_iterations);
g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
explicit_bzero(dkey, sizeof(dkey));
}
g_eli_crypto_hmac_final(&ctx, key, 0);
error = g_eli_mkey_decrypt(&geli_e->md, key, mkey, &keynum);
if (error == -1) {
explicit_bzero(mkey, sizeof(mkey));
explicit_bzero(key, sizeof(key));
printf("Bad GELI key: bad password?\n");
return (error);
} else if (error != 0) {
explicit_bzero(mkey, sizeof(mkey));
explicit_bzero(key, sizeof(key));
printf("Failed to decrypt GELI master key: %d\n", error);
return (error);
} else {
/* Add key to keychain */
save_key(key);
explicit_bzero(&key, sizeof(key));
}
found_key:
/* Store the keys */
bcopy(mkey, geli_e->sc.sc_mkey, sizeof(geli_e->sc.sc_mkey));
bcopy(mkey, geli_e->sc.sc_ivkey, sizeof(geli_e->sc.sc_ivkey));
mkp = mkey + sizeof(geli_e->sc.sc_ivkey);
if ((geli_e->sc.sc_flags & G_ELI_FLAG_AUTH) == 0) {
bcopy(mkp, geli_e->sc.sc_ekey, G_ELI_DATAKEYLEN);
} else {
/*
* The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
*/
g_eli_crypto_hmac(mkp, G_ELI_MAXKEYLEN, "\x10", 1,
geli_e->sc.sc_ekey, 0);
}
explicit_bzero(mkey, sizeof(mkey));
/* Initialize the per-sector IV. */
switch (geli_e->sc.sc_ealgo) {
case CRYPTO_AES_XTS:
break;
default:
SHA256_Init(&geli_e->sc.sc_ivctx);
SHA256_Update(&geli_e->sc.sc_ivctx, geli_e->sc.sc_ivkey,
sizeof(geli_e->sc.sc_ivkey));
break;
}
return (0);
} }
/* Disk not found. */ g_eli_crypto_hmac_init(&ctx, NULL, 0);
return (2); /*
* Prepare Derived-Key from the user passphrase.
*/
if (geli_e->md.md_iterations < 0) {
/* XXX TODO: Support loading key files. */
return (1);
} else if (geli_e->md.md_iterations == 0) {
g_eli_crypto_hmac_update(&ctx, geli_e->md.md_salt,
sizeof(geli_e->md.md_salt));
g_eli_crypto_hmac_update(&ctx, passphrase,
strlen(passphrase));
} else if (geli_e->md.md_iterations > 0) {
printf("Calculating GELI Decryption Key disk%dp%d @ %d"
" iterations...\n", dskp->unit,
(dskp->slice > 0 ? dskp->slice : dskp->part),
geli_e->md.md_iterations);
u_char dkey[G_ELI_USERKEYLEN];
pkcs5v2_genkey(dkey, sizeof(dkey), geli_e->md.md_salt,
sizeof(geli_e->md.md_salt), passphrase,
geli_e->md.md_iterations);
g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
explicit_bzero(dkey, sizeof(dkey));
}
g_eli_crypto_hmac_final(&ctx, key, 0);
error = g_eli_mkey_decrypt(&geli_e->md, key, mkey, &keynum);
if (error == -1) {
explicit_bzero(mkey, sizeof(mkey));
explicit_bzero(key, sizeof(key));
printf("Bad GELI key: bad password?\n");
return (error);
} else if (error != 0) {
explicit_bzero(mkey, sizeof(mkey));
explicit_bzero(key, sizeof(key));
printf("Failed to decrypt GELI master key: %d\n", error);
return (error);
} else {
/* Add key to keychain */
save_key(key);
explicit_bzero(&key, sizeof(key));
}
found_key:
/* Store the keys */
bcopy(mkey, geli_e->sc.sc_mkey, sizeof(geli_e->sc.sc_mkey));
bcopy(mkey, geli_e->sc.sc_ivkey, sizeof(geli_e->sc.sc_ivkey));
mkp = mkey + sizeof(geli_e->sc.sc_ivkey);
if ((geli_e->sc.sc_flags & G_ELI_FLAG_AUTH) == 0) {
bcopy(mkp, geli_e->sc.sc_ekey, G_ELI_DATAKEYLEN);
} else {
/*
* The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
*/
g_eli_crypto_hmac(mkp, G_ELI_MAXKEYLEN, "\x10", 1,
geli_e->sc.sc_ekey, 0);
}
explicit_bzero(mkey, sizeof(mkey));
/* Initialize the per-sector IV. */
switch (geli_e->sc.sc_ealgo) {
case CRYPTO_AES_XTS:
break;
default:
SHA256_Init(&geli_e->sc.sc_ivctx);
SHA256_Update(&geli_e->sc.sc_ivctx, geli_e->sc.sc_ivkey,
sizeof(geli_e->sc.sc_ivkey));
break;
}
return (0);
} }
int int
@ -402,7 +394,7 @@ geli_havekey(struct dsk *dskp)
} }
if (geli_findkey(geli_e, dskp, mkey) == 0) { if (geli_findkey(geli_e, dskp, mkey) == 0) {
if (geli_attach(dskp, NULL, mkey) == 0) { if (geli_attach(geli_e, dskp, NULL, mkey) == 0) {
return (0); return (0);
} }
} }
@ -417,20 +409,28 @@ geli_passphrase(char *pw, int disk, int parttype, int part, struct dsk *dskp)
{ {
int i; int i;
/* TODO: Implement GELI keyfile(s) support */ SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
for (i = 0; i < 3; i++) { if (geli_same_device(geli_e, dskp) != 0) {
/* Try cached passphrase */ continue;
if (i == 0 && pw[0] != '\0') { }
if (geli_attach(dskp, pw, NULL) == 0) {
/* TODO: Implement GELI keyfile(s) support */
for (i = 0; i < 3; i++) {
/* Try cached passphrase */
if (i == 0 && pw[0] != '\0') {
if (geli_attach(geli_e, dskp, pw, NULL) == 0) {
return (0);
}
}
printf("GELI Passphrase for disk%d%c%d: ", disk,
parttype, part);
pwgets(pw, GELI_PW_MAXLEN,
(geli_e->md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS) == 0);
printf("\n");
if (geli_attach(geli_e, dskp, pw, NULL) == 0) {
return (0); return (0);
} }
} }
printf("GELI Passphrase for disk%d%c%d: ", disk, parttype, part);
pwgets(pw, GELI_PW_MAXLEN);
printf("\n");
if (geli_attach(dskp, pw, NULL) == 0) {
return (0);
}
} }
return (1); return (1);

View File

@ -46,12 +46,11 @@
#define GELI_MAX_KEYS 64 #define GELI_MAX_KEYS 64
#define GELI_PW_MAXLEN 256 #define GELI_PW_MAXLEN 256
extern void pwgets(char *buf, int n); extern void pwgets(char *buf, int n, int hide);
void geli_init(void); void geli_init(void);
int geli_taste(int read_func(void *vdev, void *priv, off_t off, int geli_taste(int read_func(void *vdev, void *priv, off_t off,
void *buf, size_t bytes), struct dsk *dsk, daddr_t lastsector); void *buf, size_t bytes), struct dsk *dsk, daddr_t lastsector);
int geli_attach(struct dsk *dskp, const char *passphrase, const u_char *mkeyp);
int is_geli(struct dsk *dsk); int is_geli(struct dsk *dsk);
int geli_read(struct dsk *dsk, off_t offset, u_char *buf, size_t bytes); int geli_read(struct dsk *dsk, off_t offset, u_char *buf, size_t bytes);
int geli_decrypt(u_int algo, u_char *data, size_t datasize, int geli_decrypt(u_int algo, u_char *data, size_t datasize,

View File

@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$");
/* gets() with constrained input length, for passwords */ /* gets() with constrained input length, for passwords */
void void
pwgets(char *buf, int n) pwgets(char *buf, int n, int hide)
{ {
int c; int c;
char *lp; char *lp;
@ -55,9 +55,11 @@ pwgets(char *buf, int n)
case '\177': case '\177':
if (lp > buf) { if (lp > buf) {
lp--; lp--;
putchar('\b'); if (hide == 0) {
putchar(' '); putchar('\b');
putchar('\b'); putchar(' ');
putchar('\b');
}
} }
break; break;
case 'u'&037: case 'u'&037:
@ -68,7 +70,9 @@ pwgets(char *buf, int n)
default: default:
if ((n < 1) || ((lp - buf) < n - 1)) { if ((n < 1) || ((lp - buf) < n - 1)) {
*lp++ = c; *lp++ = c;
putchar('*'); if (hide == 0) {
putchar('*');
}
} }
} }
/*NOTREACHED*/ /*NOTREACHED*/

View File

@ -1023,7 +1023,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
struct hmac_ctx ctx; struct hmac_ctx ctx;
char passphrase[256]; char passphrase[256];
u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN];
u_int i, nkey, nkeyfiles, tries; u_int i, nkey, nkeyfiles, tries, showpass;
int error; int error;
struct keybuf *keybuf; struct keybuf *keybuf;
@ -1112,8 +1112,11 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
sizeof(passphrase)); sizeof(passphrase));
} else { } else {
printf("Enter passphrase for %s: ", pp->name); printf("Enter passphrase for %s: ", pp->name);
showpass = g_eli_visible_passphrase;
if ((md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS) != 0)
showpass = GETS_ECHOPASS;
cngets(passphrase, sizeof(passphrase), cngets(passphrase, sizeof(passphrase),
g_eli_visible_passphrase); showpass);
memcpy(cached_passphrase, passphrase, memcpy(cached_passphrase, passphrase,
sizeof(passphrase)); sizeof(passphrase));
} }
@ -1232,6 +1235,7 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
ADD_FLAG(G_ELI_FLAG_RO, "READ-ONLY"); ADD_FLAG(G_ELI_FLAG_RO, "READ-ONLY");
ADD_FLAG(G_ELI_FLAG_NODELETE, "NODELETE"); ADD_FLAG(G_ELI_FLAG_NODELETE, "NODELETE");
ADD_FLAG(G_ELI_FLAG_GELIBOOT, "GELIBOOT"); ADD_FLAG(G_ELI_FLAG_GELIBOOT, "GELIBOOT");
ADD_FLAG(G_ELI_FLAG_GELIDISPLAYPASS, "GELIDISPLAYPASS");
#undef ADD_FLAG #undef ADD_FLAG
} }
sbuf_printf(sb, "</Flags>\n"); sbuf_printf(sb, "</Flags>\n");

View File

@ -100,6 +100,8 @@
#define G_ELI_FLAG_NODELETE 0x00000040 #define G_ELI_FLAG_NODELETE 0x00000040
/* This GELI supports GELIBoot */ /* This GELI supports GELIBoot */
#define G_ELI_FLAG_GELIBOOT 0x00000080 #define G_ELI_FLAG_GELIBOOT 0x00000080
/* Hide passphrase length in GELIboot. */
#define G_ELI_FLAG_GELIDISPLAYPASS 0x00000100
/* RUNTIME FLAGS. */ /* RUNTIME FLAGS. */
/* Provider was open for writing. */ /* Provider was open for writing. */
#define G_ELI_FLAG_WOPEN 0x00010000 #define G_ELI_FLAG_WOPEN 0x00010000

View File

@ -377,6 +377,7 @@ g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
const char *prov; const char *prov;
u_char *sector; u_char *sector;
int *nargs, *boot, *noboot, *trim, *notrim, *geliboot, *nogeliboot; int *nargs, *boot, *noboot, *trim, *notrim, *geliboot, *nogeliboot;
int *displaypass, *nodisplaypass;
int zero, error, changed; int zero, error, changed;
u_int i; u_int i;
@ -434,6 +435,19 @@ g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
if (*geliboot || *nogeliboot) if (*geliboot || *nogeliboot)
changed = 1; changed = 1;
displaypass = gctl_get_paraml(req, "displaypass", sizeof(*displaypass));
if (displaypass == NULL)
displaypass = &zero;
nodisplaypass = gctl_get_paraml(req, "nodisplaypass", sizeof(*nodisplaypass));
if (nodisplaypass == NULL)
nodisplaypass = &zero;
if (*displaypass && *nodisplaypass) {
gctl_error(req, "Options -d and -D are mutually exclusive.");
return;
}
if (*displaypass || *nodisplaypass)
changed = 1;
if (!changed) { if (!changed) {
gctl_error(req, "No option given."); gctl_error(req, "No option given.");
return; return;
@ -492,6 +506,17 @@ g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
continue; continue;
} }
if (*displaypass && (sc->sc_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
G_ELI_DEBUG(1, "GELIDISPLAYPASS flag already configured for %s.",
prov);
continue;
} else if (*nodisplaypass &&
!(sc->sc_flags & G_ELI_FLAG_GELIDISPLAYPASS)) {
G_ELI_DEBUG(1, "GELIDISPLAYPASS flag not configured for %s.",
prov);
continue;
}
if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) { if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) {
/* /*
* ONETIME providers don't write metadata to * ONETIME providers don't write metadata to
@ -535,6 +560,14 @@ g_eli_ctl_configure(struct gctl_req *req, struct g_class *mp)
sc->sc_flags &= ~G_ELI_FLAG_GELIBOOT; sc->sc_flags &= ~G_ELI_FLAG_GELIBOOT;
} }
if (*displaypass) {
md.md_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
sc->sc_flags |= G_ELI_FLAG_GELIDISPLAYPASS;
} else if (*nodisplaypass) {
md.md_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS;
sc->sc_flags &= ~G_ELI_FLAG_GELIDISPLAYPASS;
}
if (sc->sc_flags & G_ELI_FLAG_ONETIME) { if (sc->sc_flags & G_ELI_FLAG_ONETIME) {
/* There's no metadata on disk so we are done here. */ /* There's no metadata on disk so we are done here. */
continue; continue;