From owner-svn-src-all@freebsd.org Wed Feb 20 23:42:06 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id CE9DF14E130E; Wed, 20 Feb 2019 23:42:05 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 7ED4F75547; Wed, 20 Feb 2019 23:42:05 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 654AFCDAA; Wed, 20 Feb 2019 23:42:05 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x1KNg5IN086989; Wed, 20 Feb 2019 23:42:05 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x1KNg3qP086981; Wed, 20 Feb 2019 23:42:03 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201902202342.x1KNg3qP086981@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Wed, 20 Feb 2019 23:42:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r344397 - in stable/11: sbin/geom/class/eli stand/libsa/geli sys/geom/eli X-SVN-Group: stable-11 X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in stable/11: sbin/geom/class/eli stand/libsa/geli sys/geom/eli X-SVN-Commit-Revision: 344397 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 7ED4F75547 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.97 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.97)[-0.970,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-0.999,0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 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: Wed, 20 Feb 2019 23:42:06 -0000 Author: kevans Date: Wed Feb 20 23:42:03 2019 New Revision: 344397 URL: https://svnweb.freebsd.org/changeset/base/344397 Log: MFC r316312, r332361, r333438-r333439, r339804: GELI dry-run r316312: sys/geom/eli: Switch bzero() to explicit_bzero() for sensitive data In GELI, anywhere we are zeroing out possibly sensitive data, like the metadata struct, the metadata sector (both contain the encrypted master key), the user key, or the master key, use explicit_bzero. Didn't touch the bzero() used to initialize structs. r332361: Introduce dry run option for attaching the device. This will allow us to verify if passphrase and key is valid without decrypting whole device. r333438: Change option dry-run from 'n' to 'C' in geli attach command. 'n' is used in other commands to define the key index. We should be consistent with that. 'C' option is used by patch(1) to perform dryrun so lets use that. r333439: Introduce the 'n' flag for the geli attach command. If the 'n' flag is provided the provided key number will be used to decrypt device. This can be used combined with dryrun to verify if the key is set correctly. This can be also used to determine which key slot we want to change on already attached device. r339804: Restore backward compatibility for "attach" verb. In r332361 and r333439, two new parameters were added to geli attach verb using gctl_get_paraml, which requires the value to be present. This would prevent old geli(8) binary from attaching geli(4) device as they have no knowledge about the new parameters. Restore backward compatibility by treating the absense of these two values as seeing the default value supplied by userland. Modified: stable/11/sbin/geom/class/eli/geli.8 stable/11/sbin/geom/class/eli/geom_eli.c stable/11/stand/libsa/geli/geliboot.c stable/11/sys/geom/eli/g_eli.c stable/11/sys/geom/eli/g_eli.h stable/11/sys/geom/eli/g_eli_ctl.c stable/11/sys/geom/eli/g_eli_key.c stable/11/sys/geom/eli/g_eli_key_cache.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sbin/geom/class/eli/geli.8 ============================================================================== --- stable/11/sbin/geom/class/eli/geli.8 Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/sbin/geom/class/eli/geli.8 Wed Feb 20 23:42:03 2019 (r344397) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 17, 2017 +.Dd May 9, 2018 .Dt GELI 8 .Os .Sh NAME @@ -67,7 +67,8 @@ utility: .Cm init .Nm .Cm attach -.Op Fl dprv +.Op Fl Cdprv +.Op Fl n Ar keyno .Op Fl j Ar passfile .Op Fl k Ar keyfile .Ar prov @@ -393,6 +394,9 @@ suffix. .Pp Additional options include: .Bl -tag -width ".Fl j Ar passfile" +.It Fl C +Do a dry-run decryption. +This is useful to verify passphrase and keyfile without decrypting the device. .It Fl d If specified, a decrypted provider will be detached automatically on last close. This can help with scarce memory so the user does not have to remember to detach the @@ -404,6 +408,9 @@ Probably a better choice is the option for the .Cm detach subcommand. +.It Fl n Ar keyno +Specifies the index number of the Master Key copy to use (could be 0 or 1). +If the index number is not provided all keys will be tested. .It Fl j Ar passfile Specifies a file which contains the passphrase component of the User Key (or part of it). Modified: stable/11/sbin/geom/class/eli/geom_eli.c ============================================================================== --- stable/11/sbin/geom/class/eli/geom_eli.c Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/sbin/geom/class/eli/geom_eli.c Wed Feb 20 23:42:03 2019 (r344397) @@ -86,7 +86,7 @@ static int eli_backup_create(struct gctl_req *req, con * * 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' - * attach [-dprv] [-j passfile] [-k keyfile] prov + * attach [-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov * detach [-fl] prov ... * stop - alias for 'detach' * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov @@ -145,14 +145,16 @@ struct g_command class_commands[] = { }, { "attach", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main, { + { 'C', "dryrun", NULL, G_TYPE_BOOL }, { 'd', "detach", NULL, G_TYPE_BOOL }, { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI }, + { 'n', "keyno", "-1", G_TYPE_NUMBER }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'r', "readonly", NULL, G_TYPE_BOOL }, G_OPT_SENTINEL }, - "[-dprv] [-j passfile] [-k keyfile] prov" + "[-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov" }, { "detach", 0, NULL, { @@ -1128,7 +1130,7 @@ eli_setkey_detached(struct gctl_req *req, const char * } /* Decrypt Master Key. */ - error = g_eli_mkey_decrypt(md, key, mkey, &nkey); + error = g_eli_mkey_decrypt_any(md, key, mkey, &nkey); bzero(key, sizeof(key)); if (error != 0) { bzero(md, sizeof(*md)); Modified: stable/11/stand/libsa/geli/geliboot.c ============================================================================== --- stable/11/stand/libsa/geli/geliboot.c Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/stand/libsa/geli/geliboot.c Wed Feb 20 23:42:03 2019 (r344397) @@ -121,14 +121,14 @@ geli_findkey(struct geli_entry *ge, struct dsk *dskp, int i; if (ge->keybuf_slot >= 0) { - if (g_eli_mkey_decrypt(&ge->md, saved_keys[ge->keybuf_slot], + if (g_eli_mkey_decrypt_any(&ge->md, saved_keys[ge->keybuf_slot], mkey, &keynum) == 0) { return (0); } } for (i = 0; i < nsaved_keys; i++) { - if (g_eli_mkey_decrypt(&ge->md, saved_keys[i], mkey, + if (g_eli_mkey_decrypt_any(&ge->md, saved_keys[i], mkey, &keynum) == 0) { ge->keybuf_slot = i; return (0); @@ -266,7 +266,7 @@ geli_attach(struct geli_entry *ge, struct dsk *dskp, c g_eli_crypto_hmac_final(&ctx, key, 0); - error = g_eli_mkey_decrypt(&geli_e->md, key, mkey, &keynum); + error = g_eli_mkey_decrypt_any(&geli_e->md, key, mkey, &keynum); if (error == -1) { explicit_bzero(mkey, sizeof(mkey)); explicit_bzero(key, sizeof(key)); Modified: stable/11/sys/geom/eli/g_eli.c ============================================================================== --- stable/11/sys/geom/eli/g_eli.c Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/sys/geom/eli/g_eli.c Wed Feb 20 23:42:03 2019 (r344397) @@ -1086,7 +1086,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, memcpy(key, keybuf->kb_ents[i].ke_data, sizeof(key)); - if (g_eli_mkey_decrypt(&md, key, + if (g_eli_mkey_decrypt_any(&md, key, mkey, &nkey) == 0 ) { explicit_bzero(key, sizeof(key)); goto have_key; @@ -1161,7 +1161,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, /* * Decrypt Master-Key. */ - error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); + error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey); bzero(key, sizeof(key)); if (error == -1) { if (i == tries) { Modified: stable/11/sys/geom/eli/g_eli.h ============================================================================== --- stable/11/sys/geom/eli/g_eli.h Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/sys/geom/eli/g_eli.h Wed Feb 20 23:42:03 2019 (r344397) @@ -686,6 +686,8 @@ void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key); int g_eli_mkey_decrypt(const struct g_eli_metadata *md, + const unsigned char *key, unsigned char *mkey, unsigned keyp); +int g_eli_mkey_decrypt_any(const struct g_eli_metadata *md, const unsigned char *key, unsigned char *mkey, unsigned *nkeyp); int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen, unsigned char *mkey); Modified: stable/11/sys/geom/eli/g_eli_ctl.c ============================================================================== --- stable/11/sys/geom/eli/g_eli_ctl.c Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/sys/geom/eli/g_eli_ctl.c Wed Feb 20 23:42:03 2019 (r344397) @@ -57,9 +57,9 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class struct g_provider *pp; const char *name; u_char *key, mkey[G_ELI_DATAIVKEYLEN]; - int *nargs, *detach, *readonly; - int keysize, error; - u_int nkey; + int *nargs, *detach, *readonly, *dryrunp; + int keysize, error, nkey, dryrun, dummy; + intmax_t *valp; g_topology_assert(); @@ -79,12 +79,39 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class return; } + /* "keyno" is optional for backward compatibility */ + nkey = -1; + valp = gctl_get_param(req, "keyno", &dummy); + if (valp != NULL) { + valp = gctl_get_paraml(req, "keyno", sizeof(*valp)); + if (valp != NULL) + nkey = *valp; + } + if (nkey < -1 || nkey >= G_ELI_MAXMKEYS) { + gctl_error(req, "Invalid '%s' argument.", "keyno"); + return; + } + readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly)); if (readonly == NULL) { gctl_error(req, "No '%s' argument.", "readonly"); return; } + /* "dryrun" is optional for backward compatibility */ + dryrun = 0; + dryrunp = gctl_get_param(req, "dryrun", &dummy); + if (dryrunp != NULL) { + dryrunp = gctl_get_paraml(req, "dryrun", sizeof(*dryrunp)); + if (dryrunp != NULL) + dryrun = *dryrunp; + } + + if (*detach && *readonly) { + gctl_error(req, "Options -d and -r are mutually exclusive."); + return; + } + name = gctl_get_asciiparam(req, "arg0"); if (name == NULL) { gctl_error(req, "No 'arg%u' argument.", 0); @@ -104,44 +131,43 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class return; } if (md.md_keys == 0x00) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "No valid keys on %s.", pp->name); return; } key = gctl_get_param(req, "key", &keysize); if (key == NULL || keysize != G_ELI_USERKEYLEN) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "No '%s' argument.", "key"); return; } - error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); - bzero(key, keysize); + if (nkey == -1) + error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey); + else + error = g_eli_mkey_decrypt(&md, key, mkey, nkey); + explicit_bzero(key, keysize); if (error == -1) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "Wrong key for %s.", pp->name); return; } else if (error > 0) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).", pp->name, error); return; } G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name); - if (*detach && *readonly) { - bzero(&md, sizeof(md)); - gctl_error(req, "Options -d and -r are mutually exclusive."); - return; - } if (*detach) md.md_flags |= G_ELI_FLAG_WO_DETACH; if (*readonly) md.md_flags |= G_ELI_FLAG_RO; - g_eli_create(req, mp, pp, &md, mkey, nkey); - bzero(mkey, sizeof(mkey)); - bzero(&md, sizeof(md)); + if (!dryrun) + g_eli_create(req, mp, pp, &md, mkey, nkey); + explicit_bzero(mkey, sizeof(mkey)); + explicit_bzero(&md, sizeof(md)); } static struct g_eli_softc * @@ -362,8 +388,8 @@ g_eli_ctl_onetime(struct gctl_req *req, struct g_class } g_eli_create(req, mp, pp, &md, mkey, -1); - bzero(mkey, sizeof(mkey)); - bzero(&md, sizeof(md)); + explicit_bzero(mkey, sizeof(mkey)); + explicit_bzero(&md, sizeof(md)); } static void @@ -582,8 +608,8 @@ g_eli_ctl_configure(struct gctl_req *req, struct g_cla "Cannot store metadata on %s (error=%d).", prov, error); } - bzero(&md, sizeof(md)); - bzero(sector, pp->sectorsize); + explicit_bzero(&md, sizeof(md)); + explicit_bzero(sector, pp->sectorsize); free(sector, M_ELI); } } @@ -607,6 +633,11 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class gctl_error(req, "No 'arg%u' argument.", 0); return; } + key = gctl_get_param(req, "key", &keysize); + if (key == NULL || keysize != G_ELI_USERKEYLEN) { + gctl_error(req, "No '%s' argument.", "key"); + return; + } sc = g_eli_find_device(mp, name); if (sc == NULL) { gctl_error(req, "Provider %s is invalid.", name); @@ -662,13 +693,6 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class md.md_iterations = *valp; } - key = gctl_get_param(req, "key", &keysize); - if (key == NULL || keysize != G_ELI_USERKEYLEN) { - bzero(&md, sizeof(md)); - gctl_error(req, "No '%s' argument.", "key"); - return; - } - mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; md.md_keys |= (1 << nkey); @@ -676,9 +700,9 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class /* Encrypt Master Key with the new key. */ error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, mkeydst); - bzero(key, keysize); + explicit_bzero(key, keysize); if (error != 0) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "Cannot encrypt Master Key (error=%d).", error); return; } @@ -686,10 +710,10 @@ g_eli_ctl_setkey(struct gctl_req *req, struct g_class sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); /* Store metadata with fresh key. */ eli_metadata_encode(&md, sector); - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector, pp->sectorsize); - bzero(sector, pp->sectorsize); + explicit_bzero(sector, pp->sectorsize); free(sector, M_ELI); if (error != 0) { gctl_error(req, "Cannot store metadata on %s (error=%d).", @@ -787,7 +811,7 @@ g_eli_ctl_delkey(struct gctl_req *req, struct g_class sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO); for (i = 0; i <= g_eli_overwrites; i++) { if (i == g_eli_overwrites) - bzero(mkeydst, keysize); + explicit_bzero(mkeydst, keysize); else arc4rand(mkeydst, keysize, 0); /* Store metadata with destroyed key. */ @@ -804,8 +828,8 @@ g_eli_ctl_delkey(struct gctl_req *req, struct g_class */ (void)g_io_flush(cp); } - bzero(&md, sizeof(md)); - bzero(sector, pp->sectorsize); + explicit_bzero(&md, sizeof(md)); + explicit_bzero(sector, pp->sectorsize); free(sector, M_ELI); if (*all) G_ELI_DEBUG(1, "All keys removed from %s.", pp->name); @@ -852,12 +876,12 @@ g_eli_suspend_one(struct g_eli_softc *sc, struct gctl_ /* * Clear sensitive data on suspend, they will be recovered on resume. */ - bzero(sc->sc_mkey, sizeof(sc->sc_mkey)); + explicit_bzero(sc->sc_mkey, sizeof(sc->sc_mkey)); g_eli_key_destroy(sc); - bzero(sc->sc_akey, sizeof(sc->sc_akey)); - bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx)); - bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey)); - bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx)); + explicit_bzero(sc->sc_akey, sizeof(sc->sc_akey)); + explicit_bzero(&sc->sc_akeyctx, sizeof(sc->sc_akeyctx)); + explicit_bzero(sc->sc_ivkey, sizeof(sc->sc_ivkey)); + explicit_bzero(&sc->sc_ivctx, sizeof(sc->sc_ivctx)); mtx_unlock(&sc->sc_queue_mtx); G_ELI_DEBUG(0, "Device %s has been suspended.", sc->sc_name); } @@ -950,6 +974,11 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class gctl_error(req, "No 'arg%u' argument.", 0); return; } + key = gctl_get_param(req, "key", &keysize); + if (key == NULL || keysize != G_ELI_USERKEYLEN) { + gctl_error(req, "No '%s' argument.", "key"); + return; + } sc = g_eli_find_device(mp, name); if (sc == NULL) { gctl_error(req, "Provider %s is invalid.", name); @@ -964,26 +993,19 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class return; } if (md.md_keys == 0x00) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "No valid keys on %s.", pp->name); return; } - key = gctl_get_param(req, "key", &keysize); - if (key == NULL || keysize != G_ELI_USERKEYLEN) { - bzero(&md, sizeof(md)); - gctl_error(req, "No '%s' argument.", "key"); - return; - } - - error = g_eli_mkey_decrypt(&md, key, mkey, &nkey); - bzero(key, keysize); + error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey); + explicit_bzero(key, keysize); if (error == -1) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "Wrong key for %s.", pp->name); return; } else if (error > 0) { - bzero(&md, sizeof(md)); + explicit_bzero(&md, sizeof(md)); gctl_error(req, "Cannot decrypt Master Key for %s (error=%d).", pp->name, error); return; @@ -1001,8 +1023,8 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class wakeup(sc); } mtx_unlock(&sc->sc_queue_mtx); - bzero(mkey, sizeof(mkey)); - bzero(&md, sizeof(md)); + explicit_bzero(mkey, sizeof(mkey)); + explicit_bzero(&md, sizeof(md)); } static int Modified: stable/11/sys/geom/eli/g_eli_key.c ============================================================================== --- stable/11/sys/geom/eli/g_eli_key.c Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/sys/geom/eli/g_eli_key.c Wed Feb 20 23:42:03 2019 (r344397) @@ -69,7 +69,7 @@ g_eli_mkey_verify(const unsigned char *mkey, const uns g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN, chmac, 0); - bzero(hmkey, sizeof(hmkey)); + explicit_bzero(hmkey, sizeof(hmkey)); /* * Compare calculated HMAC with HMAC from metadata. @@ -97,56 +97,81 @@ g_eli_mkey_hmac(unsigned char *mkey, const unsigned ch g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN, odhmac, 0); - bzero(hmkey, sizeof(hmkey)); + explicit_bzero(hmkey, sizeof(hmkey)); } /* - * Find and decrypt Master Key encrypted with 'key'. - * Return decrypted Master Key number in 'nkeyp' if not NULL. + * Find and decrypt Master Key encrypted with 'key' at slot 'nkey'. * Return 0 on success, > 0 on failure, -1 on bad key. */ int g_eli_mkey_decrypt(const struct g_eli_metadata *md, const unsigned char *key, - unsigned char *mkey, unsigned *nkeyp) + unsigned char *mkey, unsigned nkey) { unsigned char tmpmkey[G_ELI_MKEYLEN]; unsigned char enckey[SHA512_MDLEN]; /* Key for encryption. */ const unsigned char *mmkey; - int bit, error, nkey; + int bit, error; - if (nkeyp != NULL) - *nkeyp = -1; + if (nkey > G_ELI_MKEYLEN) + return (-1); /* * The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1) */ g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0); - mmkey = md->md_mkeys; - for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++, mmkey += G_ELI_MKEYLEN) { - bit = (1 << nkey); - if (!(md->md_keys & bit)) - continue; - bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN); - error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey, - G_ELI_MKEYLEN, enckey, md->md_keylen); - if (error != 0) { - bzero(tmpmkey, sizeof(tmpmkey)); - bzero(enckey, sizeof(enckey)); - return (error); - } - if (g_eli_mkey_verify(tmpmkey, key)) { - bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN); - bzero(tmpmkey, sizeof(tmpmkey)); - bzero(enckey, sizeof(enckey)); + mmkey = md->md_mkeys + G_ELI_MKEYLEN * nkey; + bit = (1 << nkey); + if (!(md->md_keys & bit)) + return (-1); + bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN); + error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey, + G_ELI_MKEYLEN, enckey, md->md_keylen); + if (error != 0) { + explicit_bzero(tmpmkey, sizeof(tmpmkey)); + explicit_bzero(enckey, sizeof(enckey)); + return (error); + } + if (g_eli_mkey_verify(tmpmkey, key)) { + bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN); + explicit_bzero(tmpmkey, sizeof(tmpmkey)); + explicit_bzero(enckey, sizeof(enckey)); + return (0); + } + explicit_bzero(enckey, sizeof(enckey)); + explicit_bzero(tmpmkey, sizeof(tmpmkey)); + + return (-1); +} + +/* + * Find and decrypt Master Key encrypted with 'key'. + * Return decrypted Master Key number in 'nkeyp' if not NULL. + * Return 0 on success, > 0 on failure, -1 on bad key. + */ +int +g_eli_mkey_decrypt_any(const struct g_eli_metadata *md, + const unsigned char *key, unsigned char *mkey, unsigned *nkeyp) +{ + int error, nkey; + + if (nkeyp != NULL) + *nkeyp = -1; + + error = -1; + for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++) { + error = g_eli_mkey_decrypt(md, key, mkey, nkey); + if (error == 0) { if (nkeyp != NULL) *nkeyp = nkey; - return (0); + break; + } else if (error > 0) { + break; } } - bzero(enckey, sizeof(enckey)); - bzero(tmpmkey, sizeof(tmpmkey)); - return (-1); + + return (error); } /* @@ -175,7 +200,7 @@ g_eli_mkey_encrypt(unsigned algo, const unsigned char */ error = g_eli_crypto_encrypt(algo, mkey, G_ELI_MKEYLEN, enckey, keylen); - bzero(enckey, sizeof(enckey)); + explicit_bzero(enckey, sizeof(enckey)); return (error); } Modified: stable/11/sys/geom/eli/g_eli_key_cache.c ============================================================================== --- stable/11/sys/geom/eli/g_eli_key_cache.c Wed Feb 20 23:05:17 2019 (r344396) +++ stable/11/sys/geom/eli/g_eli_key_cache.c Wed Feb 20 23:42:03 2019 (r344397) @@ -117,7 +117,7 @@ g_eli_key_allocate(struct g_eli_softc *sc, uint64_t ke keysearch.gek_keyno = keyno; ekey = RB_FIND(g_eli_key_tree, &sc->sc_ekeys_tree, &keysearch); if (ekey != NULL) { - bzero(key, sizeof(*key)); + explicit_bzero(key, sizeof(*key)); free(key, M_ELI); key = ekey; TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next); @@ -174,7 +174,7 @@ g_eli_key_remove(struct g_eli_softc *sc, struct g_eli_ RB_REMOVE(g_eli_key_tree, &sc->sc_ekeys_tree, key); TAILQ_REMOVE(&sc->sc_ekeys_queue, key, gek_next); sc->sc_ekeys_allocated--; - bzero(key, sizeof(*key)); + explicit_bzero(key, sizeof(*key)); free(key, M_ELI); } @@ -239,7 +239,7 @@ g_eli_key_destroy(struct g_eli_softc *sc) mtx_lock(&sc->sc_ekeys_lock); if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0) { - bzero(sc->sc_ekey, sizeof(sc->sc_ekey)); + explicit_bzero(sc->sc_ekey, sizeof(sc->sc_ekey)); } else { struct g_eli_key *key;