2005-07-27 21:43:37 +00:00
|
|
|
/*-
|
2017-11-27 15:17:37 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
|
|
*
|
2019-04-03 23:57:37 +00:00
|
|
|
* Copyright (c) 2005-2019 Pawel Jakub Dawidek <pawel@dawidek.net>
|
2005-07-27 21:43:37 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2006-02-01 12:06:01 +00:00
|
|
|
*
|
2005-07-27 21:43:37 +00:00
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2011-12-17 15:26:34 +00:00
|
|
|
#include <sys/cons.h>
|
2005-07-27 21:43:37 +00:00
|
|
|
#include <sys/kernel.h>
|
2006-02-11 13:08:24 +00:00
|
|
|
#include <sys/linker.h>
|
2005-07-27 21:43:37 +00:00
|
|
|
#include <sys/module.h>
|
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/mutex.h>
|
|
|
|
#include <sys/bio.h>
|
2011-07-11 05:22:31 +00:00
|
|
|
#include <sys/sbuf.h>
|
2005-07-27 21:43:37 +00:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/malloc.h>
|
2009-03-16 19:31:08 +00:00
|
|
|
#include <sys/eventhandler.h>
|
2005-07-27 21:43:37 +00:00
|
|
|
#include <sys/kthread.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/sched.h>
|
2005-08-21 18:12:51 +00:00
|
|
|
#include <sys/smp.h>
|
2005-07-27 21:43:37 +00:00
|
|
|
#include <sys/uio.h>
|
2006-02-11 12:45:01 +00:00
|
|
|
#include <sys/vnode.h>
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
#include <vm/uma.h>
|
|
|
|
|
|
|
|
#include <geom/geom.h>
|
2019-08-07 19:28:35 +00:00
|
|
|
#include <geom/geom_dbg.h>
|
2005-07-27 21:43:37 +00:00
|
|
|
#include <geom/eli/g_eli.h>
|
|
|
|
#include <geom/eli/pkcs5v2.h>
|
|
|
|
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
#include <crypto/intake.h>
|
|
|
|
|
2011-02-25 10:24:35 +00:00
|
|
|
FEATURE(geom_eli, "GEOM crypto module");
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
MALLOC_DEFINE(M_ELI, "eli data", "GEOM_ELI Data");
|
|
|
|
|
|
|
|
SYSCTL_DECL(_kern_geom);
|
2020-02-24 10:42:56 +00:00
|
|
|
SYSCTL_NODE(_kern_geom, OID_AUTO, eli, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
|
|
|
"GEOM_ELI stuff");
|
2011-05-08 09:29:21 +00:00
|
|
|
static int g_eli_version = G_ELI_VERSION;
|
|
|
|
SYSCTL_INT(_kern_geom_eli, OID_AUTO, version, CTLFLAG_RD, &g_eli_version, 0,
|
|
|
|
"GELI version");
|
2010-09-25 10:32:04 +00:00
|
|
|
int g_eli_debug = 0;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_INT(_kern_geom_eli, OID_AUTO, debug, CTLFLAG_RWTUN, &g_eli_debug, 0,
|
2005-07-27 21:43:37 +00:00
|
|
|
"Debug level");
|
|
|
|
static u_int g_eli_tries = 3;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, tries, CTLFLAG_RWTUN, &g_eli_tries, 0,
|
2006-02-07 17:23:22 +00:00
|
|
|
"Number of tries for entering the passphrase");
|
2010-11-14 14:12:43 +00:00
|
|
|
static u_int g_eli_visible_passphrase = GETS_NOECHO;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, visible_passphrase, CTLFLAG_RWTUN,
|
2005-07-27 21:43:37 +00:00
|
|
|
&g_eli_visible_passphrase, 0,
|
2010-11-14 14:12:43 +00:00
|
|
|
"Visibility of passphrase prompt (0 = invisible, 1 = visible, 2 = asterisk)");
|
2010-09-23 11:19:48 +00:00
|
|
|
u_int g_eli_overwrites = G_ELI_OVERWRITES;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, overwrites, CTLFLAG_RWTUN, &g_eli_overwrites,
|
2006-02-07 17:23:22 +00:00
|
|
|
0, "Number of times on-disk keys should be overwritten when destroying them");
|
2005-08-21 18:12:51 +00:00
|
|
|
static u_int g_eli_threads = 0;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, threads, CTLFLAG_RWTUN, &g_eli_threads, 0,
|
2005-07-27 21:43:37 +00:00
|
|
|
"Number of threads doing crypto work");
|
2006-06-05 21:38:54 +00:00
|
|
|
u_int g_eli_batch = 0;
|
2014-06-28 03:56:17 +00:00
|
|
|
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, batch, CTLFLAG_RWTUN, &g_eli_batch, 0,
|
2006-06-05 21:38:54 +00:00
|
|
|
"Use crypto operations batching");
|
2005-07-27 21:43:37 +00:00
|
|
|
|
2014-09-16 08:40:52 +00:00
|
|
|
/*
|
|
|
|
* 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
|
2014-10-22 23:41:15 +00:00
|
|
|
fetch_loader_passphrase(void * dummy)
|
|
|
|
{
|
|
|
|
char * env_passphrase;
|
|
|
|
|
|
|
|
KASSERT(dynamic_kenv, ("need dynamic kenv"));
|
|
|
|
|
|
|
|
if ((env_passphrase = kern_getenv("kern.geom.eli.passphrase")) != NULL) {
|
|
|
|
/* Extract passphrase from the environment. */
|
|
|
|
strlcpy(cached_passphrase, env_passphrase,
|
|
|
|
sizeof(cached_passphrase));
|
|
|
|
freeenv(env_passphrase);
|
|
|
|
|
|
|
|
/* Wipe the passphrase from the environment. */
|
|
|
|
kern_unsetenv("kern.geom.eli.passphrase");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SYSINIT(geli_fetch_loader_passphrase, SI_SUB_KMEM + 1, SI_ORDER_ANY,
|
|
|
|
fetch_loader_passphrase, NULL);
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
|
2014-10-22 23:41:15 +00:00
|
|
|
static void
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
zero_boot_passcache(void)
|
2014-09-16 08:40:52 +00:00
|
|
|
{
|
|
|
|
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
explicit_bzero(cached_passphrase, sizeof(cached_passphrase));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
zero_geli_intake_keys(void)
|
|
|
|
{
|
|
|
|
struct keybuf *keybuf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if ((keybuf = get_keybuf()) != NULL) {
|
|
|
|
/* Scan the key buffer, clear all GELI keys. */
|
|
|
|
for (i = 0; i < keybuf->kb_nents; i++) {
|
|
|
|
if (keybuf->kb_ents[i].ke_type == KEYBUF_TYPE_GELI) {
|
|
|
|
explicit_bzero(keybuf->kb_ents[i].ke_data,
|
|
|
|
sizeof(keybuf->kb_ents[i].ke_data));
|
|
|
|
keybuf->kb_ents[i].ke_type = KEYBUF_TYPE_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
zero_intake_passcache(void *dummy)
|
|
|
|
{
|
|
|
|
zero_boot_passcache();
|
|
|
|
zero_geli_intake_keys();
|
2014-09-16 08:40:52 +00:00
|
|
|
}
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
EVENTHANDLER_DEFINE(mountroot, zero_intake_passcache, NULL, 0);
|
2014-09-16 08:40:52 +00:00
|
|
|
|
2009-03-16 19:31:08 +00:00
|
|
|
static eventhandler_tag g_eli_pre_sync = NULL;
|
|
|
|
|
2019-04-03 23:57:37 +00:00
|
|
|
static int g_eli_read_metadata_offset(struct g_class *mp, struct g_provider *pp,
|
|
|
|
off_t offset, struct g_eli_metadata *md);
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
static int g_eli_destroy_geom(struct gctl_req *req, struct g_class *mp,
|
|
|
|
struct g_geom *gp);
|
2009-03-16 19:31:08 +00:00
|
|
|
static void g_eli_init(struct g_class *mp);
|
|
|
|
static void g_eli_fini(struct g_class *mp);
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
static g_taste_t g_eli_taste;
|
|
|
|
static g_dumpconf_t g_eli_dumpconf;
|
|
|
|
|
|
|
|
struct g_class g_eli_class = {
|
|
|
|
.name = G_ELI_CLASS_NAME,
|
|
|
|
.version = G_VERSION,
|
|
|
|
.ctlreq = g_eli_config,
|
|
|
|
.taste = g_eli_taste,
|
2009-03-16 19:31:08 +00:00
|
|
|
.destroy_geom = g_eli_destroy_geom,
|
|
|
|
.init = g_eli_init,
|
|
|
|
.fini = g_eli_fini
|
2005-07-27 21:43:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Code paths:
|
|
|
|
* BIO_READ:
|
2010-10-20 20:50:55 +00:00
|
|
|
* g_eli_start -> g_eli_crypto_read -> g_io_request -> g_eli_read_done -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
|
2005-07-27 21:43:37 +00:00
|
|
|
* BIO_WRITE:
|
|
|
|
* g_eli_start -> g_eli_crypto_run -> g_eli_crypto_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* EAGAIN from crypto(9) means, that we were probably balanced to another crypto
|
|
|
|
* accelerator or something like this.
|
|
|
|
* The function updates the SID and rerun the operation.
|
|
|
|
*/
|
2006-06-05 21:38:54 +00:00
|
|
|
int
|
2005-07-27 21:43:37 +00:00
|
|
|
g_eli_crypto_rerun(struct cryptop *crp)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
struct g_eli_worker *wr;
|
|
|
|
struct bio *bp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
bp = (struct bio *)crp->crp_opaque;
|
|
|
|
sc = bp->bio_to->geom->softc;
|
|
|
|
LIST_FOREACH(wr, &sc->sc_workers, w_next) {
|
|
|
|
if (wr->w_number == bp->bio_pflags)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
KASSERT(wr != NULL, ("Invalid worker (%u).", bp->bio_pflags));
|
2018-07-18 00:56:25 +00:00
|
|
|
G_ELI_DEBUG(1, "Rerunning crypto %s request (sid: %p -> %p).",
|
|
|
|
bp->bio_cmd == BIO_READ ? "READ" : "WRITE", wr->w_sid,
|
|
|
|
crp->crp_session);
|
|
|
|
wr->w_sid = crp->crp_session;
|
2005-07-27 21:43:37 +00:00
|
|
|
crp->crp_etype = 0;
|
|
|
|
error = crypto_dispatch(crp);
|
|
|
|
if (error == 0)
|
|
|
|
return (0);
|
|
|
|
G_ELI_DEBUG(1, "%s: crypto_dispatch() returned %d.", __func__, error);
|
|
|
|
crp->crp_etype = error;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2018-02-14 20:15:32 +00:00
|
|
|
static void
|
|
|
|
g_eli_getattr_done(struct bio *bp)
|
|
|
|
{
|
|
|
|
if (bp->bio_error == 0 &&
|
|
|
|
!strcmp(bp->bio_attribute, "GEOM::physpath")) {
|
|
|
|
strlcat(bp->bio_data, "/eli", bp->bio_length);
|
|
|
|
}
|
|
|
|
g_std_done(bp);
|
|
|
|
}
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
/*
|
|
|
|
* The function is called afer reading encrypted data from the provider.
|
2005-08-13 17:45:37 +00:00
|
|
|
*
|
2010-10-20 20:50:55 +00:00
|
|
|
* g_eli_start -> g_eli_crypto_read -> g_io_request -> G_ELI_READ_DONE -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
|
2005-07-27 21:43:37 +00:00
|
|
|
*/
|
2006-06-05 21:38:54 +00:00
|
|
|
void
|
2005-07-27 21:43:37 +00:00
|
|
|
g_eli_read_done(struct bio *bp)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
struct bio *pbp;
|
|
|
|
|
|
|
|
G_ELI_LOGREQ(2, bp, "Request done.");
|
|
|
|
pbp = bp->bio_parent;
|
2015-11-05 17:37:35 +00:00
|
|
|
if (pbp->bio_error == 0 && bp->bio_error != 0)
|
2005-07-27 21:43:37 +00:00
|
|
|
pbp->bio_error = bp->bio_error;
|
2011-04-03 17:38:12 +00:00
|
|
|
g_destroy_bio(bp);
|
2006-06-05 21:38:54 +00:00
|
|
|
/*
|
|
|
|
* Do we have all sectors already?
|
|
|
|
*/
|
|
|
|
pbp->bio_inbed++;
|
|
|
|
if (pbp->bio_inbed < pbp->bio_children)
|
|
|
|
return;
|
2010-10-20 20:50:55 +00:00
|
|
|
sc = pbp->bio_to->geom->softc;
|
2005-07-27 21:43:37 +00:00
|
|
|
if (pbp->bio_error != 0) {
|
2015-11-05 17:37:35 +00:00
|
|
|
G_ELI_LOGREQ(0, pbp, "%s() failed (error=%d)", __func__,
|
|
|
|
pbp->bio_error);
|
2005-07-27 21:43:37 +00:00
|
|
|
pbp->bio_completed = 0;
|
2006-06-05 21:38:54 +00:00
|
|
|
if (pbp->bio_driver2 != NULL) {
|
|
|
|
free(pbp->bio_driver2, M_ELI);
|
|
|
|
pbp->bio_driver2 = NULL;
|
|
|
|
}
|
2005-07-27 21:43:37 +00:00
|
|
|
g_io_deliver(pbp, pbp->bio_error);
|
2018-07-15 18:03:19 +00:00
|
|
|
if (sc != NULL)
|
|
|
|
atomic_subtract_int(&sc->sc_inflight, 1);
|
2005-07-27 21:43:37 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-08-17 15:25:57 +00:00
|
|
|
mtx_lock(&sc->sc_queue_mtx);
|
|
|
|
bioq_insert_tail(&sc->sc_queue, pbp);
|
|
|
|
mtx_unlock(&sc->sc_queue_mtx);
|
|
|
|
wakeup(sc);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The function is called after we encrypt and write data.
|
2005-08-13 17:45:37 +00:00
|
|
|
*
|
|
|
|
* g_eli_start -> g_eli_crypto_run -> g_eli_crypto_write_done -> g_io_request -> G_ELI_WRITE_DONE -> g_io_deliver
|
2005-07-27 21:43:37 +00:00
|
|
|
*/
|
2006-06-05 21:38:54 +00:00
|
|
|
void
|
2005-07-27 21:43:37 +00:00
|
|
|
g_eli_write_done(struct bio *bp)
|
|
|
|
{
|
2010-10-20 20:50:55 +00:00
|
|
|
struct g_eli_softc *sc;
|
2005-07-27 21:43:37 +00:00
|
|
|
struct bio *pbp;
|
|
|
|
|
|
|
|
G_ELI_LOGREQ(2, bp, "Request done.");
|
|
|
|
pbp = bp->bio_parent;
|
2015-11-05 17:37:35 +00:00
|
|
|
if (pbp->bio_error == 0 && bp->bio_error != 0)
|
|
|
|
pbp->bio_error = bp->bio_error;
|
2011-04-03 17:38:12 +00:00
|
|
|
g_destroy_bio(bp);
|
2006-06-05 21:38:54 +00:00
|
|
|
/*
|
|
|
|
* Do we have all sectors already?
|
|
|
|
*/
|
|
|
|
pbp->bio_inbed++;
|
|
|
|
if (pbp->bio_inbed < pbp->bio_children)
|
|
|
|
return;
|
2005-07-27 21:43:37 +00:00
|
|
|
free(pbp->bio_driver2, M_ELI);
|
|
|
|
pbp->bio_driver2 = NULL;
|
2006-06-05 21:38:54 +00:00
|
|
|
if (pbp->bio_error != 0) {
|
2015-11-05 17:37:35 +00:00
|
|
|
G_ELI_LOGREQ(0, pbp, "%s() failed (error=%d)", __func__,
|
2005-07-27 21:43:37 +00:00
|
|
|
pbp->bio_error);
|
|
|
|
pbp->bio_completed = 0;
|
2015-11-05 17:37:35 +00:00
|
|
|
} else
|
|
|
|
pbp->bio_completed = pbp->bio_length;
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
/*
|
|
|
|
* Write is finished, send it up.
|
|
|
|
*/
|
2010-10-20 20:50:55 +00:00
|
|
|
sc = pbp->bio_to->geom->softc;
|
2005-07-27 21:43:37 +00:00
|
|
|
g_io_deliver(pbp, pbp->bio_error);
|
2018-07-15 18:03:19 +00:00
|
|
|
if (sc != NULL)
|
|
|
|
atomic_subtract_int(&sc->sc_inflight, 1);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function should never be called, but GEOM made as it set ->orphan()
|
|
|
|
* method for every geom.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
g_eli_orphan_spoil_assert(struct g_consumer *cp)
|
|
|
|
{
|
|
|
|
|
|
|
|
panic("Function %s() called for %s.", __func__, cp->geom->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
g_eli_orphan(struct g_consumer *cp)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
|
|
|
|
g_topology_assert();
|
|
|
|
sc = cp->geom->softc;
|
|
|
|
if (sc == NULL)
|
|
|
|
return;
|
2010-10-20 20:50:55 +00:00
|
|
|
g_eli_destroy(sc, TRUE);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
|
2019-04-03 23:57:37 +00:00
|
|
|
static void
|
|
|
|
g_eli_resize(struct g_consumer *cp)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
struct g_provider *epp, *pp;
|
|
|
|
off_t oldsize;
|
|
|
|
|
|
|
|
g_topology_assert();
|
|
|
|
sc = cp->geom->softc;
|
|
|
|
if (sc == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((sc->sc_flags & G_ELI_FLAG_AUTORESIZE) == 0) {
|
|
|
|
G_ELI_DEBUG(0, "Autoresize is turned off, old size: %jd.",
|
|
|
|
(intmax_t)sc->sc_provsize);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pp = cp->provider;
|
|
|
|
|
|
|
|
if ((sc->sc_flags & G_ELI_FLAG_ONETIME) == 0) {
|
|
|
|
struct g_eli_metadata md;
|
|
|
|
u_char *sector;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
sector = NULL;
|
|
|
|
|
|
|
|
error = g_eli_read_metadata_offset(cp->geom->class, pp,
|
|
|
|
sc->sc_provsize - pp->sectorsize, &md);
|
|
|
|
if (error != 0) {
|
|
|
|
G_ELI_DEBUG(0, "Cannot read metadata from %s (error=%d).",
|
|
|
|
pp->name, error);
|
|
|
|
goto iofail;
|
|
|
|
}
|
|
|
|
|
|
|
|
md.md_provsize = pp->mediasize;
|
|
|
|
|
|
|
|
sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
|
|
|
|
eli_metadata_encode(&md, sector);
|
|
|
|
error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
|
|
|
|
pp->sectorsize);
|
|
|
|
if (error != 0) {
|
|
|
|
G_ELI_DEBUG(0, "Cannot store metadata on %s (error=%d).",
|
|
|
|
pp->name, error);
|
|
|
|
goto iofail;
|
|
|
|
}
|
|
|
|
explicit_bzero(sector, pp->sectorsize);
|
|
|
|
error = g_write_data(cp, sc->sc_provsize - pp->sectorsize,
|
|
|
|
sector, pp->sectorsize);
|
|
|
|
if (error != 0) {
|
|
|
|
G_ELI_DEBUG(0, "Cannot clear old metadata from %s (error=%d).",
|
|
|
|
pp->name, error);
|
|
|
|
goto iofail;
|
|
|
|
}
|
|
|
|
iofail:
|
|
|
|
explicit_bzero(&md, sizeof(md));
|
2020-06-25 20:17:34 +00:00
|
|
|
zfree(sector, M_ELI);
|
2019-04-03 23:57:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
oldsize = sc->sc_mediasize;
|
|
|
|
sc->sc_mediasize = eli_mediasize(sc, pp->mediasize, pp->sectorsize);
|
|
|
|
g_eli_key_resize(sc);
|
|
|
|
sc->sc_provsize = pp->mediasize;
|
|
|
|
|
|
|
|
epp = LIST_FIRST(&sc->sc_geom->provider);
|
|
|
|
g_resize_provider(epp, sc->sc_mediasize);
|
|
|
|
G_ELI_DEBUG(0, "Device %s size changed from %jd to %jd.", epp->name,
|
|
|
|
(intmax_t)oldsize, (intmax_t)sc->sc_mediasize);
|
|
|
|
}
|
|
|
|
|
2005-08-13 17:45:37 +00:00
|
|
|
/*
|
2010-10-20 20:01:45 +00:00
|
|
|
* BIO_READ:
|
2010-10-20 20:50:55 +00:00
|
|
|
* G_ELI_START -> g_eli_crypto_read -> g_io_request -> g_eli_read_done -> g_eli_crypto_run -> g_eli_crypto_read_done -> g_io_deliver
|
2010-10-20 20:01:45 +00:00
|
|
|
* BIO_WRITE:
|
|
|
|
* G_ELI_START -> g_eli_crypto_run -> g_eli_crypto_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
|
2005-08-13 17:45:37 +00:00
|
|
|
*/
|
2006-02-01 12:06:01 +00:00
|
|
|
static void
|
2005-07-27 21:43:37 +00:00
|
|
|
g_eli_start(struct bio *bp)
|
2006-02-01 12:06:01 +00:00
|
|
|
{
|
2005-07-27 21:43:37 +00:00
|
|
|
struct g_eli_softc *sc;
|
2006-04-12 12:18:44 +00:00
|
|
|
struct g_consumer *cp;
|
2005-07-27 21:43:37 +00:00
|
|
|
struct bio *cbp;
|
|
|
|
|
|
|
|
sc = bp->bio_to->geom->softc;
|
|
|
|
KASSERT(sc != NULL,
|
|
|
|
("Provider's error should be set (error=%d)(device=%s).",
|
|
|
|
bp->bio_to->error, bp->bio_to->name));
|
|
|
|
G_ELI_LOGREQ(2, bp, "Request received.");
|
|
|
|
|
|
|
|
switch (bp->bio_cmd) {
|
|
|
|
case BIO_READ:
|
|
|
|
case BIO_WRITE:
|
2006-04-12 12:18:44 +00:00
|
|
|
case BIO_GETATTR:
|
2006-10-31 21:23:51 +00:00
|
|
|
case BIO_FLUSH:
|
Add support for managing Shingled Magnetic Recording (SMR) drives.
This change includes support for SCSI SMR drives (which conform to the
Zoned Block Commands or ZBC spec) and ATA SMR drives (which conform to
the Zoned ATA Command Set or ZAC spec) behind SAS expanders.
This includes full management support through the GEOM BIO interface, and
through a new userland utility, zonectl(8), and through camcontrol(8).
This is now ready for filesystems to use to detect and manage zoned drives.
(There is no work in progress that I know of to use this for ZFS or UFS, if
anyone is interested, let me know and I may have some suggestions.)
Also, improve ATA command passthrough and dispatch support, both via ATA
and ATA passthrough over SCSI.
Also, add support to camcontrol(8) for the ATA Extended Power Conditions
feature set. You can now manage ATA device power states, and set various
idle time thresholds for a drive to enter lower power states.
Note that this change cannot be MFCed in full, because it depends on
changes to the struct bio API that break compatilibity. In order to
avoid breaking the stable API, only changes that don't touch or depend on
the struct bio changes can be merged. For example, the camcontrol(8)
changes don't depend on the new bio API, but zonectl(8) and the probe
changes to the da(4) and ada(4) drivers do depend on it.
Also note that the SMR changes have not yet been tested with an actual
SCSI ZBC device, or a SCSI to ATA translation layer (SAT) that supports
ZBC to ZAC translation. I have not yet gotten a suitable drive or SAT
layer, so any testing help would be appreciated. These changes have been
tested with Seagate Host Aware SATA drives attached to both SAS and SATA
controllers. Also, I do not have any SATA Host Managed devices, and I
suspect that it may take additional (hopefully minor) changes to support
them.
Thanks to Seagate for supplying the test hardware and answering questions.
sbin/camcontrol/Makefile:
Add epc.c and zone.c.
sbin/camcontrol/camcontrol.8:
Document the zone and epc subcommands.
sbin/camcontrol/camcontrol.c:
Add the zone and epc subcommands.
Add auxiliary register support to build_ata_cmd(). Make sure to
set the CAM_ATAIO_NEEDRESULT, CAM_ATAIO_DMA, and CAM_ATAIO_FPDMA
flags as appropriate for ATA commands.
Add a new get_ata_status() function to parse ATA result from SCSI
sense descriptors (for ATA passthrough over SCSI) and ATA I/O
requests.
sbin/camcontrol/camcontrol.h:
Update the build_ata_cmd() prototype
Add get_ata_status(), zone(), and epc().
sbin/camcontrol/epc.c:
Support for ATA Extended Power Conditions features. This includes
support for all features documented in the ACS-4 Revision 12
specification from t13.org (dated February 18, 2016).
The EPC feature set allows putting a drive into a power power mode
immediately, or setting timeouts so that the drive will
automatically enter progressively lower power states after various
idle times.
sbin/camcontrol/fwdownload.c:
Update the firmware download code for the new build_ata_cmd()
arguments.
sbin/camcontrol/zone.c:
Implement support for Shingled Magnetic Recording (SMR) drives
via SCSI Zoned Block Commands (ZBC) and ATA Zoned Device ATA
Command Set (ZAC).
These specs were developed in concert, and are functionally
identical. The primary differences are due to SCSI and ATA
differences. (SCSI is big endian, ATA is little endian, for
example.)
This includes support for all commands defined in the ZBC and
ZAC specs.
sys/cam/ata/ata_all.c:
Decode a number of additional ATA command names in ata_op_string().
Add a new CCB building function, ata_read_log().
Add ata_zac_mgmt_in() and ata_zac_mgmt_out() CCB building
functions. These support both DMA and NCQ encapsulation.
sys/cam/ata/ata_all.h:
Add prototypes for ata_read_log(), ata_zac_mgmt_out(), and
ata_zac_mgmt_in().
sys/cam/ata/ata_da.c:
Revamp the ada(4) driver to support zoned devices.
Add four new probe states to gather information needed for zone
support.
Add a new adasetflags() function to avoid duplication of large
blocks of flag setting between the async handler and register
functions.
Add new sysctl variables that describe zone support and paramters.
Add support for the new BIO_ZONE bio, and all of its subcommands:
DISK_ZONE_OPEN, DISK_ZONE_CLOSE, DISK_ZONE_FINISH, DISK_ZONE_RWP,
DISK_ZONE_REPORT_ZONES, and DISK_ZONE_GET_PARAMS.
sys/cam/scsi/scsi_all.c:
Add command descriptions for the ZBC IN/OUT commands.
Add descriptions for ZBC Host Managed devices.
Add a new function, scsi_ata_pass() to do ATA passthrough over
SCSI. This will eventually replace scsi_ata_pass_16() -- it
can create the 12, 16, and 32-byte variants of the ATA
PASS-THROUGH command, and supports setting all of the
registers defined as of SAT-4, Revision 5 (March 11, 2016).
Change scsi_ata_identify() to use scsi_ata_pass() instead of
scsi_ata_pass_16().
Add a new scsi_ata_read_log() function to facilitate reading
ATA logs via SCSI.
sys/cam/scsi/scsi_all.h:
Add the new ATA PASS-THROUGH(32) command CDB. Add extended and
variable CDB opcodes.
Add Zoned Block Device Characteristics VPD page.
Add ATA Return SCSI sense descriptor.
Add prototypes for scsi_ata_read_log() and scsi_ata_pass().
sys/cam/scsi/scsi_da.c:
Revamp the da(4) driver to support zoned devices.
Add five new probe states, four of which are needed for ATA
devices.
Add five new sysctl variables that describe zone support and
parameters.
The da(4) driver supports SCSI ZBC devices, as well as ATA ZAC
devices when they are attached via a SCSI to ATA Translation (SAT)
layer. Since ZBC -> ZAC translation is a new feature in the T10
SAT-4 spec, most SATA drives will be supported via ATA commands
sent via the SCSI ATA PASS-THROUGH command. The da(4) driver will
prefer the ZBC interface, if it is available, for performance
reasons, but will use the ATA PASS-THROUGH interface to the ZAC
command set if the SAT layer doesn't support translation yet.
As I mentioned above, ZBC command support is untested.
Add support for the new BIO_ZONE bio, and all of its subcommands:
DISK_ZONE_OPEN, DISK_ZONE_CLOSE, DISK_ZONE_FINISH, DISK_ZONE_RWP,
DISK_ZONE_REPORT_ZONES, and DISK_ZONE_GET_PARAMS.
Add scsi_zbc_in() and scsi_zbc_out() CCB building functions.
Add scsi_ata_zac_mgmt_out() and scsi_ata_zac_mgmt_in() CCB/CDB
building functions. Note that these have return values, unlike
almost all other CCB building functions in CAM. The reason is
that they can fail, depending upon the particular combination
of input parameters. The primary failure case is if the user
wants NCQ, but fails to specify additional CDB storage. NCQ
requires using the 32-byte version of the SCSI ATA PASS-THROUGH
command, and the current CAM CDB size is 16 bytes.
sys/cam/scsi/scsi_da.h:
Add ZBC IN and ZBC OUT CDBs and opcodes.
Add SCSI Report Zones data structures.
Add scsi_zbc_in(), scsi_zbc_out(), scsi_ata_zac_mgmt_out(), and
scsi_ata_zac_mgmt_in() prototypes.
sys/dev/ahci/ahci.c:
Fix SEND / RECEIVE FPDMA QUEUED in the ahci(4) driver.
ahci_setup_fis() previously set the top bits of the sector count
register in the FIS to 0 for FPDMA commands. This is okay for
read and write, because the PRIO field is in the only thing in
those bits, and we don't implement that further up the stack.
But, for SEND and RECEIVE FPDMA QUEUED, the subcommand is in that
byte, so it needs to be transmitted to the drive.
In ahci_setup_fis(), always set the the top 8 bits of the
sector count register. We need it in both the standard
and NCQ / FPDMA cases.
sys/geom/eli/g_eli.c:
Pass BIO_ZONE commands through the GELI class.
sys/geom/geom.h:
Add g_io_zonecmd() prototype.
sys/geom/geom_dev.c:
Add new DIOCZONECMD ioctl, which allows sending zone commands to
disks.
sys/geom/geom_disk.c:
Add support for BIO_ZONE commands.
sys/geom/geom_disk.h:
Add a new flag, DISKFLAG_CANZONE, that indicates that a given
GEOM disk client can handle BIO_ZONE commands.
sys/geom/geom_io.c:
Add a new function, g_io_zonecmd(), that handles execution of
BIO_ZONE commands.
Add permissions check for BIO_ZONE commands.
Add command decoding for BIO_ZONE commands.
sys/geom/geom_subr.c:
Add DDB command decoding for BIO_ZONE commands.
sys/kern/subr_devstat.c:
Record statistics for REPORT ZONES commands. Note that the
number of bytes transferred for REPORT ZONES won't quite match
what is received from the harware. This is because we're
necessarily counting bytes coming from the da(4) / ada(4) drivers,
which are using the disk_zone.h interface to communicate up
the stack. The structure sizes it uses are slightly different
than the SCSI and ATA structure sizes.
sys/sys/ata.h:
Add many bit and structure definitions for ZAC, NCQ, and EPC
command support.
sys/sys/bio.h:
Convert the bio_cmd field to a straight enumeration. This will
yield more space for additional commands in the future. After
change r297955 and other related changes, this is now possible.
Converting to an enumeration will also prevent use as a bitmask
in the future.
sys/sys/disk.h:
Define the DIOCZONECMD ioctl.
sys/sys/disk_zone.h:
Add a new API for managing zoned disks. This is very close to
the SCSI ZBC and ATA ZAC standards, but uses integers in native
byte order instead of big endian (SCSI) or little endian (ATA)
byte arrays.
This is intended to offer to the complete feature set of the ZBC
and ZAC disk management without requiring the application developer
to include SCSI or ATA headers. We also use one set of headers
for ioctl consumers and kernel bio-level consumers.
sys/sys/param.h:
Bump __FreeBSD_version for sys/bio.h command changes, and inclusion
of SMR support.
usr.sbin/Makefile:
Add the zonectl utility.
usr.sbin/diskinfo/diskinfo.c
Add disk zoning capability to the 'diskinfo -v' output.
usr.sbin/zonectl/Makefile:
Add zonectl makefile.
usr.sbin/zonectl/zonectl.8
zonectl(8) man page.
usr.sbin/zonectl/zonectl.c
The zonectl(8) utility. This allows managing SCSI or ATA zoned
disks via the disk_zone.h API. You can report zones, reset write
pointers, get parameters, etc.
Sponsored by: Spectra Logic
Differential Revision: https://reviews.freebsd.org/D6147
Reviewed by: wblock (documentation)
2016-05-19 14:08:36 +00:00
|
|
|
case BIO_ZONE:
|
2020-01-17 01:15:55 +00:00
|
|
|
case BIO_SPEEDUP:
|
2005-07-27 21:43:37 +00:00
|
|
|
break;
|
|
|
|
case BIO_DELETE:
|
|
|
|
/*
|
2015-08-08 09:51:38 +00:00
|
|
|
* If the user hasn't set the NODELETE flag, we just pass
|
|
|
|
* it down the stack and let the layers beneath us do (or
|
|
|
|
* not) whatever they do with it. If they have, we
|
|
|
|
* reject it. A possible extension would be an
|
|
|
|
* additional flag to take it as a hint to shred the data
|
|
|
|
* with [multiple?] overwrites.
|
2005-07-27 21:43:37 +00:00
|
|
|
*/
|
2015-08-08 09:51:38 +00:00
|
|
|
if (!(sc->sc_flags & G_ELI_FLAG_NODELETE))
|
|
|
|
break;
|
2006-09-30 08:16:49 +00:00
|
|
|
default:
|
2005-07-27 21:43:37 +00:00
|
|
|
g_io_deliver(bp, EOPNOTSUPP);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cbp = g_clone_bio(bp);
|
|
|
|
if (cbp == NULL) {
|
|
|
|
g_io_deliver(bp, ENOMEM);
|
|
|
|
return;
|
|
|
|
}
|
2010-10-20 20:50:55 +00:00
|
|
|
bp->bio_driver1 = cbp;
|
|
|
|
bp->bio_pflags = G_ELI_NEW_BIO;
|
2006-04-12 12:18:44 +00:00
|
|
|
switch (bp->bio_cmd) {
|
|
|
|
case BIO_READ:
|
2006-06-05 21:38:54 +00:00
|
|
|
if (!(sc->sc_flags & G_ELI_FLAG_AUTH)) {
|
2010-10-20 20:50:55 +00:00
|
|
|
g_eli_crypto_read(sc, bp, 0);
|
2006-06-05 21:38:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
2006-04-12 12:18:44 +00:00
|
|
|
case BIO_WRITE:
|
2005-08-17 15:25:57 +00:00
|
|
|
mtx_lock(&sc->sc_queue_mtx);
|
|
|
|
bioq_insert_tail(&sc->sc_queue, bp);
|
|
|
|
mtx_unlock(&sc->sc_queue_mtx);
|
|
|
|
wakeup(sc);
|
2006-04-12 12:18:44 +00:00
|
|
|
break;
|
|
|
|
case BIO_GETATTR:
|
2006-10-31 21:23:51 +00:00
|
|
|
case BIO_FLUSH:
|
2015-08-08 09:51:38 +00:00
|
|
|
case BIO_DELETE:
|
2020-01-17 01:15:55 +00:00
|
|
|
case BIO_SPEEDUP:
|
Add support for managing Shingled Magnetic Recording (SMR) drives.
This change includes support for SCSI SMR drives (which conform to the
Zoned Block Commands or ZBC spec) and ATA SMR drives (which conform to
the Zoned ATA Command Set or ZAC spec) behind SAS expanders.
This includes full management support through the GEOM BIO interface, and
through a new userland utility, zonectl(8), and through camcontrol(8).
This is now ready for filesystems to use to detect and manage zoned drives.
(There is no work in progress that I know of to use this for ZFS or UFS, if
anyone is interested, let me know and I may have some suggestions.)
Also, improve ATA command passthrough and dispatch support, both via ATA
and ATA passthrough over SCSI.
Also, add support to camcontrol(8) for the ATA Extended Power Conditions
feature set. You can now manage ATA device power states, and set various
idle time thresholds for a drive to enter lower power states.
Note that this change cannot be MFCed in full, because it depends on
changes to the struct bio API that break compatilibity. In order to
avoid breaking the stable API, only changes that don't touch or depend on
the struct bio changes can be merged. For example, the camcontrol(8)
changes don't depend on the new bio API, but zonectl(8) and the probe
changes to the da(4) and ada(4) drivers do depend on it.
Also note that the SMR changes have not yet been tested with an actual
SCSI ZBC device, or a SCSI to ATA translation layer (SAT) that supports
ZBC to ZAC translation. I have not yet gotten a suitable drive or SAT
layer, so any testing help would be appreciated. These changes have been
tested with Seagate Host Aware SATA drives attached to both SAS and SATA
controllers. Also, I do not have any SATA Host Managed devices, and I
suspect that it may take additional (hopefully minor) changes to support
them.
Thanks to Seagate for supplying the test hardware and answering questions.
sbin/camcontrol/Makefile:
Add epc.c and zone.c.
sbin/camcontrol/camcontrol.8:
Document the zone and epc subcommands.
sbin/camcontrol/camcontrol.c:
Add the zone and epc subcommands.
Add auxiliary register support to build_ata_cmd(). Make sure to
set the CAM_ATAIO_NEEDRESULT, CAM_ATAIO_DMA, and CAM_ATAIO_FPDMA
flags as appropriate for ATA commands.
Add a new get_ata_status() function to parse ATA result from SCSI
sense descriptors (for ATA passthrough over SCSI) and ATA I/O
requests.
sbin/camcontrol/camcontrol.h:
Update the build_ata_cmd() prototype
Add get_ata_status(), zone(), and epc().
sbin/camcontrol/epc.c:
Support for ATA Extended Power Conditions features. This includes
support for all features documented in the ACS-4 Revision 12
specification from t13.org (dated February 18, 2016).
The EPC feature set allows putting a drive into a power power mode
immediately, or setting timeouts so that the drive will
automatically enter progressively lower power states after various
idle times.
sbin/camcontrol/fwdownload.c:
Update the firmware download code for the new build_ata_cmd()
arguments.
sbin/camcontrol/zone.c:
Implement support for Shingled Magnetic Recording (SMR) drives
via SCSI Zoned Block Commands (ZBC) and ATA Zoned Device ATA
Command Set (ZAC).
These specs were developed in concert, and are functionally
identical. The primary differences are due to SCSI and ATA
differences. (SCSI is big endian, ATA is little endian, for
example.)
This includes support for all commands defined in the ZBC and
ZAC specs.
sys/cam/ata/ata_all.c:
Decode a number of additional ATA command names in ata_op_string().
Add a new CCB building function, ata_read_log().
Add ata_zac_mgmt_in() and ata_zac_mgmt_out() CCB building
functions. These support both DMA and NCQ encapsulation.
sys/cam/ata/ata_all.h:
Add prototypes for ata_read_log(), ata_zac_mgmt_out(), and
ata_zac_mgmt_in().
sys/cam/ata/ata_da.c:
Revamp the ada(4) driver to support zoned devices.
Add four new probe states to gather information needed for zone
support.
Add a new adasetflags() function to avoid duplication of large
blocks of flag setting between the async handler and register
functions.
Add new sysctl variables that describe zone support and paramters.
Add support for the new BIO_ZONE bio, and all of its subcommands:
DISK_ZONE_OPEN, DISK_ZONE_CLOSE, DISK_ZONE_FINISH, DISK_ZONE_RWP,
DISK_ZONE_REPORT_ZONES, and DISK_ZONE_GET_PARAMS.
sys/cam/scsi/scsi_all.c:
Add command descriptions for the ZBC IN/OUT commands.
Add descriptions for ZBC Host Managed devices.
Add a new function, scsi_ata_pass() to do ATA passthrough over
SCSI. This will eventually replace scsi_ata_pass_16() -- it
can create the 12, 16, and 32-byte variants of the ATA
PASS-THROUGH command, and supports setting all of the
registers defined as of SAT-4, Revision 5 (March 11, 2016).
Change scsi_ata_identify() to use scsi_ata_pass() instead of
scsi_ata_pass_16().
Add a new scsi_ata_read_log() function to facilitate reading
ATA logs via SCSI.
sys/cam/scsi/scsi_all.h:
Add the new ATA PASS-THROUGH(32) command CDB. Add extended and
variable CDB opcodes.
Add Zoned Block Device Characteristics VPD page.
Add ATA Return SCSI sense descriptor.
Add prototypes for scsi_ata_read_log() and scsi_ata_pass().
sys/cam/scsi/scsi_da.c:
Revamp the da(4) driver to support zoned devices.
Add five new probe states, four of which are needed for ATA
devices.
Add five new sysctl variables that describe zone support and
parameters.
The da(4) driver supports SCSI ZBC devices, as well as ATA ZAC
devices when they are attached via a SCSI to ATA Translation (SAT)
layer. Since ZBC -> ZAC translation is a new feature in the T10
SAT-4 spec, most SATA drives will be supported via ATA commands
sent via the SCSI ATA PASS-THROUGH command. The da(4) driver will
prefer the ZBC interface, if it is available, for performance
reasons, but will use the ATA PASS-THROUGH interface to the ZAC
command set if the SAT layer doesn't support translation yet.
As I mentioned above, ZBC command support is untested.
Add support for the new BIO_ZONE bio, and all of its subcommands:
DISK_ZONE_OPEN, DISK_ZONE_CLOSE, DISK_ZONE_FINISH, DISK_ZONE_RWP,
DISK_ZONE_REPORT_ZONES, and DISK_ZONE_GET_PARAMS.
Add scsi_zbc_in() and scsi_zbc_out() CCB building functions.
Add scsi_ata_zac_mgmt_out() and scsi_ata_zac_mgmt_in() CCB/CDB
building functions. Note that these have return values, unlike
almost all other CCB building functions in CAM. The reason is
that they can fail, depending upon the particular combination
of input parameters. The primary failure case is if the user
wants NCQ, but fails to specify additional CDB storage. NCQ
requires using the 32-byte version of the SCSI ATA PASS-THROUGH
command, and the current CAM CDB size is 16 bytes.
sys/cam/scsi/scsi_da.h:
Add ZBC IN and ZBC OUT CDBs and opcodes.
Add SCSI Report Zones data structures.
Add scsi_zbc_in(), scsi_zbc_out(), scsi_ata_zac_mgmt_out(), and
scsi_ata_zac_mgmt_in() prototypes.
sys/dev/ahci/ahci.c:
Fix SEND / RECEIVE FPDMA QUEUED in the ahci(4) driver.
ahci_setup_fis() previously set the top bits of the sector count
register in the FIS to 0 for FPDMA commands. This is okay for
read and write, because the PRIO field is in the only thing in
those bits, and we don't implement that further up the stack.
But, for SEND and RECEIVE FPDMA QUEUED, the subcommand is in that
byte, so it needs to be transmitted to the drive.
In ahci_setup_fis(), always set the the top 8 bits of the
sector count register. We need it in both the standard
and NCQ / FPDMA cases.
sys/geom/eli/g_eli.c:
Pass BIO_ZONE commands through the GELI class.
sys/geom/geom.h:
Add g_io_zonecmd() prototype.
sys/geom/geom_dev.c:
Add new DIOCZONECMD ioctl, which allows sending zone commands to
disks.
sys/geom/geom_disk.c:
Add support for BIO_ZONE commands.
sys/geom/geom_disk.h:
Add a new flag, DISKFLAG_CANZONE, that indicates that a given
GEOM disk client can handle BIO_ZONE commands.
sys/geom/geom_io.c:
Add a new function, g_io_zonecmd(), that handles execution of
BIO_ZONE commands.
Add permissions check for BIO_ZONE commands.
Add command decoding for BIO_ZONE commands.
sys/geom/geom_subr.c:
Add DDB command decoding for BIO_ZONE commands.
sys/kern/subr_devstat.c:
Record statistics for REPORT ZONES commands. Note that the
number of bytes transferred for REPORT ZONES won't quite match
what is received from the harware. This is because we're
necessarily counting bytes coming from the da(4) / ada(4) drivers,
which are using the disk_zone.h interface to communicate up
the stack. The structure sizes it uses are slightly different
than the SCSI and ATA structure sizes.
sys/sys/ata.h:
Add many bit and structure definitions for ZAC, NCQ, and EPC
command support.
sys/sys/bio.h:
Convert the bio_cmd field to a straight enumeration. This will
yield more space for additional commands in the future. After
change r297955 and other related changes, this is now possible.
Converting to an enumeration will also prevent use as a bitmask
in the future.
sys/sys/disk.h:
Define the DIOCZONECMD ioctl.
sys/sys/disk_zone.h:
Add a new API for managing zoned disks. This is very close to
the SCSI ZBC and ATA ZAC standards, but uses integers in native
byte order instead of big endian (SCSI) or little endian (ATA)
byte arrays.
This is intended to offer to the complete feature set of the ZBC
and ZAC disk management without requiring the application developer
to include SCSI or ATA headers. We also use one set of headers
for ioctl consumers and kernel bio-level consumers.
sys/sys/param.h:
Bump __FreeBSD_version for sys/bio.h command changes, and inclusion
of SMR support.
usr.sbin/Makefile:
Add the zonectl utility.
usr.sbin/diskinfo/diskinfo.c
Add disk zoning capability to the 'diskinfo -v' output.
usr.sbin/zonectl/Makefile:
Add zonectl makefile.
usr.sbin/zonectl/zonectl.8
zonectl(8) man page.
usr.sbin/zonectl/zonectl.c
The zonectl(8) utility. This allows managing SCSI or ATA zoned
disks via the disk_zone.h API. You can report zones, reset write
pointers, get parameters, etc.
Sponsored by: Spectra Logic
Differential Revision: https://reviews.freebsd.org/D6147
Reviewed by: wblock (documentation)
2016-05-19 14:08:36 +00:00
|
|
|
case BIO_ZONE:
|
2018-02-14 20:15:32 +00:00
|
|
|
if (bp->bio_cmd == BIO_GETATTR)
|
|
|
|
cbp->bio_done = g_eli_getattr_done;
|
|
|
|
else
|
|
|
|
cbp->bio_done = g_std_done;
|
2006-04-12 12:18:44 +00:00
|
|
|
cp = LIST_FIRST(&sc->sc_geom->consumer);
|
|
|
|
cbp->bio_to = cp->provider;
|
2006-04-15 18:30:42 +00:00
|
|
|
G_ELI_LOGREQ(2, cbp, "Sending request.");
|
2006-04-12 12:18:44 +00:00
|
|
|
g_io_request(cbp, cp);
|
|
|
|
break;
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-21 19:44:28 +00:00
|
|
|
static int
|
|
|
|
g_eli_newsession(struct g_eli_worker *wr)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
struct crypto_session_params csp;
|
2020-06-09 22:26:07 +00:00
|
|
|
uint32_t caps;
|
|
|
|
int error, new_crypto;
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
void *key;
|
2010-10-21 19:44:28 +00:00
|
|
|
|
|
|
|
sc = wr->w_softc;
|
|
|
|
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
memset(&csp, 0, sizeof(csp));
|
|
|
|
csp.csp_mode = CSP_MODE_CIPHER;
|
|
|
|
csp.csp_cipher_alg = sc->sc_ealgo;
|
|
|
|
csp.csp_ivlen = g_eli_ivlen(sc->sc_ealgo);
|
|
|
|
csp.csp_cipher_klen = sc->sc_ekeylen / 8;
|
2010-10-21 19:44:28 +00:00
|
|
|
if (sc->sc_ealgo == CRYPTO_AES_XTS)
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
csp.csp_cipher_klen <<= 1;
|
2011-05-08 09:17:56 +00:00
|
|
|
if ((sc->sc_flags & G_ELI_FLAG_FIRST_KEY) != 0) {
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
key = g_eli_key_hold(sc, 0,
|
2011-05-08 09:17:56 +00:00
|
|
|
LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize);
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
csp.csp_cipher_key = key;
|
2011-05-08 09:17:56 +00:00
|
|
|
} else {
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
key = NULL;
|
|
|
|
csp.csp_cipher_key = sc->sc_ekey;
|
2011-05-08 09:17:56 +00:00
|
|
|
}
|
2010-10-21 19:44:28 +00:00
|
|
|
if (sc->sc_flags & G_ELI_FLAG_AUTH) {
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
csp.csp_mode = CSP_MODE_ETA;
|
|
|
|
csp.csp_auth_alg = sc->sc_aalgo;
|
|
|
|
csp.csp_auth_klen = G_ELI_AUTH_SECKEYLEN;
|
2010-10-21 19:44:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (sc->sc_crypto) {
|
2020-06-09 22:26:07 +00:00
|
|
|
case G_ELI_CRYPTO_SW_ACCEL:
|
2010-10-21 19:44:28 +00:00
|
|
|
case G_ELI_CRYPTO_SW:
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
error = crypto_newsession(&wr->w_sid, &csp,
|
2010-10-21 19:44:28 +00:00
|
|
|
CRYPTOCAP_F_SOFTWARE);
|
|
|
|
break;
|
|
|
|
case G_ELI_CRYPTO_HW:
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
error = crypto_newsession(&wr->w_sid, &csp,
|
2010-10-21 19:44:28 +00:00
|
|
|
CRYPTOCAP_F_HARDWARE);
|
|
|
|
break;
|
|
|
|
case G_ELI_CRYPTO_UNKNOWN:
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
error = crypto_newsession(&wr->w_sid, &csp,
|
2020-06-09 22:26:07 +00:00
|
|
|
CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE);
|
2010-10-21 19:44:28 +00:00
|
|
|
if (error == 0) {
|
2020-06-09 22:26:07 +00:00
|
|
|
caps = crypto_ses2caps(wr->w_sid);
|
|
|
|
if (caps & CRYPTOCAP_F_HARDWARE)
|
|
|
|
new_crypto = G_ELI_CRYPTO_HW;
|
|
|
|
else if (caps & CRYPTOCAP_F_ACCEL_SOFTWARE)
|
|
|
|
new_crypto = G_ELI_CRYPTO_SW_ACCEL;
|
|
|
|
else
|
|
|
|
new_crypto = G_ELI_CRYPTO_SW;
|
2010-10-21 19:44:28 +00:00
|
|
|
mtx_lock(&sc->sc_queue_mtx);
|
|
|
|
if (sc->sc_crypto == G_ELI_CRYPTO_UNKNOWN)
|
2020-06-09 22:26:07 +00:00
|
|
|
sc->sc_crypto = new_crypto;
|
2010-10-21 19:44:28 +00:00
|
|
|
mtx_unlock(&sc->sc_queue_mtx);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("%s: invalid condition", __func__);
|
|
|
|
}
|
|
|
|
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
if ((sc->sc_flags & G_ELI_FLAG_FIRST_KEY) != 0) {
|
|
|
|
if (error)
|
|
|
|
g_eli_key_drop(sc, key);
|
|
|
|
else
|
|
|
|
wr->w_first_key = key;
|
|
|
|
}
|
2011-05-08 09:17:56 +00:00
|
|
|
|
2010-10-21 19:44:28 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
g_eli_freesession(struct g_eli_worker *wr)
|
|
|
|
{
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
struct g_eli_softc *sc;
|
2010-10-21 19:44:28 +00:00
|
|
|
|
|
|
|
crypto_freesession(wr->w_sid);
|
Refactor driver and consumer interfaces for OCF (in-kernel crypto).
- The linked list of cryptoini structures used in session
initialization is replaced with a new flat structure: struct
crypto_session_params. This session includes a new mode to define
how the other fields should be interpreted. Available modes
include:
- COMPRESS (for compression/decompression)
- CIPHER (for simply encryption/decryption)
- DIGEST (computing and verifying digests)
- AEAD (combined auth and encryption such as AES-GCM and AES-CCM)
- ETA (combined auth and encryption using encrypt-then-authenticate)
Additional modes could be added in the future (e.g. if we wanted to
support TLS MtE for AES-CBC in the kernel we could add a new mode
for that. TLS modes might also affect how AAD is interpreted, etc.)
The flat structure also includes the key lengths and algorithms as
before. However, code doesn't have to walk the linked list and
switch on the algorithm to determine which key is the auth key vs
encryption key. The 'csp_auth_*' fields are always used for auth
keys and settings and 'csp_cipher_*' for cipher. (Compression
algorithms are stored in csp_cipher_alg.)
- Drivers no longer register a list of supported algorithms. This
doesn't quite work when you factor in modes (e.g. a driver might
support both AES-CBC and SHA2-256-HMAC separately but not combined
for ETA). Instead, a new 'crypto_probesession' method has been
added to the kobj interface for symmteric crypto drivers. This
method returns a negative value on success (similar to how
device_probe works) and the crypto framework uses this value to pick
the "best" driver. There are three constants for hardware
(e.g. ccr), accelerated software (e.g. aesni), and plain software
(cryptosoft) that give preference in that order. One effect of this
is that if you request only hardware when creating a new session,
you will no longer get a session using accelerated software.
Another effect is that the default setting to disallow software
crypto via /dev/crypto now disables accelerated software.
Once a driver is chosen, 'crypto_newsession' is invoked as before.
- Crypto operations are now solely described by the flat 'cryptop'
structure. The linked list of descriptors has been removed.
A separate enum has been added to describe the type of data buffer
in use instead of using CRYPTO_F_* flags to make it easier to add
more types in the future if needed (e.g. wired userspace buffers for
zero-copy). It will also make it easier to re-introduce separate
input and output buffers (in-kernel TLS would benefit from this).
Try to make the flags related to IV handling less insane:
- CRYPTO_F_IV_SEPARATE means that the IV is stored in the 'crp_iv'
member of the operation structure. If this flag is not set, the
IV is stored in the data buffer at the 'crp_iv_start' offset.
- CRYPTO_F_IV_GENERATE means that a random IV should be generated
and stored into the data buffer. This cannot be used with
CRYPTO_F_IV_SEPARATE.
If a consumer wants to deal with explicit vs implicit IVs, etc. it
can always generate the IV however it needs and store partial IVs in
the buffer and the full IV/nonce in crp_iv and set
CRYPTO_F_IV_SEPARATE.
The layout of the buffer is now described via fields in cryptop.
crp_aad_start and crp_aad_length define the boundaries of any AAD.
Previously with GCM and CCM you defined an auth crd with this range,
but for ETA your auth crd had to span both the AAD and plaintext
(and they had to be adjacent).
crp_payload_start and crp_payload_length define the boundaries of
the plaintext/ciphertext. Modes that only do a single operation
(COMPRESS, CIPHER, DIGEST) should only use this region and leave the
AAD region empty.
If a digest is present (or should be generated), it's starting
location is marked by crp_digest_start.
Instead of using the CRD_F_ENCRYPT flag to determine the direction
of the operation, cryptop now includes an 'op' field defining the
operation to perform. For digests I've added a new VERIFY digest
mode which assumes a digest is present in the input and fails the
request with EBADMSG if it doesn't match the internally-computed
digest. GCM and CCM already assumed this, and the new AEAD mode
requires this for decryption. The new ETA mode now also requires
this for decryption, so IPsec and GELI no longer do their own
authentication verification. Simple DIGEST operations can also do
this, though there are no in-tree consumers.
To eventually support some refcounting to close races, the session
cookie is now passed to crypto_getop() and clients should no longer
set crp_sesssion directly.
- Assymteric crypto operation structures should be allocated via
crypto_getkreq() and freed via crypto_freekreq(). This permits the
crypto layer to track open asym requests and close races with a
driver trying to unregister while asym requests are in flight.
- crypto_copyback, crypto_copydata, crypto_apply, and
crypto_contiguous_subsegment now accept the 'crp' object as the
first parameter instead of individual members. This makes it easier
to deal with different buffer types in the future as well as
separate input and output buffers. It's also simpler for driver
writers to use.
- bus_dmamap_load_crp() loads a DMA mapping for a crypto buffer.
This understands the various types of buffers so that drivers that
use DMA do not have to be aware of different buffer types.
- Helper routines now exist to build an auth context for HMAC IPAD
and OPAD. This reduces some duplicated work among drivers.
- Key buffers are now treated as const throughout the framework and in
device drivers. However, session key buffers provided when a session
is created are expected to remain alive for the duration of the
session.
- GCM and CCM sessions now only specify a cipher algorithm and a cipher
key. The redundant auth information is not needed or used.
- For cryptosoft, split up the code a bit such that the 'process'
callback now invokes a function pointer in the session. This
function pointer is set based on the mode (in effect) though it
simplifies a few edge cases that would otherwise be in the switch in
'process'.
It does split up GCM vs CCM which I think is more readable even if there
is some duplication.
- I changed /dev/crypto to support GMAC requests using CRYPTO_AES_NIST_GMAC
as an auth algorithm and updated cryptocheck to work with it.
- Combined cipher and auth sessions via /dev/crypto now always use ETA
mode. The COP_F_CIPHER_FIRST flag is now a no-op that is ignored.
This was actually documented as being true in crypto(4) before, but
the code had not implemented this before I added the CIPHER_FIRST
flag.
- I have not yet updated /dev/crypto to be aware of explicit modes for
sessions. I will probably do that at some point in the future as well
as teach it about IV/nonce and tag lengths for AEAD so we can support
all of the NIST KAT tests for GCM and CCM.
- I've split up the exising crypto.9 manpage into several pages
of which many are written from scratch.
- I have converted all drivers and consumers in the tree and verified
that they compile, but I have not tested all of them. I have tested
the following drivers:
- cryptosoft
- aesni (AES only)
- blake2
- ccr
and the following consumers:
- cryptodev
- IPsec
- ktls_ocf
- GELI (lightly)
I have not tested the following:
- ccp
- aesni with sha
- hifn
- kgssapi_krb5
- ubsec
- padlock
- safe
- armv8_crypto (aarch64)
- glxsb (i386)
- sec (ppc)
- cesa (armv7)
- cryptocteon (mips64)
- nlmsec (mips64)
Discussed with: cem
Relnotes: yes
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D23677
2020-03-27 18:25:23 +00:00
|
|
|
if (wr->w_first_key != NULL) {
|
|
|
|
sc = wr->w_softc;
|
|
|
|
g_eli_key_drop(sc, wr->w_first_key);
|
|
|
|
wr->w_first_key = NULL;
|
|
|
|
}
|
2010-10-21 19:44:28 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 20:50:55 +00:00
|
|
|
static void
|
|
|
|
g_eli_cancel(struct g_eli_softc *sc)
|
|
|
|
{
|
|
|
|
struct bio *bp;
|
|
|
|
|
|
|
|
mtx_assert(&sc->sc_queue_mtx, MA_OWNED);
|
|
|
|
|
|
|
|
while ((bp = bioq_takefirst(&sc->sc_queue)) != NULL) {
|
|
|
|
KASSERT(bp->bio_pflags == G_ELI_NEW_BIO,
|
|
|
|
("Not new bio when canceling (bp=%p).", bp));
|
|
|
|
g_io_deliver(bp, ENXIO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bio *
|
|
|
|
g_eli_takefirst(struct g_eli_softc *sc)
|
|
|
|
{
|
|
|
|
struct bio *bp;
|
|
|
|
|
|
|
|
mtx_assert(&sc->sc_queue_mtx, MA_OWNED);
|
|
|
|
|
|
|
|
if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
|
|
|
|
return (bioq_takefirst(&sc->sc_queue));
|
|
|
|
/*
|
|
|
|
* Device suspended, so we skip new I/O requests.
|
|
|
|
*/
|
|
|
|
TAILQ_FOREACH(bp, &sc->sc_queue.queue, bio_queue) {
|
|
|
|
if (bp->bio_pflags != G_ELI_NEW_BIO)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (bp != NULL)
|
|
|
|
bioq_remove(&sc->sc_queue, bp);
|
|
|
|
return (bp);
|
|
|
|
}
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
/*
|
|
|
|
* This is the main function for kernel worker thread when we don't have
|
|
|
|
* hardware acceleration and we have to do cryptography in software.
|
|
|
|
* Dedicated thread is needed, so we don't slow down g_up/g_down GEOM
|
|
|
|
* threads with crypto work.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
g_eli_worker(void *arg)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
struct g_eli_worker *wr;
|
|
|
|
struct bio *bp;
|
2010-10-21 19:44:28 +00:00
|
|
|
int error;
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
wr = arg;
|
|
|
|
sc = wr->w_softc;
|
Add an EARLY_AP_STARTUP option to start APs earlier during boot.
Currently, Application Processors (non-boot CPUs) are started by
MD code at SI_SUB_CPU, but they are kept waiting in a "pen" until
SI_SUB_SMP at which point they are released to run kernel threads.
SI_SUB_SMP is one of the last SYSINIT levels, so APs don't enter
the scheduler and start running threads until fairly late in the
boot.
This change moves SI_SUB_SMP up to just before software interrupt
threads are created allowing the APs to start executing kernel
threads much sooner (before any devices are probed). This allows
several initialization routines that need to perform initialization
on all CPUs to now perform that initialization in one step rather
than having to defer the AP initialization to a second SYSINIT run
at SI_SUB_SMP. It also permits all CPUs to be available for
handling interrupts before any devices are probed.
This last feature fixes a problem on with interrupt vector exhaustion.
Specifically, in the old model all device interrupts were routed
onto the boot CPU during boot. Later after the APs were released at
SI_SUB_SMP, interrupts were redistributed across all CPUs.
However, several drivers for multiqueue hardware allocate N interrupts
per CPU in the system. In a system with many CPUs, just a few drivers
doing this could exhaust the available pool of interrupt vectors on
the boot CPU as each driver was allocating N * mp_ncpu vectors on the
boot CPU. Now, drivers will allocate interrupts on their desired CPUs
during boot meaning that only N interrupts are allocated from the boot
CPU instead of N * mp_ncpu.
Some other bits of code can also be simplified as smp_started is
now true much earlier and will now always be true for these bits of
code. This removes the need to treat the single-CPU boot environment
as a special case.
As a transition aid, the new behavior is available under a new kernel
option (EARLY_AP_STARTUP). This will allow the option to be turned off
if need be during initial testing. I plan to enable this on x86 by
default in a followup commit in the next few days and to have all
platforms moved over before 11.0. Once the transition is complete,
the option will be removed along with the !EARLY_AP_STARTUP code.
These changes have only been tested on x86. Other platform maintainers
are encouraged to port their architectures over as well. The main
things to check for are any uses of smp_started in MD code that can be
simplified and SI_SUB_SMP SYSINITs in MD code that can be removed in
the EARLY_AP_STARTUP case (e.g. the interrupt shuffling).
PR: kern/199321
Reviewed by: markj, gnn, kib
Sponsored by: Netflix
2016-05-14 18:22:52 +00:00
|
|
|
#ifdef EARLY_AP_STARTUP
|
|
|
|
MPASS(!sc->sc_cpubind || smp_started);
|
|
|
|
#elif defined(SMP)
|
2007-01-28 20:29:12 +00:00
|
|
|
/* Before sched_bind() to a CPU, wait for all CPUs to go on-line. */
|
2011-10-27 16:12:25 +00:00
|
|
|
if (sc->sc_cpubind) {
|
2007-01-28 20:29:12 +00:00
|
|
|
while (!smp_started)
|
|
|
|
tsleep(wr, 0, "geli:smp", hz / 4);
|
|
|
|
}
|
|
|
|
#endif
|
Commit 14/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-05 00:00:57 +00:00
|
|
|
thread_lock(curthread);
|
2010-04-15 16:34:06 +00:00
|
|
|
sched_prio(curthread, PUSER);
|
2011-10-27 16:12:25 +00:00
|
|
|
if (sc->sc_cpubind)
|
|
|
|
sched_bind(curthread, wr->w_number % mp_ncpus);
|
Commit 14/14 of sched_lock decomposition.
- Use thread_lock() rather than sched_lock for per-thread scheduling
sychronization.
- Use the per-process spinlock rather than the sched_lock for per-process
scheduling synchronization.
Tested by: kris, current@
Tested on: i386, amd64, ULE, 4BSD, libthr, libkse, PREEMPTION, etc.
Discussed with: kris, attilio, kmacy, jhb, julian, bde (small parts each)
2007-06-05 00:00:57 +00:00
|
|
|
thread_unlock(curthread);
|
2006-02-01 12:06:01 +00:00
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
G_ELI_DEBUG(1, "Thread %s started.", curthread->td_proc->p_comm);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
mtx_lock(&sc->sc_queue_mtx);
|
2010-10-20 20:50:55 +00:00
|
|
|
again:
|
|
|
|
bp = g_eli_takefirst(sc);
|
2005-07-27 21:43:37 +00:00
|
|
|
if (bp == NULL) {
|
2006-06-05 21:38:54 +00:00
|
|
|
if (sc->sc_flags & G_ELI_FLAG_DESTROY) {
|
2010-10-20 20:50:55 +00:00
|
|
|
g_eli_cancel(sc);
|
2005-07-27 21:43:37 +00:00
|
|
|
LIST_REMOVE(wr, w_next);
|
2010-10-21 19:44:28 +00:00
|
|
|
g_eli_freesession(wr);
|
2005-07-27 21:43:37 +00:00
|
|
|
free(wr, M_ELI);
|
|
|
|
G_ELI_DEBUG(1, "Thread %s exiting.",
|
|
|
|
curthread->td_proc->p_comm);
|
|
|
|
wakeup(&sc->sc_workers);
|
|
|
|
mtx_unlock(&sc->sc_queue_mtx);
|
2007-10-20 23:23:23 +00:00
|
|
|
kproc_exit(0);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
2010-10-20 20:50:55 +00:00
|
|
|
while (sc->sc_flags & G_ELI_FLAG_SUSPEND) {
|
|
|
|
if (sc->sc_inflight > 0) {
|
2011-10-25 13:08:03 +00:00
|
|
|
G_ELI_DEBUG(0, "inflight=%d",
|
|
|
|
sc->sc_inflight);
|
2010-10-20 20:50:55 +00:00
|
|
|
/*
|
|
|
|
* We still have inflight BIOs, so
|
|
|
|
* sleep and retry.
|
|
|
|
*/
|
|
|
|
msleep(sc, &sc->sc_queue_mtx, PRIBIO,
|
|
|
|
"geli:inf", hz / 5);
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Suspend requested, mark the worker as
|
|
|
|
* suspended and go to sleep.
|
|
|
|
*/
|
2010-10-21 19:44:28 +00:00
|
|
|
if (wr->w_active) {
|
|
|
|
g_eli_freesession(wr);
|
|
|
|
wr->w_active = FALSE;
|
|
|
|
}
|
2010-10-20 20:50:55 +00:00
|
|
|
wakeup(&sc->sc_workers);
|
|
|
|
msleep(sc, &sc->sc_queue_mtx, PRIBIO,
|
|
|
|
"geli:suspend", 0);
|
2010-10-21 19:44:28 +00:00
|
|
|
if (!wr->w_active &&
|
|
|
|
!(sc->sc_flags & G_ELI_FLAG_SUSPEND)) {
|
|
|
|
error = g_eli_newsession(wr);
|
|
|
|
KASSERT(error == 0,
|
|
|
|
("g_eli_newsession() failed on resume (error=%d)",
|
|
|
|
error));
|
|
|
|
wr->w_active = TRUE;
|
|
|
|
}
|
2010-10-20 20:50:55 +00:00
|
|
|
goto again;
|
|
|
|
}
|
2010-04-15 16:34:06 +00:00
|
|
|
msleep(sc, &sc->sc_queue_mtx, PDROP, "geli:w", 0);
|
2005-07-27 21:43:37 +00:00
|
|
|
continue;
|
|
|
|
}
|
2010-10-20 20:50:55 +00:00
|
|
|
if (bp->bio_pflags == G_ELI_NEW_BIO)
|
|
|
|
atomic_add_int(&sc->sc_inflight, 1);
|
2005-07-27 21:43:37 +00:00
|
|
|
mtx_unlock(&sc->sc_queue_mtx);
|
2010-10-20 20:50:55 +00:00
|
|
|
if (bp->bio_pflags == G_ELI_NEW_BIO) {
|
|
|
|
bp->bio_pflags = 0;
|
|
|
|
if (sc->sc_flags & G_ELI_FLAG_AUTH) {
|
|
|
|
if (bp->bio_cmd == BIO_READ)
|
|
|
|
g_eli_auth_read(sc, bp);
|
|
|
|
else
|
|
|
|
g_eli_auth_run(wr, bp);
|
|
|
|
} else {
|
|
|
|
if (bp->bio_cmd == BIO_READ)
|
|
|
|
g_eli_crypto_read(sc, bp, 1);
|
|
|
|
else
|
|
|
|
g_eli_crypto_run(wr, bp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (sc->sc_flags & G_ELI_FLAG_AUTH)
|
|
|
|
g_eli_auth_run(wr, bp);
|
|
|
|
else
|
|
|
|
g_eli_crypto_run(wr, bp);
|
|
|
|
}
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-03 23:57:37 +00:00
|
|
|
static int
|
|
|
|
g_eli_read_metadata_offset(struct g_class *mp, struct g_provider *pp,
|
|
|
|
off_t offset, struct g_eli_metadata *md)
|
2005-07-27 21:43:37 +00:00
|
|
|
{
|
|
|
|
struct g_geom *gp;
|
|
|
|
struct g_consumer *cp;
|
|
|
|
u_char *buf = NULL;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
g_topology_assert();
|
|
|
|
|
|
|
|
gp = g_new_geomf(mp, "eli:taste");
|
|
|
|
gp->start = g_eli_start;
|
|
|
|
gp->access = g_std_access;
|
|
|
|
/*
|
|
|
|
* g_eli_read_metadata() is always called from the event thread.
|
|
|
|
* Our geom is created and destroyed in the same event, so there
|
|
|
|
* could be no orphan nor spoil event in the meantime.
|
|
|
|
*/
|
|
|
|
gp->orphan = g_eli_orphan_spoil_assert;
|
|
|
|
gp->spoiled = g_eli_orphan_spoil_assert;
|
|
|
|
cp = g_new_consumer(gp);
|
2020-07-08 17:12:12 +00:00
|
|
|
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
|
2005-07-27 21:43:37 +00:00
|
|
|
error = g_attach(cp, pp);
|
|
|
|
if (error != 0)
|
|
|
|
goto end;
|
|
|
|
error = g_access(cp, 1, 0, 0);
|
|
|
|
if (error != 0)
|
|
|
|
goto end;
|
|
|
|
g_topology_unlock();
|
2019-04-03 23:57:37 +00:00
|
|
|
buf = g_read_data(cp, offset, pp->sectorsize, &error);
|
2005-07-27 21:43:37 +00:00
|
|
|
g_topology_lock();
|
2005-11-30 19:24:51 +00:00
|
|
|
if (buf == NULL)
|
2005-07-27 21:43:37 +00:00
|
|
|
goto end;
|
2015-07-02 10:57:34 +00:00
|
|
|
error = eli_metadata_decode(buf, md);
|
|
|
|
if (error != 0)
|
|
|
|
goto end;
|
|
|
|
/* Metadata was read and decoded successfully. */
|
2005-07-27 21:43:37 +00:00
|
|
|
end:
|
|
|
|
if (buf != NULL)
|
|
|
|
g_free(buf);
|
|
|
|
if (cp->provider != NULL) {
|
|
|
|
if (cp->acr == 1)
|
|
|
|
g_access(cp, -1, 0, 0);
|
|
|
|
g_detach(cp);
|
|
|
|
}
|
|
|
|
g_destroy_consumer(cp);
|
|
|
|
g_destroy_geom(gp);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2019-04-03 23:57:37 +00:00
|
|
|
int
|
|
|
|
g_eli_read_metadata(struct g_class *mp, struct g_provider *pp,
|
|
|
|
struct g_eli_metadata *md)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (g_eli_read_metadata_offset(mp, pp,
|
|
|
|
pp->mediasize - pp->sectorsize, md));
|
|
|
|
}
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
/*
|
|
|
|
* The function is called when we had last close on provider and user requested
|
|
|
|
* to close it when this situation occur.
|
|
|
|
*/
|
|
|
|
static void
|
2013-09-02 10:44:54 +00:00
|
|
|
g_eli_last_close(void *arg, int flags __unused)
|
2005-07-27 21:43:37 +00:00
|
|
|
{
|
|
|
|
struct g_geom *gp;
|
2013-09-02 10:44:54 +00:00
|
|
|
char gpname[64];
|
2005-07-27 21:43:37 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
g_topology_assert();
|
2013-09-02 10:44:54 +00:00
|
|
|
gp = arg;
|
|
|
|
strlcpy(gpname, gp->name, sizeof(gpname));
|
|
|
|
error = g_eli_destroy(gp->softc, TRUE);
|
2005-07-27 21:43:37 +00:00
|
|
|
KASSERT(error == 0, ("Cannot detach %s on last close (error=%d).",
|
2013-09-02 10:44:54 +00:00
|
|
|
gpname, error));
|
|
|
|
G_ELI_DEBUG(0, "Detached %s on last close.", gpname);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
g_eli_access(struct g_provider *pp, int dr, int dw, int de)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
struct g_geom *gp;
|
|
|
|
|
|
|
|
gp = pp->geom;
|
|
|
|
sc = gp->softc;
|
|
|
|
|
|
|
|
if (dw > 0) {
|
2006-08-09 18:11:14 +00:00
|
|
|
if (sc->sc_flags & G_ELI_FLAG_RO) {
|
|
|
|
/* Deny write attempts. */
|
|
|
|
return (EROFS);
|
|
|
|
}
|
2005-07-27 21:43:37 +00:00
|
|
|
/* Someone is opening us for write, we need to remember that. */
|
|
|
|
sc->sc_flags |= G_ELI_FLAG_WOPEN;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
/* Is this the last close? */
|
|
|
|
if (pp->acr + dr > 0 || pp->acw + dw > 0 || pp->ace + de > 0)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Automatically detach on last close if requested.
|
|
|
|
*/
|
|
|
|
if ((sc->sc_flags & G_ELI_FLAG_RW_DETACH) ||
|
|
|
|
(sc->sc_flags & G_ELI_FLAG_WOPEN)) {
|
2013-09-02 10:44:54 +00:00
|
|
|
g_post_event(g_eli_last_close, gp, M_WAITOK, NULL);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2006-11-01 16:05:06 +00:00
|
|
|
static int
|
|
|
|
g_eli_cpu_is_disabled(int cpu)
|
|
|
|
{
|
|
|
|
#ifdef SMP
|
Commit the support for removing cpumask_t and replacing it directly with
cpuset_t objects.
That is going to offer the underlying support for a simple bump of
MAXCPU and then support for number of cpus > 32 (as it is today).
Right now, cpumask_t is an int, 32 bits on all our supported architecture.
cpumask_t on the other side is implemented as an array of longs, and
easilly extendible by definition.
The architectures touched by this commit are the following:
- amd64
- i386
- pc98
- arm
- ia64
- XEN
while the others are still missing.
Userland is believed to be fully converted with the changes contained
here.
Some technical notes:
- This commit may be considered an ABI nop for all the architectures
different from amd64 and ia64 (and sparc64 in the future)
- per-cpu members, which are now converted to cpuset_t, needs to be
accessed avoiding migration, because the size of cpuset_t should be
considered unknown
- size of cpuset_t objects is different from kernel and userland (this is
primirally done in order to leave some more space in userland to cope
with KBI extensions). If you need to access kernel cpuset_t from the
userland please refer to example in this patch on how to do that
correctly (kgdb may be a good source, for example).
- Support for other architectures is going to be added soon
- Only MAXCPU for amd64 is bumped now
The patch has been tested by sbruno and Nicholas Esborn on opteron
4 x 12 pack CPUs. More testing on big SMP is expected to came soon.
pluknet tested the patch with his 8-ways on both amd64 and i386.
Tested by: pluknet, sbruno, gianni, Nicholas Esborn
Reviewed by: jeff, jhb, sbruno
2011-05-05 14:39:14 +00:00
|
|
|
return (CPU_ISSET(cpu, &hlt_cpus_mask));
|
2006-11-01 16:05:06 +00:00
|
|
|
#else
|
|
|
|
return (0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
struct g_geom *
|
|
|
|
g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
|
|
|
|
const struct g_eli_metadata *md, const u_char *mkey, int nkey)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
struct g_eli_worker *wr;
|
|
|
|
struct g_geom *gp;
|
|
|
|
struct g_provider *pp;
|
|
|
|
struct g_consumer *cp;
|
2020-05-13 19:17:28 +00:00
|
|
|
struct g_geom_alias *gap;
|
2005-07-27 21:43:37 +00:00
|
|
|
u_int i, threads;
|
2019-07-01 22:06:16 +00:00
|
|
|
int dcw, error;
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
G_ELI_DEBUG(1, "Creating device %s%s.", bpp->name, G_ELI_SUFFIX);
|
2020-04-15 00:14:50 +00:00
|
|
|
KASSERT(eli_metadata_crypto_supported(md),
|
|
|
|
("%s: unsupported crypto for %s", __func__, bpp->name));
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
gp = g_new_geomf(mp, "%s%s", bpp->name, G_ELI_SUFFIX);
|
|
|
|
sc = malloc(sizeof(*sc), M_ELI, M_WAITOK | M_ZERO);
|
|
|
|
gp->start = g_eli_start;
|
|
|
|
/*
|
2015-07-10 19:27:19 +00:00
|
|
|
* Spoiling can happen even though we have the provider open
|
|
|
|
* exclusively, e.g. through media change events.
|
2005-07-27 21:43:37 +00:00
|
|
|
*/
|
2015-07-10 19:27:19 +00:00
|
|
|
gp->spoiled = g_eli_orphan;
|
2005-07-27 21:43:37 +00:00
|
|
|
gp->orphan = g_eli_orphan;
|
2019-04-03 23:57:37 +00:00
|
|
|
gp->resize = g_eli_resize;
|
2006-08-09 18:11:14 +00:00
|
|
|
gp->dumpconf = g_eli_dumpconf;
|
2005-07-27 21:43:37 +00:00
|
|
|
/*
|
2006-08-09 18:11:14 +00:00
|
|
|
* If detach-on-last-close feature is not enabled and we don't operate
|
|
|
|
* on read-only provider, we can simply use g_std_access().
|
2005-07-27 21:43:37 +00:00
|
|
|
*/
|
2006-08-09 18:11:14 +00:00
|
|
|
if (md->md_flags & (G_ELI_FLAG_WO_DETACH | G_ELI_FLAG_RO))
|
2005-07-27 21:43:37 +00:00
|
|
|
gp->access = g_eli_access;
|
|
|
|
else
|
|
|
|
gp->access = g_std_access;
|
|
|
|
|
2016-01-07 05:47:34 +00:00
|
|
|
eli_metadata_softc(sc, md, bpp->sectorsize, bpp->mediasize);
|
2005-07-27 21:43:37 +00:00
|
|
|
sc->sc_nkey = nkey;
|
2006-06-05 21:38:54 +00:00
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
gp->softc = sc;
|
|
|
|
sc->sc_geom = gp;
|
|
|
|
|
|
|
|
bioq_init(&sc->sc_queue);
|
|
|
|
mtx_init(&sc->sc_queue_mtx, "geli:queue", NULL, MTX_DEF);
|
2011-04-21 13:31:43 +00:00
|
|
|
mtx_init(&sc->sc_ekeys_lock, "geli:ekeys", NULL, MTX_DEF);
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
pp = NULL;
|
|
|
|
cp = g_new_consumer(gp);
|
2020-07-08 17:12:12 +00:00
|
|
|
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
|
2005-07-27 21:43:37 +00:00
|
|
|
error = g_attach(cp, bpp);
|
|
|
|
if (error != 0) {
|
|
|
|
if (req != NULL) {
|
|
|
|
gctl_error(req, "Cannot attach to %s (error=%d).",
|
|
|
|
bpp->name, error);
|
|
|
|
} else {
|
|
|
|
G_ELI_DEBUG(1, "Cannot attach to %s (error=%d).",
|
|
|
|
bpp->name, error);
|
|
|
|
}
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Keep provider open all the time, so we can run critical tasks,
|
|
|
|
* like Master Keys deletion, without wondering if we can open
|
|
|
|
* provider or not.
|
2006-08-09 18:11:14 +00:00
|
|
|
* We don't open provider for writing only when user requested read-only
|
|
|
|
* access.
|
2005-07-27 21:43:37 +00:00
|
|
|
*/
|
2019-07-01 22:06:16 +00:00
|
|
|
dcw = (sc->sc_flags & G_ELI_FLAG_RO) ? 0 : 1;
|
|
|
|
error = g_access(cp, 1, dcw, 1);
|
2005-07-27 21:43:37 +00:00
|
|
|
if (error != 0) {
|
|
|
|
if (req != NULL) {
|
|
|
|
gctl_error(req, "Cannot access %s (error=%d).",
|
|
|
|
bpp->name, error);
|
|
|
|
} else {
|
|
|
|
G_ELI_DEBUG(1, "Cannot access %s (error=%d).",
|
|
|
|
bpp->name, error);
|
|
|
|
}
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
|
2010-09-23 11:49:47 +00:00
|
|
|
/*
|
|
|
|
* Remember the keys in our softc structure.
|
|
|
|
*/
|
|
|
|
g_eli_mkey_propagate(sc, mkey);
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
LIST_INIT(&sc->sc_workers);
|
|
|
|
|
|
|
|
threads = g_eli_threads;
|
2005-08-21 18:12:51 +00:00
|
|
|
if (threads == 0)
|
|
|
|
threads = mp_ncpus;
|
2011-10-27 16:12:25 +00:00
|
|
|
sc->sc_cpubind = (mp_ncpus > 1 && threads == mp_ncpus);
|
2005-07-27 21:43:37 +00:00
|
|
|
for (i = 0; i < threads; i++) {
|
2006-11-01 16:05:06 +00:00
|
|
|
if (g_eli_cpu_is_disabled(i)) {
|
|
|
|
G_ELI_DEBUG(1, "%s: CPU %u disabled, skipping.",
|
2006-11-02 09:01:34 +00:00
|
|
|
bpp->name, i);
|
2006-11-01 16:05:06 +00:00
|
|
|
continue;
|
|
|
|
}
|
2005-07-27 21:43:37 +00:00
|
|
|
wr = malloc(sizeof(*wr), M_ELI, M_WAITOK | M_ZERO);
|
|
|
|
wr->w_softc = sc;
|
|
|
|
wr->w_number = i;
|
2010-10-20 20:50:55 +00:00
|
|
|
wr->w_active = TRUE;
|
2005-07-27 21:43:37 +00:00
|
|
|
|
2010-10-21 19:44:28 +00:00
|
|
|
error = g_eli_newsession(wr);
|
2005-07-27 21:43:37 +00:00
|
|
|
if (error != 0) {
|
|
|
|
free(wr, M_ELI);
|
|
|
|
if (req != NULL) {
|
2006-02-07 17:23:22 +00:00
|
|
|
gctl_error(req, "Cannot set up crypto session "
|
2005-07-27 21:43:37 +00:00
|
|
|
"for %s (error=%d).", bpp->name, error);
|
|
|
|
} else {
|
2006-02-07 17:23:22 +00:00
|
|
|
G_ELI_DEBUG(1, "Cannot set up crypto session "
|
2005-07-27 21:43:37 +00:00
|
|
|
"for %s (error=%d).", bpp->name, error);
|
|
|
|
}
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
|
2007-10-20 23:23:23 +00:00
|
|
|
error = kproc_create(g_eli_worker, wr, &wr->w_proc, 0, 0,
|
2005-07-27 21:43:37 +00:00
|
|
|
"g_eli[%u] %s", i, bpp->name);
|
|
|
|
if (error != 0) {
|
2010-10-21 19:44:28 +00:00
|
|
|
g_eli_freesession(wr);
|
2005-07-27 21:43:37 +00:00
|
|
|
free(wr, M_ELI);
|
|
|
|
if (req != NULL) {
|
2005-08-17 15:25:57 +00:00
|
|
|
gctl_error(req, "Cannot create kernel thread "
|
|
|
|
"for %s (error=%d).", bpp->name, error);
|
2005-07-27 21:43:37 +00:00
|
|
|
} else {
|
2005-08-17 15:25:57 +00:00
|
|
|
G_ELI_DEBUG(1, "Cannot create kernel thread "
|
|
|
|
"for %s (error=%d).", bpp->name, error);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
LIST_INSERT_HEAD(&sc->sc_workers, wr, w_next);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create decrypted provider.
|
|
|
|
*/
|
|
|
|
pp = g_new_providerf(gp, "%s%s", bpp->name, G_ELI_SUFFIX);
|
2020-07-08 17:12:12 +00:00
|
|
|
pp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE;
|
2010-09-23 11:49:47 +00:00
|
|
|
pp->mediasize = sc->sc_mediasize;
|
|
|
|
pp->sectorsize = sc->sc_sectorsize;
|
2020-05-13 19:17:28 +00:00
|
|
|
LIST_FOREACH(gap, &bpp->aliases, ga_next)
|
|
|
|
g_provider_add_alias(pp, "%s%s", gap->ga_alias, G_ELI_SUFFIX);
|
2006-06-05 21:38:54 +00:00
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
g_error_provider(pp, 0);
|
|
|
|
|
|
|
|
G_ELI_DEBUG(0, "Device %s created.", pp->name);
|
2006-06-05 21:38:54 +00:00
|
|
|
G_ELI_DEBUG(0, "Encryption: %s %u", g_eli_algo2str(sc->sc_ealgo),
|
|
|
|
sc->sc_ekeylen);
|
2020-04-15 00:14:50 +00:00
|
|
|
if (sc->sc_flags & G_ELI_FLAG_AUTH)
|
2006-06-05 21:38:54 +00:00
|
|
|
G_ELI_DEBUG(0, " Integrity: %s", g_eli_algo2str(sc->sc_aalgo));
|
2005-07-27 21:43:37 +00:00
|
|
|
G_ELI_DEBUG(0, " Crypto: %s",
|
2020-06-09 22:26:07 +00:00
|
|
|
sc->sc_crypto == G_ELI_CRYPTO_SW_ACCEL ? "accelerated software" :
|
2005-07-27 21:43:37 +00:00
|
|
|
sc->sc_crypto == G_ELI_CRYPTO_SW ? "software" : "hardware");
|
|
|
|
return (gp);
|
|
|
|
failed:
|
2005-08-17 15:25:57 +00:00
|
|
|
mtx_lock(&sc->sc_queue_mtx);
|
|
|
|
sc->sc_flags |= G_ELI_FLAG_DESTROY;
|
|
|
|
wakeup(sc);
|
|
|
|
/*
|
|
|
|
* Wait for kernel threads self destruction.
|
|
|
|
*/
|
|
|
|
while (!LIST_EMPTY(&sc->sc_workers)) {
|
|
|
|
msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
|
|
|
|
"geli:destroy", 0);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
mtx_destroy(&sc->sc_queue_mtx);
|
|
|
|
if (cp->provider != NULL) {
|
|
|
|
if (cp->acr == 1)
|
2019-07-01 22:06:16 +00:00
|
|
|
g_access(cp, -1, -dcw, -1);
|
2005-07-27 21:43:37 +00:00
|
|
|
g_detach(cp);
|
|
|
|
}
|
|
|
|
g_destroy_consumer(cp);
|
|
|
|
g_destroy_geom(gp);
|
2011-04-21 13:31:43 +00:00
|
|
|
g_eli_key_destroy(sc);
|
2020-06-25 20:20:22 +00:00
|
|
|
zfree(sc, M_ELI);
|
2005-07-27 21:43:37 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
g_eli_destroy(struct g_eli_softc *sc, boolean_t force)
|
|
|
|
{
|
|
|
|
struct g_geom *gp;
|
|
|
|
struct g_provider *pp;
|
|
|
|
|
|
|
|
g_topology_assert();
|
|
|
|
|
|
|
|
if (sc == NULL)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
gp = sc->sc_geom;
|
|
|
|
pp = LIST_FIRST(&gp->provider);
|
|
|
|
if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
|
|
|
|
if (force) {
|
|
|
|
G_ELI_DEBUG(1, "Device %s is still open, so it "
|
2006-02-07 17:23:22 +00:00
|
|
|
"cannot be definitely removed.", pp->name);
|
2013-09-02 10:44:54 +00:00
|
|
|
sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
|
|
|
|
gp->access = g_eli_access;
|
|
|
|
g_wither_provider(pp, ENXIO);
|
|
|
|
return (EBUSY);
|
2005-07-27 21:43:37 +00:00
|
|
|
} else {
|
|
|
|
G_ELI_DEBUG(1,
|
|
|
|
"Device %s is still open (r%dw%de%d).", pp->name,
|
|
|
|
pp->acr, pp->acw, pp->ace);
|
|
|
|
return (EBUSY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-17 15:25:57 +00:00
|
|
|
mtx_lock(&sc->sc_queue_mtx);
|
|
|
|
sc->sc_flags |= G_ELI_FLAG_DESTROY;
|
|
|
|
wakeup(sc);
|
|
|
|
while (!LIST_EMPTY(&sc->sc_workers)) {
|
|
|
|
msleep(&sc->sc_workers, &sc->sc_queue_mtx, PRIBIO,
|
|
|
|
"geli:destroy", 0);
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
mtx_destroy(&sc->sc_queue_mtx);
|
|
|
|
gp->softc = NULL;
|
2011-04-21 13:31:43 +00:00
|
|
|
g_eli_key_destroy(sc);
|
2020-06-25 20:20:22 +00:00
|
|
|
zfree(sc, M_ELI);
|
2005-07-27 21:43:37 +00:00
|
|
|
|
2020-01-02 20:30:53 +00:00
|
|
|
G_ELI_DEBUG(0, "Device %s destroyed.", gp->name);
|
2005-07-27 21:43:37 +00:00
|
|
|
g_wither_geom_close(gp, ENXIO);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
g_eli_destroy_geom(struct gctl_req *req __unused,
|
|
|
|
struct g_class *mp __unused, struct g_geom *gp)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
|
|
|
|
sc = gp->softc;
|
2010-10-20 20:50:55 +00:00
|
|
|
return (g_eli_destroy(sc, FALSE));
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
|
2006-02-11 13:08:24 +00:00
|
|
|
static int
|
|
|
|
g_eli_keyfiles_load(struct hmac_ctx *ctx, const char *provider)
|
|
|
|
{
|
2011-02-13 19:34:48 +00:00
|
|
|
u_char *keyfile, *data;
|
2006-02-11 13:08:24 +00:00
|
|
|
char *file, name[64];
|
2011-02-13 19:34:48 +00:00
|
|
|
size_t size;
|
2006-02-11 13:08:24 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; ; i++) {
|
|
|
|
snprintf(name, sizeof(name), "%s:geli_keyfile%d", provider, i);
|
|
|
|
keyfile = preload_search_by_type(name);
|
2015-07-02 10:55:32 +00:00
|
|
|
if (keyfile == NULL && i == 0) {
|
|
|
|
/*
|
|
|
|
* If there is only one keyfile, allow simpler name.
|
|
|
|
*/
|
|
|
|
snprintf(name, sizeof(name), "%s:geli_keyfile", provider);
|
|
|
|
keyfile = preload_search_by_type(name);
|
|
|
|
}
|
2006-02-11 13:08:24 +00:00
|
|
|
if (keyfile == NULL)
|
|
|
|
return (i); /* Return number of loaded keyfiles. */
|
2011-02-13 19:34:48 +00:00
|
|
|
data = preload_fetch_addr(keyfile);
|
2006-02-11 13:08:24 +00:00
|
|
|
if (data == NULL) {
|
|
|
|
G_ELI_DEBUG(0, "Cannot find key file data for %s.",
|
|
|
|
name);
|
|
|
|
return (0);
|
|
|
|
}
|
2011-02-13 19:34:48 +00:00
|
|
|
size = preload_fetch_size(keyfile);
|
|
|
|
if (size == 0) {
|
2006-02-11 13:08:24 +00:00
|
|
|
G_ELI_DEBUG(0, "Cannot find key file size for %s.",
|
|
|
|
name);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
file = preload_search_info(keyfile, MODINFO_NAME);
|
|
|
|
if (file == NULL) {
|
|
|
|
G_ELI_DEBUG(0, "Cannot find key file name for %s.",
|
|
|
|
name);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
G_ELI_DEBUG(1, "Loaded keyfile %s for %s (type: %s).", file,
|
|
|
|
provider, name);
|
2011-02-13 19:34:48 +00:00
|
|
|
g_eli_crypto_hmac_update(ctx, data, size);
|
2006-02-11 13:08:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
g_eli_keyfiles_clear(const char *provider)
|
|
|
|
{
|
2011-02-13 19:34:48 +00:00
|
|
|
u_char *keyfile, *data;
|
2006-02-11 13:08:24 +00:00
|
|
|
char name[64];
|
2011-02-13 19:34:48 +00:00
|
|
|
size_t size;
|
2006-02-11 13:08:24 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; ; i++) {
|
|
|
|
snprintf(name, sizeof(name), "%s:geli_keyfile%d", provider, i);
|
|
|
|
keyfile = preload_search_by_type(name);
|
|
|
|
if (keyfile == NULL)
|
|
|
|
return;
|
2011-02-13 19:34:48 +00:00
|
|
|
data = preload_fetch_addr(keyfile);
|
|
|
|
size = preload_fetch_size(keyfile);
|
|
|
|
if (data != NULL && size != 0)
|
2020-06-25 20:25:35 +00:00
|
|
|
explicit_bzero(data, size);
|
2006-02-11 13:08:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
/*
|
|
|
|
* Tasting is only made on boot.
|
|
|
|
* We detect providers which should be attached before root is mounted.
|
|
|
|
*/
|
|
|
|
static struct g_geom *
|
|
|
|
g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
|
|
|
|
{
|
|
|
|
struct g_eli_metadata md;
|
|
|
|
struct g_geom *gp;
|
|
|
|
struct hmac_ctx ctx;
|
|
|
|
char passphrase[256];
|
|
|
|
u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN];
|
2017-08-26 14:07:24 +00:00
|
|
|
u_int i, nkey, nkeyfiles, tries, showpass;
|
2005-07-27 21:43:37 +00:00
|
|
|
int error;
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
struct keybuf *keybuf;
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name);
|
|
|
|
g_topology_assert();
|
|
|
|
|
2007-04-08 23:54:23 +00:00
|
|
|
if (root_mounted() || g_eli_tries == 0)
|
2005-07-27 21:43:37 +00:00
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
G_ELI_DEBUG(3, "Tasting %s.", pp->name);
|
|
|
|
|
|
|
|
error = g_eli_read_metadata(mp, pp, &md);
|
|
|
|
if (error != 0)
|
|
|
|
return (NULL);
|
|
|
|
gp = NULL;
|
|
|
|
|
|
|
|
if (strcmp(md.md_magic, G_ELI_MAGIC) != 0)
|
|
|
|
return (NULL);
|
|
|
|
if (md.md_version > G_ELI_VERSION) {
|
|
|
|
printf("geom_eli.ko module is too old to handle %s.\n",
|
|
|
|
pp->name);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if (md.md_provsize != pp->mediasize)
|
|
|
|
return (NULL);
|
|
|
|
/* Should we attach it on boot? */
|
2020-02-07 21:36:14 +00:00
|
|
|
if (!(md.md_flags & G_ELI_FLAG_BOOT) &&
|
|
|
|
!(md.md_flags & G_ELI_FLAG_GELIBOOT))
|
2005-07-27 21:43:37 +00:00
|
|
|
return (NULL);
|
|
|
|
if (md.md_keys == 0x00) {
|
|
|
|
G_ELI_DEBUG(0, "No valid keys on %s.", pp->name);
|
|
|
|
return (NULL);
|
|
|
|
}
|
2020-04-15 00:14:50 +00:00
|
|
|
if (!eli_metadata_crypto_supported(&md)) {
|
|
|
|
G_ELI_DEBUG(0, "%s uses invalid or unsupported algorithms\n",
|
|
|
|
pp->name);
|
|
|
|
return (NULL);
|
|
|
|
}
|
2006-02-11 13:08:24 +00:00
|
|
|
if (md.md_iterations == -1) {
|
|
|
|
/* If there is no passphrase, we try only once. */
|
|
|
|
tries = 1;
|
|
|
|
} else {
|
|
|
|
/* Ask for the passphrase no more than g_eli_tries times. */
|
|
|
|
tries = g_eli_tries;
|
|
|
|
}
|
|
|
|
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
if ((keybuf = get_keybuf()) != NULL) {
|
|
|
|
/* Scan the key buffer, try all GELI keys. */
|
|
|
|
for (i = 0; i < keybuf->kb_nents; i++) {
|
|
|
|
if (keybuf->kb_ents[i].ke_type == KEYBUF_TYPE_GELI) {
|
|
|
|
memcpy(key, keybuf->kb_ents[i].ke_data,
|
|
|
|
sizeof(key));
|
|
|
|
|
2018-05-09 20:53:38 +00:00
|
|
|
if (g_eli_mkey_decrypt_any(&md, key,
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
mkey, &nkey) == 0 ) {
|
|
|
|
explicit_bzero(key, sizeof(key));
|
|
|
|
goto have_key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i <= tries; i++) {
|
|
|
|
g_eli_crypto_hmac_init(&ctx, NULL, 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load all key files.
|
|
|
|
*/
|
|
|
|
nkeyfiles = g_eli_keyfiles_load(&ctx, pp->name);
|
|
|
|
|
|
|
|
if (nkeyfiles == 0 && md.md_iterations == -1) {
|
|
|
|
/*
|
|
|
|
* No key files and no passphrase, something is
|
|
|
|
* definitely wrong here.
|
|
|
|
* geli(8) doesn't allow for such situation, so assume
|
|
|
|
* that there was really no passphrase and in that case
|
|
|
|
* key files are no properly defined in loader.conf.
|
|
|
|
*/
|
|
|
|
G_ELI_DEBUG(0,
|
|
|
|
"Found no key files in loader.conf for %s.",
|
|
|
|
pp->name);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ask for the passphrase if defined. */
|
|
|
|
if (md.md_iterations >= 0) {
|
|
|
|
/* 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);
|
2017-08-26 14:07:24 +00:00
|
|
|
showpass = g_eli_visible_passphrase;
|
|
|
|
if ((md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS) != 0)
|
|
|
|
showpass = GETS_ECHOPASS;
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
cngets(passphrase, sizeof(passphrase),
|
2017-08-26 14:07:24 +00:00
|
|
|
showpass);
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
memcpy(cached_passphrase, passphrase,
|
|
|
|
sizeof(passphrase));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare Derived-Key from the user passphrase.
|
|
|
|
*/
|
|
|
|
if (md.md_iterations == 0) {
|
|
|
|
g_eli_crypto_hmac_update(&ctx, md.md_salt,
|
|
|
|
sizeof(md.md_salt));
|
|
|
|
g_eli_crypto_hmac_update(&ctx, passphrase,
|
|
|
|
strlen(passphrase));
|
|
|
|
explicit_bzero(passphrase, sizeof(passphrase));
|
|
|
|
} else if (md.md_iterations > 0) {
|
|
|
|
u_char dkey[G_ELI_USERKEYLEN];
|
|
|
|
|
|
|
|
pkcs5v2_genkey(dkey, sizeof(dkey), md.md_salt,
|
|
|
|
sizeof(md.md_salt), passphrase, md.md_iterations);
|
2020-06-25 20:25:35 +00:00
|
|
|
explicit_bzero(passphrase, sizeof(passphrase));
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
|
|
|
|
explicit_bzero(dkey, sizeof(dkey));
|
|
|
|
}
|
|
|
|
|
|
|
|
g_eli_crypto_hmac_final(&ctx, key, 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Decrypt Master-Key.
|
|
|
|
*/
|
2018-05-09 20:53:38 +00:00
|
|
|
error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
|
2020-06-25 20:25:35 +00:00
|
|
|
explicit_bzero(key, sizeof(key));
|
Implement boot-time encryption key passing (keybuf)
This patch adds a general mechanism for providing encryption keys to the
kernel from the boot loader. This is intended to enable GELI support at
boot time, providing a better mechanism for passing keys to the kernel
than environment variables. It is designed to be extensible to other
applications, and can easily handle multiple encrypted volumes with
different keys.
This mechanism is currently used by the pending GELI EFI work.
Additionally, this mechanism can potentially be used to interface with
GRUB, opening up options for coreboot+GRUB configurations with completely
encrypted disks.
Another benefit over the existing system is that it does not require
re-deriving the user key from the password at each boot stage.
Most of this patch was written by Eric McCorkle. It was extended by
Allan Jude with a number of minor enhancements and extending the keybuf
feature into boot2.
GELI user keys are now derived once, in boot2, then passed to the loader,
which reuses the key, then passes it to the kernel, where the GELI module
destroys the keybuf after decrypting the volumes.
Submitted by: Eric McCorkle <eric@metricspace.net> (Original Version)
Reviewed by: oshogbo (earlier version), cem (earlier version)
MFC after: 3 weeks
Relnotes: yes
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D9575
2017-04-01 05:05:22 +00:00
|
|
|
if (error == -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);
|
|
|
|
}
|
|
|
|
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) {
|
|
|
|
G_ELI_DEBUG(0,
|
|
|
|
"Cannot decrypt Master Key for %s (error=%d).",
|
|
|
|
pp->name, error);
|
|
|
|
g_eli_keyfiles_clear(pp->name);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
g_eli_keyfiles_clear(pp->name);
|
|
|
|
G_ELI_DEBUG(1, "Using Master Key %u for %s.", nkey, pp->name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
have_key:
|
2005-07-27 21:43:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We have correct key, let's attach provider.
|
|
|
|
*/
|
|
|
|
gp = g_eli_create(NULL, mp, pp, &md, mkey, nkey);
|
2020-06-25 20:25:35 +00:00
|
|
|
explicit_bzero(mkey, sizeof(mkey));
|
|
|
|
explicit_bzero(&md, sizeof(md));
|
2005-07-27 21:43:37 +00:00
|
|
|
if (gp == NULL) {
|
|
|
|
G_ELI_DEBUG(0, "Cannot create device %s%s.", pp->name,
|
|
|
|
G_ELI_SUFFIX);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
return (gp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
|
|
|
|
struct g_consumer *cp, struct g_provider *pp)
|
|
|
|
{
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
|
|
|
|
g_topology_assert();
|
|
|
|
sc = gp->softc;
|
|
|
|
if (sc == NULL)
|
|
|
|
return;
|
|
|
|
if (pp != NULL || cp != NULL)
|
|
|
|
return; /* Nothing here. */
|
2011-04-21 13:31:43 +00:00
|
|
|
|
2013-11-11 11:13:12 +00:00
|
|
|
sbuf_printf(sb, "%s<KeysTotal>%ju</KeysTotal>\n", indent,
|
2011-04-21 13:31:43 +00:00
|
|
|
(uintmax_t)sc->sc_ekeys_total);
|
2013-11-11 11:13:12 +00:00
|
|
|
sbuf_printf(sb, "%s<KeysAllocated>%ju</KeysAllocated>\n", indent,
|
2011-04-21 13:31:43 +00:00
|
|
|
(uintmax_t)sc->sc_ekeys_allocated);
|
2005-07-27 22:31:57 +00:00
|
|
|
sbuf_printf(sb, "%s<Flags>", indent);
|
|
|
|
if (sc->sc_flags == 0)
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, "NONE");
|
2005-07-27 22:31:57 +00:00
|
|
|
else {
|
|
|
|
int first = 1;
|
|
|
|
|
|
|
|
#define ADD_FLAG(flag, name) do { \
|
2006-06-05 21:38:54 +00:00
|
|
|
if (sc->sc_flags & (flag)) { \
|
2005-07-27 22:31:57 +00:00
|
|
|
if (!first) \
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, ", "); \
|
2005-07-27 22:31:57 +00:00
|
|
|
else \
|
|
|
|
first = 0; \
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, name); \
|
2005-07-27 22:31:57 +00:00
|
|
|
} \
|
|
|
|
} while (0)
|
2010-10-20 20:50:55 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_SUSPEND, "SUSPEND");
|
2010-09-23 11:49:47 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_SINGLE_KEY, "SINGLE-KEY");
|
2006-08-11 19:09:12 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_NATIVE_BYTE_ORDER, "NATIVE-BYTE-ORDER");
|
2005-07-27 22:31:57 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_ONETIME, "ONETIME");
|
|
|
|
ADD_FLAG(G_ELI_FLAG_BOOT, "BOOT");
|
|
|
|
ADD_FLAG(G_ELI_FLAG_WO_DETACH, "W-DETACH");
|
|
|
|
ADD_FLAG(G_ELI_FLAG_RW_DETACH, "RW-DETACH");
|
2006-06-05 21:38:54 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_AUTH, "AUTH");
|
2005-07-27 22:31:57 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_WOPEN, "W-OPEN");
|
|
|
|
ADD_FLAG(G_ELI_FLAG_DESTROY, "DESTROY");
|
2006-08-09 18:11:14 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_RO, "READ-ONLY");
|
2015-08-08 09:51:38 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_NODELETE, "NODELETE");
|
Create the GELIBOOT GEOM_ELI flag
This flag indicates that the user wishes to use the GELIBOOT feature to boot from a fully encrypted root file system.
Currently, GELIBOOT does not support key files, and in the future when it does, they will be loaded differently.
Due to the design of GELI, and the desire for secrecy, the GELI metadata does not know if key files are used or not, it just adds the key material (if any) to the HMAC before the optional passphrase, so there is no way to tell if a GELI partition requires key files or not.
Since the GELIBOOT code in boot2 and the loader does not support keys, they will now only attempt to attach if this flag is set. This will stop GELIBOOT from prompting for passwords to GELIs that it cannot decrypt, disrupting the boot process
PR: 208251
Reviewed by: ed, oshogbo, wblock
Sponsored by: ScaleEngine Inc.
Differential Revision: https://reviews.freebsd.org/D5867
2016-04-08 01:25:25 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_GELIBOOT, "GELIBOOT");
|
2017-08-26 14:07:24 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_GELIDISPLAYPASS, "GELIDISPLAYPASS");
|
2019-04-03 23:57:37 +00:00
|
|
|
ADD_FLAG(G_ELI_FLAG_AUTORESIZE, "AUTORESIZE");
|
2005-07-27 22:31:57 +00:00
|
|
|
#undef ADD_FLAG
|
|
|
|
}
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, "</Flags>\n");
|
2005-07-27 22:31:57 +00:00
|
|
|
|
2006-06-05 21:38:54 +00:00
|
|
|
if (!(sc->sc_flags & G_ELI_FLAG_ONETIME)) {
|
2005-07-27 22:31:57 +00:00
|
|
|
sbuf_printf(sb, "%s<UsedKey>%u</UsedKey>\n", indent,
|
|
|
|
sc->sc_nkey);
|
|
|
|
}
|
2011-10-25 13:57:50 +00:00
|
|
|
sbuf_printf(sb, "%s<Version>%u</Version>\n", indent, sc->sc_version);
|
2005-07-27 21:43:37 +00:00
|
|
|
sbuf_printf(sb, "%s<Crypto>", indent);
|
|
|
|
switch (sc->sc_crypto) {
|
|
|
|
case G_ELI_CRYPTO_HW:
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, "hardware");
|
2005-07-27 21:43:37 +00:00
|
|
|
break;
|
|
|
|
case G_ELI_CRYPTO_SW:
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, "software");
|
2005-07-27 21:43:37 +00:00
|
|
|
break;
|
2020-06-09 22:26:07 +00:00
|
|
|
case G_ELI_CRYPTO_SW_ACCEL:
|
|
|
|
sbuf_cat(sb, "accelerated software");
|
|
|
|
break;
|
2005-07-27 21:43:37 +00:00
|
|
|
default:
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, "UNKNOWN");
|
2005-07-27 21:43:37 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-06-19 15:36:02 +00:00
|
|
|
sbuf_cat(sb, "</Crypto>\n");
|
2006-06-05 21:38:54 +00:00
|
|
|
if (sc->sc_flags & G_ELI_FLAG_AUTH) {
|
|
|
|
sbuf_printf(sb,
|
|
|
|
"%s<AuthenticationAlgorithm>%s</AuthenticationAlgorithm>\n",
|
|
|
|
indent, g_eli_algo2str(sc->sc_aalgo));
|
|
|
|
}
|
|
|
|
sbuf_printf(sb, "%s<KeyLength>%u</KeyLength>\n", indent,
|
|
|
|
sc->sc_ekeylen);
|
2011-10-25 13:08:03 +00:00
|
|
|
sbuf_printf(sb, "%s<EncryptionAlgorithm>%s</EncryptionAlgorithm>\n",
|
|
|
|
indent, g_eli_algo2str(sc->sc_ealgo));
|
2010-10-22 22:45:26 +00:00
|
|
|
sbuf_printf(sb, "%s<State>%s</State>\n", indent,
|
|
|
|
(sc->sc_flags & G_ELI_FLAG_SUSPEND) ? "SUSPENDED" : "ACTIVE");
|
2005-07-27 21:43:37 +00:00
|
|
|
}
|
|
|
|
|
2009-03-16 19:31:08 +00:00
|
|
|
static void
|
|
|
|
g_eli_shutdown_pre_sync(void *arg, int howto)
|
|
|
|
{
|
|
|
|
struct g_class *mp;
|
|
|
|
struct g_geom *gp, *gp2;
|
|
|
|
struct g_provider *pp;
|
|
|
|
struct g_eli_softc *sc;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
mp = arg;
|
|
|
|
g_topology_lock();
|
|
|
|
LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
|
|
|
|
sc = gp->softc;
|
|
|
|
if (sc == NULL)
|
|
|
|
continue;
|
|
|
|
pp = LIST_FIRST(&gp->provider);
|
|
|
|
KASSERT(pp != NULL, ("No provider? gp=%p (%s)", gp, gp->name));
|
2020-05-27 19:13:26 +00:00
|
|
|
if (pp->acr != 0 || pp->acw != 0 || pp->ace != 0 ||
|
|
|
|
SCHEDULER_STOPPED())
|
|
|
|
{
|
2009-03-16 19:31:08 +00:00
|
|
|
sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
|
|
|
|
gp->access = g_eli_access;
|
2020-05-27 19:13:26 +00:00
|
|
|
} else {
|
|
|
|
error = g_eli_destroy(sc, TRUE);
|
2009-03-16 19:31:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
g_topology_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
g_eli_init(struct g_class *mp)
|
|
|
|
{
|
|
|
|
|
|
|
|
g_eli_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
|
|
|
|
g_eli_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
|
|
|
|
if (g_eli_pre_sync == NULL)
|
|
|
|
G_ELI_DEBUG(0, "Warning! Cannot register shutdown event.");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
g_eli_fini(struct g_class *mp)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (g_eli_pre_sync != NULL)
|
|
|
|
EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_eli_pre_sync);
|
|
|
|
}
|
|
|
|
|
2005-07-27 21:43:37 +00:00
|
|
|
DECLARE_GEOM_CLASS(g_eli_class, g_eli);
|
2006-07-27 11:52:12 +00:00
|
|
|
MODULE_DEPEND(g_eli, crypto, 1, 1, 1);
|
2018-04-10 19:18:16 +00:00
|
|
|
MODULE_VERSION(geom_eli, 0);
|