diff options
Diffstat (limited to 'lib/geom/eli')
-rw-r--r-- | lib/geom/eli/Makefile | 8 | ||||
-rw-r--r-- | lib/geom/eli/Makefile.depend | 3 | ||||
-rw-r--r-- | lib/geom/eli/geli.8 | 50 | ||||
-rw-r--r-- | lib/geom/eli/geom_eli.c | 85 |
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; } |