From owner-svn-src-all@FreeBSD.ORG Tue Sep 16 08:40:53 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 33DFACF0; Tue, 16 Sep 2014 08:40:53 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1F15B977; Tue, 16 Sep 2014 08:40:53 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8G8eqdM033141; Tue, 16 Sep 2014 08:40:52 GMT (envelope-from cperciva@FreeBSD.org) Received: (from cperciva@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8G8eqR7033140; Tue, 16 Sep 2014 08:40:52 GMT (envelope-from cperciva@FreeBSD.org) Message-Id: <201409160840.s8G8eqR7033140@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: cperciva set sender to cperciva@FreeBSD.org using -f From: Colin Percival Date: Tue, 16 Sep 2014 08:40:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271664 - head/sys/geom/eli X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Sep 2014 08:40:53 -0000 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) {