svn commit: r271664 - head/sys/geom/eli

Colin Percival cperciva at FreeBSD.org
Tue Sep 16 08:40:53 UTC 2014


Author: cperciva
Date: Tue Sep 16 08:40:52 2014
New Revision: 271664
URL: http://svnweb.freebsd.org/changeset/base/271664

Log:
  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.
  
  When examining a new GELI provider, the most recently used passphrase
  will be attempted before prompting for a passphrase; and whenever a
  passphrase is entered, it is cached for later reference.  When the root
  disk is mounted, the cached passphrase is zeroed (triggered by the
  "mountroot" event), in order to minimize the possibility of leakage
  of passphrases.  (After root is mounted, the "taste and prompt for
  passphrases on the console" code path is disabled, so there is no
  potential for a passphrase to be stored after the zeroing takes place.)
  
  This behaviour can be disabled by setting kern.geom.eli.boot_passcache=0.
  
  Reviewed by:	pjd, dteske, allanjude
  MFC after:	7 days

Modified:
  head/sys/geom/eli/g_eli.c

Modified: head/sys/geom/eli/g_eli.c
==============================================================================
--- head/sys/geom/eli/g_eli.c	Tue Sep 16 05:45:38 2014	(r271663)
+++ head/sys/geom/eli/g_eli.c	Tue Sep 16 08:40:52 2014	(r271664)
@@ -82,6 +82,24 @@ u_int g_eli_batch = 0;
 SYSCTL_UINT(_kern_geom_eli, OID_AUTO, batch, CTLFLAG_RWTUN, &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,
@@ -1059,7 +1077,7 @@ g_eli_taste(struct g_class *mp, struct g
 		tries = g_eli_tries;
 	}
 
-	for (i = 0; i < tries; i++) {
+	for (i = 0; i <= tries; i++) {
 		g_eli_crypto_hmac_init(&ctx, NULL, 0);
 
 		/*
@@ -1083,9 +1101,19 @@ g_eli_taste(struct g_class *mp, struct g
 
 		/* 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));
+			}
 		}
 
 		/*
@@ -1115,15 +1143,18 @@ g_eli_taste(struct g_class *mp, struct g
 		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) {


More information about the svn-src-all mailing list