Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Feb 2023 18:02:52 GMT
From:      Gordon Tetlow <gordon@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 5fff09660e06 - main - geli: split the initalization of HMAC
Message-ID:  <202302081802.318I2qxg007379@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by gordon:

URL: https://cgit.FreeBSD.org/src/commit/?id=5fff09660e06a66bed6482da9c70df328e16bbb6

commit 5fff09660e06a66bed6482da9c70df328e16bbb6
Author:     Mariusz Zaborski <oshogbo@FreeBSD.org>
AuthorDate: 2023-02-08 16:41:06 +0000
Commit:     Gordon Tetlow <gordon@FreeBSD.org>
CommitDate: 2023-02-08 18:01:58 +0000

    geli: split the initalization of HMAC
    
    GELI allows to read a user key from a standard input.
    However if user initialize multiple providers at once, the standard
    input will be empty for the second and next providers.
    This caused GELI to encrypt a master key with an empty key file.
    
    This commits initialize the HMAC with the key file, and then reuse the
    finalized structure to generate different encryption keys for different
    providers.
    
    Reported by:    Nathan Dorfman
    Tested by:      philip
    Security:       FreeBSD-SA-23:01.geli
    Security:       CVE-2023-0751
---
 lib/geom/eli/geom_eli.c | 72 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 54 insertions(+), 18 deletions(-)

diff --git a/lib/geom/eli/geom_eli.c b/lib/geom/eli/geom_eli.c
index 4c04a9256b5e..8897af15b8f3 100644
--- a/lib/geom/eli/geom_eli.c
+++ b/lib/geom/eli/geom_eli.c
@@ -571,27 +571,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 +608,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 +735,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 +869,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 +914,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 +1038,7 @@ out:
 
 	/* Clear the cached metadata, including keys. */
 	explicit_bzero(&md, sizeof(md));
+	explicit_bzero(&ctxtemplate, sizeof(ctxtemplate));
 }
 
 static void
@@ -1020,6 +1050,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 +1066,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 +1099,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 +1133,7 @@ out:
 
 	/* Clear sensitive data from memory. */
 	explicit_bzero(cached_passphrase, sizeof(cached_passphrase));
+	explicit_bzero(&ctxtemplate, sizeof(ctxtemplate));
 }
 
 static void
@@ -1295,7 +1331,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 +1366,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;
 	}
@@ -1388,7 +1424,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov,
 	explicit_bzero(mkey, sizeof(mkey));
 
 	/* 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;
@@ -1534,7 +1570,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;
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202302081802.318I2qxg007379>