aboutsummaryrefslogtreecommitdiff
path: root/lib/geom/eli
diff options
context:
space:
mode:
Diffstat (limited to 'lib/geom/eli')
-rw-r--r--lib/geom/eli/Makefile8
-rw-r--r--lib/geom/eli/Makefile.depend3
-rw-r--r--lib/geom/eli/geli.850
-rw-r--r--lib/geom/eli/geom_eli.c85
4 files changed, 107 insertions, 39 deletions
diff --git a/lib/geom/eli/Makefile b/lib/geom/eli/Makefile
index e36eece7a6e2..a22eacb9d7e8 100644
--- a/lib/geom/eli/Makefile
+++ b/lib/geom/eli/Makefile
@@ -1,15 +1,11 @@
-# $FreeBSD$
-
-PACKAGE=runtime
-.PATH: ${.CURDIR:H:H}/misc ${SRCTOP}/sys/geom/eli ${SRCTOP}/sys/crypto/sha2
+PACKAGE=geom
+.PATH: ${SRCTOP}/sys/geom/eli
GEOM_CLASS= eli
SRCS= g_eli_crypto.c
SRCS+= g_eli_hmac.c
SRCS+= g_eli_key.c
SRCS+= pkcs5v2.c
-SRCS+= sha256c.c
-SRCS+= sha512c.c
LIBADD= md crypto
diff --git a/lib/geom/eli/Makefile.depend b/lib/geom/eli/Makefile.depend
index 3378fcd11dbc..8e5ef128814d 100644
--- a/lib/geom/eli/Makefile.depend
+++ b/lib/geom/eli/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
@@ -10,7 +8,6 @@ DIRDEPS = \
lib/libcompiler_rt \
lib/libgeom \
lib/libmd \
- sbin/geom/core \
secure/lib/libcrypto \
diff --git a/lib/geom/eli/geli.8 b/lib/geom/eli/geli.8
index 1ad0c684642b..876caf67ab40 100644
--- a/lib/geom/eli/geli.8
+++ b/lib/geom/eli/geli.8
@@ -22,9 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd April 18, 2022
+.Dd April 24, 2024
.Dt GELI 8
.Os
.Sh NAME
@@ -853,6 +851,15 @@ This variable should be set in
Specifies how many times the Master Key is overwritten
with random values when it is destroyed.
After this operation it is filled with zeros.
+.It Va kern.geom.eli.use_uma_bytes
+.Nm
+must allocate a buffer for every write operation, used when performing
+encryption.
+This sysctl reports the maximum size in bytes for which geli will perform the
+allocation using
+.Xr uma 9 ,
+as opposed to
+.Xr malloc 9 .
.It Va kern.geom.eli.visible_passphrase : No 0
If set to 1, the passphrase entered on boot will be visible.
This alternative should be used with caution as the entered
@@ -865,11 +872,14 @@ Specifies how many kernel threads should be used for doing software
cryptography.
Its purpose is to increase performance on SMP systems.
If set to 0, a CPU-pinned thread will be started for every active CPU.
+Note that this variable must be set prior to attaching
+.Nm
+to a disk.
.It Va kern.geom.eli.batch : No 0
When set to 1, can speed-up crypto operations by using batching.
Batching reduces the number of interrupts by responding to a group of
crypto requests with one interrupt.
-The crypto card and the driver has to support this feature.
+The crypto card and the driver have to support this feature.
.It Va kern.geom.eli.key_cache_limit : No 8192
Specifies how many Data Keys to cache.
The default limit
@@ -886,13 +896,41 @@ Reports how many times we were looking up a Data Key and it was not in cache.
This sysctl is not updated for providers that need fewer Data Keys than the limit
specified in
.Va kern.geom.eli.key_cache_limit .
-.Va kern.geom.eli.unmapped_io
+.It Va kern.geom.eli.unmapped_io
Enable support for unmapped I/O buffers, currently implemented only on 64-bit
platforms.
This is an optimization which reduces the overhead of I/O processing.
This variable is intended for debugging purposes and must be set in
.Pa /boot/loader.conf .
.El
+.Sh PERFORMANCE CONSIDERATIONS
+The default value of
+.Va kern.geom.eli.threads
+is usually good for a system with one SSD.
+However, it may need to be lowered on systems with many disks,
+so as to avoid creating too much thread-switching overhead.
+On systems with more disks than CPUs, it's best to set this variable
+to 1.
+.Pp
+.Nm
+internally uses
+.Xr malloc 9
+to allocate memory for operations larger than
+.Va kern.geom.eli.use_uma_bytes ,
+but malloc is slow for allocations larger than
+.Va vm.kmem_zmax .
+So it's best to avoid writing more than
+.Ms MAX(kern.geom.eli.use_uma_bytes, vm.kmem_zmax)
+in a single write operation.
+On systems that format
+.Xr zfs 4
+on top of
+.Nm ,
+the maximum write size can be controlled by
+.Va vfs.zfs.vdev.aggregation_limit
+and
+.Va vfs.zfs.vdev.aggregation_limit_non_rotating
+for HDDs and SSDs, respectively.
.Sh EXIT STATUS
Exit status is 0 on success, and 1 if the command fails.
.Sh EXAMPLES
@@ -1204,10 +1242,8 @@ after the first time a provider is attached and before it is
initialized in this way.
.Sh SEE ALSO
.Xr crypto 4 ,
-.Xr gbde 4 ,
.Xr geom 4 ,
.Xr loader.conf 5 ,
-.Xr gbde 8 ,
.Xr geom 8 ,
.Xr crypto 9
.Sh HISTORY
diff --git a/lib/geom/eli/geom_eli.c b/lib/geom/eli/geom_eli.c
index 4c04a9256b5e..4dd1c5dea35d 100644
--- a/lib/geom/eli/geom_eli.c
+++ b/lib/geom/eli/geom_eli.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004-2019 Pawel Jakub Dawidek <pawel@dawidek.net>
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
@@ -571,27 +568,35 @@ eli_genkey_passphrase(struct gctl_req *req, struct g_eli_metadata *md, bool new,
return (0);
}
-static unsigned char *
-eli_genkey(struct gctl_req *req, struct g_eli_metadata *md, unsigned char *key,
- bool new)
+static bool
+eli_init_key_hmac_ctx(struct gctl_req *req, struct hmac_ctx *ctx, bool new)
{
- struct hmac_ctx ctx;
- bool nopassphrase;
int nfiles;
+ bool nopassphrase;
nopassphrase =
gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase");
- g_eli_crypto_hmac_init(&ctx, NULL, 0);
-
- nfiles = eli_genkey_files(req, new, "keyfile", &ctx, NULL, 0);
- if (nfiles == -1)
- return (NULL);
- else if (nfiles == 0 && nopassphrase) {
+ g_eli_crypto_hmac_init(ctx, NULL, 0);
+ nfiles = eli_genkey_files(req, new, "keyfile", ctx, NULL, 0);
+ if (nfiles == -1) {
+ return (false);
+ } else if (nfiles == 0 && nopassphrase) {
gctl_error(req, "No key components given.");
- return (NULL);
+ return (false);
}
+ return (true);
+}
+
+static unsigned char *
+eli_genkey(struct gctl_req *req, const struct hmac_ctx *ctxtemplate,
+ struct g_eli_metadata *md, unsigned char *key, bool new)
+{
+ struct hmac_ctx ctx;
+
+ memcpy(&ctx, ctxtemplate, sizeof(ctx));
+
if (eli_genkey_passphrase(req, md, new, &ctx) == -1)
return (NULL);
@@ -600,6 +605,22 @@ eli_genkey(struct gctl_req *req, struct g_eli_metadata *md, unsigned char *key,
return (key);
}
+static unsigned char *
+eli_genkey_single(struct gctl_req *req, struct g_eli_metadata *md,
+ unsigned char *key, bool new)
+{
+ struct hmac_ctx ctx;
+ unsigned char *rkey;
+
+ if (!eli_init_key_hmac_ctx(req, &ctx, new)) {
+ return (NULL);
+ }
+ rkey = eli_genkey(req, &ctx, md, key, new);
+ explicit_bzero(&ctx, sizeof(ctx));
+
+ return (rkey);
+}
+
static int
eli_metadata_read(struct gctl_req *req, const char *prov,
struct g_eli_metadata *md)
@@ -711,6 +732,7 @@ eli_init(struct gctl_req *req)
intmax_t val;
int error, i, nargs, nparams, param;
const int one = 1;
+ struct hmac_ctx ctxtemplate;
nargs = gctl_get_int(req, "nargs");
if (nargs <= 0) {
@@ -844,6 +866,10 @@ eli_init(struct gctl_req *req)
*/
nparams = req->narg - nargs - 1;
+ /* Generate HMAC context template. */
+ if (!eli_init_key_hmac_ctx(req, &ctxtemplate, true))
+ return;
+
/* Create new child request for each provider and issue to kernel */
for (i = 0; i < nargs; i++) {
r = gctl_get_handle();
@@ -885,7 +911,7 @@ eli_init(struct gctl_req *req)
arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys));
/* Generate user key. */
- if (eli_genkey(r, &md, key, true) == NULL) {
+ if (eli_genkey(r, &ctxtemplate, &md, key, true) == NULL) {
/*
* Error generating key - details added to geom request
* by eli_genkey().
@@ -1009,6 +1035,7 @@ out:
/* Clear the cached metadata, including keys. */
explicit_bzero(&md, sizeof(md));
+ explicit_bzero(&ctxtemplate, sizeof(ctxtemplate));
}
static void
@@ -1020,6 +1047,7 @@ eli_attach(struct gctl_req *req)
off_t mediasize;
int i, nargs, nparams, param;
const int one = 1;
+ struct hmac_ctx ctxtemplate;
nargs = gctl_get_int(req, "nargs");
if (nargs <= 0) {
@@ -1035,6 +1063,10 @@ eli_attach(struct gctl_req *req)
*/
nparams = req->narg - nargs - 1;
+ /* Generate HMAC context template. */
+ if (!eli_init_key_hmac_ctx(req, &ctxtemplate, false))
+ return;
+
/* Create new child request for each provider and issue to kernel */
for (i = 0; i < nargs; i++) {
r = gctl_get_handle();
@@ -1064,7 +1096,7 @@ eli_attach(struct gctl_req *req)
goto out;
}
- if (eli_genkey(r, &md, key, false) == NULL) {
+ if (eli_genkey(r, &ctxtemplate, &md, key, false) == NULL) {
/*
* Error generating key - details added to geom request
* by eli_genkey().
@@ -1098,6 +1130,7 @@ out:
/* Clear sensitive data from memory. */
explicit_bzero(cached_passphrase, sizeof(cached_passphrase));
+ explicit_bzero(&ctxtemplate, sizeof(ctxtemplate));
}
static void
@@ -1295,7 +1328,7 @@ eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md)
old = md->md_iterations;
/* Generate key for Master Key encryption. */
- if (eli_genkey(req, md, key, true) == NULL) {
+ if (eli_genkey_single(req, md, key, true) == NULL) {
explicit_bzero(key, sizeof(key));
return;
}
@@ -1330,7 +1363,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov,
}
/* Generate key for Master Key decryption. */
- if (eli_genkey(req, md, key, false) == NULL) {
+ if (eli_genkey_single(req, md, key, false) == NULL) {
explicit_bzero(key, sizeof(key));
return;
}
@@ -1387,8 +1420,14 @@ eli_setkey_detached(struct gctl_req *req, const char *prov,
bcopy(mkey, mkeydst, sizeof(mkey));
explicit_bzero(mkey, sizeof(mkey));
+ /*
+ * The previous eli_genkey() set cached_passphrase, we do not want to
+ * use that for the new passphrase so always prompt for it
+ */
+ explicit_bzero(cached_passphrase, sizeof(cached_passphrase));
+
/* Generate key for Master Key encryption. */
- if (eli_genkey(req, md, key, true) == NULL) {
+ if (eli_genkey_single(req, md, key, true) == NULL) {
explicit_bzero(key, sizeof(key));
explicit_bzero(md, sizeof(*md));
return;
@@ -1433,7 +1472,7 @@ eli_setkey(struct gctl_req *req)
if (req->error == NULL || req->error[0] == '\0') {
printf("Note, that the master key encrypted with old keys "
- "and/or passphrase may still exists in a metadata backup "
+ "and/or passphrase may still exist in a metadata backup "
"file.\n");
}
}
@@ -1534,7 +1573,7 @@ eli_resume(struct gctl_req *req)
return;
}
- if (eli_genkey(req, &md, key, false) == NULL) {
+ if (eli_genkey_single(req, &md, key, false) == NULL) {
explicit_bzero(key, sizeof(key));
return;
}