Index: UPDATING =================================================================== --- UPDATING +++ UPDATING @@ -51,6 +51,10 @@ ****************************** SPECIAL WARNING: ****************************** +20170816: + During boot the geli passphrase will be hidden. To restore previous + behavior see geli(8) configuration options. + 20170722: Clang, llvm, lldb, compiler-rt and libc++ have been upgraded to 5.0.0. Please see the 20141231 entry below for information about prerequisites Index: sbin/geom/class/eli/geli.8 =================================================================== --- sbin/geom/class/eli/geli.8 +++ sbin/geom/class/eli/geli.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 3, 2016 +.Dd July 27, 2017 .Dt GELI 8 .Os .Sh NAME @@ -51,7 +51,7 @@ .Pp .Nm .Cm init -.Op Fl bgPTv +.Op Fl bghPTv .Op Fl a Ar aalgo .Op Fl B Ar backupfile .Op Fl e Ar ealgo @@ -88,7 +88,7 @@ .Ar prov .Nm .Cm configure -.Op Fl bBgGtT +.Op Fl bBgGHhtT .Ar prov ... .Nm .Cm setkey @@ -296,6 +296,9 @@ .It Fl g Enable booting from this encrypted root filesystem. The boot loader prompts for the passphrase and loads +.It Fl h +While booting from this encrypted root filesystem disable visibility of +passphrase length. .Xr loader 8 from the encrypted partition. .It Fl i Ar iterations @@ -497,6 +500,12 @@ from the encrypted partition. .It Fl G Deactivate booting from this encrypted root partition. +.It Fl h +While booting from this encrypted root filesystem disable visibility of +passphrase length. +.It Fl H +While booting from this encrypted root filesystem enable visibility of +passphrase length. .It Fl t Enable TRIM/UNMAP passthru. For more information, see the description of the Index: sbin/geom/class/eli/geom_eli.c =================================================================== --- sbin/geom/class/eli/geom_eli.c +++ sbin/geom/class/eli/geom_eli.c @@ -82,7 +82,7 @@ /* * Available commands: * - * init [-bgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov + * init [-bghPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov * label - alias for 'init' * attach [-dprv] [-j passfile] [-k keyfile] prov * detach [-fl] prov ... @@ -109,6 +109,7 @@ { 'B', "backupfile", "", G_TYPE_STRING }, { 'e', "ealgo", "", G_TYPE_STRING }, { 'g', "geliboot", NULL, G_TYPE_BOOL }, + { 'h', "hidepass", NULL, G_TYPE_BOOL }, { 'i', "iterations", "-1", G_TYPE_NUMBER }, { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, @@ -119,7 +120,7 @@ { 'V', "mdversion", "-1", G_TYPE_NUMBER }, G_OPT_SENTINEL }, - "[-bgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov" + "[-bghPTv] [-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, { @@ -128,6 +129,7 @@ { 'B', "backupfile", "", G_TYPE_STRING }, { 'e', "ealgo", "", G_TYPE_STRING }, { 'g', "geliboot", NULL, G_TYPE_BOOL }, + { 'h', "hidepass", NULL, G_TYPE_BOOL }, { 'i', "iterations", "-1", G_TYPE_NUMBER }, { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, @@ -184,11 +186,13 @@ { 'B', "noboot", NULL, G_TYPE_BOOL }, { 'g', "geliboot", NULL, G_TYPE_BOOL }, { 'G', "nogeliboot", NULL, G_TYPE_BOOL }, + { 'h', "hidepass", NULL, G_TYPE_BOOL }, + { 'H', "nohidepass", NULL, G_TYPE_BOOL }, { 't', "trim", NULL, G_TYPE_BOOL }, { 'T', "notrim", NULL, G_TYPE_BOOL }, G_OPT_SENTINEL }, - "[-bBgGtT] prov ..." + "[-bBgGhHtT] prov ..." }, { "setkey", G_FLAG_VERBOSE, eli_main, { @@ -708,6 +712,8 @@ md.md_flags |= G_ELI_FLAG_BOOT; if (gctl_get_int(req, "geliboot")) md.md_flags |= G_ELI_FLAG_GELIBOOT; + if (gctl_get_int(req, "hidepass")) + md.md_flags |= G_ELI_FLAG_GELIHIDEPASS; if (gctl_get_int(req, "notrim")) md.md_flags |= G_ELI_FLAG_NODELETE; md.md_ealgo = CRYPTO_ALGORITHM_MIN - 1; @@ -912,7 +918,7 @@ static void eli_configure_detached(struct gctl_req *req, const char *prov, int boot, - int geliboot, int trim) + int geliboot, int hidepass, int trim) { struct g_eli_metadata md; bool changed = 0; @@ -948,6 +954,20 @@ changed = 1; } + if (hidepass == 1 && (md.md_flags & G_ELI_FLAG_GELIHIDEPASS)) { + if (verbose) + printf("GELIHIDEPASS flag already configured for %s.\n", prov); + } else if (hidepass == 0 && !(md.md_flags & G_ELI_FLAG_GELIHIDEPASS)) { + if (verbose) + printf("GELIHIDEPASS flag not configured for %s.\n", prov); + } else if (hidepass >= 0) { + if (hidepass) + md.md_flags |= G_ELI_FLAG_GELIHIDEPASS; + else + md.md_flags &= ~G_ELI_FLAG_GELIHIDEPASS; + changed = 1; + } + if (trim == 0 && (md.md_flags & G_ELI_FLAG_NODELETE)) { if (verbose) printf("TRIM disable flag already configured for %s.\n", prov); @@ -971,8 +991,9 @@ eli_configure(struct gctl_req *req) { const char *prov; - bool boot, noboot, geliboot, nogeliboot, trim, notrim; - int doboot, dogeliboot, dotrim; + bool boot, noboot, geliboot, nogeliboot, hidepass, nohidepass; + bool trim, notrim; + int doboot, dogeliboot, dohidepass, dotrim; int i, nargs; nargs = gctl_get_int(req, "nargs"); @@ -985,6 +1006,8 @@ noboot = gctl_get_int(req, "noboot"); geliboot = gctl_get_int(req, "geliboot"); nogeliboot = gctl_get_int(req, "nogeliboot"); + hidepass = gctl_get_int(req, "hidepass"); + nohidepass = gctl_get_int(req, "nohidepass"); trim = gctl_get_int(req, "trim"); notrim = gctl_get_int(req, "notrim"); @@ -1008,6 +1031,16 @@ else if (nogeliboot) dogeliboot = 0; + dohidepass = -1; + if (hidepass && nohidepass) { + gctl_error(req, "Options -h and -H are mutually exclusive."); + return; + } + if (hidepass) + dohidepass = 1; + else if (nohidepass) + dohidepass = 0; + dotrim = -1; if (trim && notrim) { gctl_error(req, "Options -t and -T are mutually exclusive."); @@ -1018,7 +1051,8 @@ else if (notrim) dotrim = 0; - if (doboot == -1 && dogeliboot == -1 && dotrim == -1) { + if (doboot == -1 && dogeliboot == -1 && dohidepass == -1 && + dotrim == -1) { gctl_error(req, "No option given."); return; } @@ -1028,8 +1062,10 @@ /* 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, doboot, dogeliboot, dotrim); + if (!eli_is_attached(prov)) { + eli_configure_detached(req, prov, doboot, dogeliboot, + dohidepass, dotrim); + } } } Index: sys/boot/geli/geliboot.h =================================================================== --- sys/boot/geli/geliboot.h +++ sys/boot/geli/geliboot.h @@ -46,12 +46,11 @@ #define GELI_MAX_KEYS 64 #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); int geli_taste(int read_func(void *vdev, void *priv, off_t off, 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 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, Index: sys/boot/geli/geliboot.c =================================================================== --- sys/boot/geli/geliboot.c +++ sys/boot/geli/geliboot.c @@ -220,8 +220,9 @@ /* * Attempt to decrypt the device */ -int -geli_attach(struct dsk *dskp, const char *passphrase, const u_char *mkeyp) +static int +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_int keynum; @@ -233,12 +234,8 @@ explicit_bzero(mkeyp, G_ELI_DATAIVKEYLEN); } - SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) { - if (geli_same_device(geli_e, dskp) != 0) { - continue; - } - - if (mkeyp != NULL || geli_findkey(geli_e, dskp, mkey) == 0) { + { + if (mkeyp != NULL || geli_findkey(ge, dskp, mkey) == 0) { goto found_key; } @@ -313,12 +310,9 @@ sizeof(geli_e->sc.sc_ivkey)); break; } - - return (0); } - /* Disk not found. */ - return (2); + return (0); } int @@ -402,7 +396,7 @@ } 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); } } @@ -417,20 +411,28 @@ { int i; - /* TODO: Implement GELI keyfile(s) support */ - for (i = 0; i < 3; i++) { - /* Try cached passphrase */ - if (i == 0 && pw[0] != '\0') { - if (geli_attach(dskp, pw, NULL) == 0) { + SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) { + if (geli_same_device(geli_e, dskp) != 0) { + continue; + } + + /* 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_GELIHIDEPASS)); + printf("\n"); + 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); - printf("\n"); - if (geli_attach(dskp, pw, NULL) == 0) { - return (0); - } } return (1); Index: sys/boot/geli/pwgets.c =================================================================== --- sys/boot/geli/pwgets.c +++ sys/boot/geli/pwgets.c @@ -39,7 +39,7 @@ /* gets() with constrained input length, for passwords */ void -pwgets(char *buf, int n) +pwgets(char *buf, int n, int hide) { int c; char *lp; @@ -55,9 +55,11 @@ case '\177': if (lp > buf) { lp--; - putchar('\b'); - putchar(' '); - putchar('\b'); + if (hide == 0) { + putchar('\b'); + putchar(' '); + putchar('\b'); + } } break; case 'u'&037: @@ -68,7 +70,9 @@ default: if ((n < 1) || ((lp - buf) < n - 1)) { *lp++ = c; - putchar('*'); + if (hide == 0) { + putchar('*'); + } } } /*NOTREACHED*/ Index: sys/geom/eli/g_eli.h =================================================================== --- sys/geom/eli/g_eli.h +++ sys/geom/eli/g_eli.h @@ -100,6 +100,8 @@ #define G_ELI_FLAG_NODELETE 0x00000040 /* This GELI supports GELIBoot */ #define G_ELI_FLAG_GELIBOOT 0x00000080 +/* Hide passphrase length in GELIboot. */ +#define G_ELI_FLAG_GELIHIDEPASS 0x00000100 /* RUNTIME FLAGS. */ /* Provider was open for writing. */ #define G_ELI_FLAG_WOPEN 0x00010000 Index: sys/geom/eli/g_eli.c =================================================================== --- sys/geom/eli/g_eli.c +++ sys/geom/eli/g_eli.c @@ -1023,7 +1023,7 @@ struct hmac_ctx ctx; char passphrase[256]; 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; struct keybuf *keybuf; @@ -1112,8 +1112,11 @@ sizeof(passphrase)); } else { printf("Enter passphrase for %s: ", pp->name); + showpass = g_eli_visible_passphrase; + if ((md.md_flags & G_ELI_FLAG_GELIHIDEPASS) != 0) + showpass = GETS_NOECHO; cngets(passphrase, sizeof(passphrase), - g_eli_visible_passphrase); + showpass); memcpy(cached_passphrase, passphrase, sizeof(passphrase)); } @@ -1232,6 +1235,7 @@ ADD_FLAG(G_ELI_FLAG_RO, "READ-ONLY"); ADD_FLAG(G_ELI_FLAG_NODELETE, "NODELETE"); ADD_FLAG(G_ELI_FLAG_GELIBOOT, "GELIBOOT"); + ADD_FLAG(G_ELI_FLAG_GELIHIDEPASS, "GELIHIDEPASS"); #undef ADD_FLAG } sbuf_printf(sb, "\n"); Index: sys/geom/eli/g_eli_ctl.c =================================================================== --- sys/geom/eli/g_eli_ctl.c +++ sys/geom/eli/g_eli_ctl.c @@ -377,6 +377,7 @@ const char *prov; u_char *sector; int *nargs, *boot, *noboot, *trim, *notrim, *geliboot, *nogeliboot; + int *hidepass, *nohidepass; int zero, error, changed; u_int i; @@ -434,6 +435,19 @@ if (*geliboot || *nogeliboot) changed = 1; + hidepass = gctl_get_paraml(req, "hidepass", sizeof(*hidepass)); + if (hidepass == NULL) + hidepass = &zero; + nohidepass = gctl_get_paraml(req, "nohidepass", sizeof(*nohidepass)); + if (nohidepass == NULL) + nohidepass = &zero; + if (*hidepass && *nohidepass) { + gctl_error(req, "Options -h and -H are mutually exclusive."); + return; + } + if (*hidepass || *nohidepass) + changed = 1; + if (!changed) { gctl_error(req, "No option given."); return; @@ -492,6 +506,17 @@ continue; } + if (*hidepass && (sc->sc_flags & G_ELI_FLAG_GELIHIDEPASS)) { + G_ELI_DEBUG(1, "GELIHIDEPASS flag already configured for %s.", + prov); + continue; + } else if (*nohidepass && + !(sc->sc_flags & G_ELI_FLAG_GELIHIDEPASS)) { + G_ELI_DEBUG(1, "GELIHIDEPASS flag not configured for %s.", + prov); + continue; + } + if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) { /* * ONETIME providers don't write metadata to @@ -535,6 +560,14 @@ sc->sc_flags &= ~G_ELI_FLAG_GELIBOOT; } + if (*hidepass) { + md.md_flags |= G_ELI_FLAG_GELIHIDEPASS; + sc->sc_flags |= G_ELI_FLAG_GELIHIDEPASS; + } else if (*nohidepass) { + md.md_flags &= ~G_ELI_FLAG_GELIHIDEPASS; + sc->sc_flags &= ~G_ELI_FLAG_GELIHIDEPASS; + } + if (sc->sc_flags & G_ELI_FLAG_ONETIME) { /* There's no metadata on disk so we are done here. */ continue;