MFC r271664:

Cache GELI passphrases entered at the console during the boot process,
  in order to improve user-friendliness when a system has multiple disks
  encrypted using the same passphrase.

Relnotes:	yes
Approved by:	re (gjb)
This commit is contained in:
cperciva 2014-09-23 00:43:18 +00:00
parent 66312b96c4
commit 925d357775

View File

@ -88,6 +88,24 @@ TUNABLE_INT("kern.geom.eli.batch", &g_eli_batch);
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, batch, CTLFLAG_RW, &g_eli_batch, 0,
"Use crypto operations batching");
/*
* Passphrase cached during boot, in order to be more user-friendly if
* there are multiple providers using the same passphrase.
*/
static char cached_passphrase[256];
static u_int g_eli_boot_passcache = 1;
TUNABLE_INT("kern.geom.eli.boot_passcache", &g_eli_boot_passcache);
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, boot_passcache, CTLFLAG_RD,
&g_eli_boot_passcache, 0,
"Passphrases are cached during boot process for possible reuse");
static void
zero_boot_passcache(void * dummy)
{
memset(cached_passphrase, 0, sizeof(cached_passphrase));
}
EVENTHANDLER_DEFINE(mountroot, zero_boot_passcache, NULL, 0);
static eventhandler_tag g_eli_pre_sync = NULL;
static int g_eli_destroy_geom(struct gctl_req *req, struct g_class *mp,
@ -1065,7 +1083,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
tries = g_eli_tries;
}
for (i = 0; i < tries; i++) {
for (i = 0; i <= tries; i++) {
g_eli_crypto_hmac_init(&ctx, NULL, 0);
/*
@ -1089,9 +1107,19 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
/* Ask for the passphrase if defined. */
if (md.md_iterations >= 0) {
printf("Enter passphrase for %s: ", pp->name);
cngets(passphrase, sizeof(passphrase),
g_eli_visible_passphrase);
/* Try first with cached passphrase. */
if (i == 0) {
if (!g_eli_boot_passcache)
continue;
memcpy(passphrase, cached_passphrase,
sizeof(passphrase));
} else {
printf("Enter passphrase for %s: ", pp->name);
cngets(passphrase, sizeof(passphrase),
g_eli_visible_passphrase);
memcpy(cached_passphrase, passphrase,
sizeof(passphrase));
}
}
/*
@ -1121,15 +1149,18 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
bzero(key, sizeof(key));
if (error == -1) {
if (i == tries - 1) {
if (i == tries) {
G_ELI_DEBUG(0,
"Wrong key for %s. No tries left.",
pp->name);
g_eli_keyfiles_clear(pp->name);
return (NULL);
}
G_ELI_DEBUG(0, "Wrong key for %s. Tries left: %u.",
pp->name, tries - i - 1);
if (i > 0) {
G_ELI_DEBUG(0,
"Wrong key for %s. Tries left: %u.",
pp->name, tries - i);
}
/* Try again. */
continue;
} else if (error > 0) {