File 0001-lib-crypto-Introduce-new-HMAC-functions-to-reuse-buf.patch of Package grub2

From e98e880b67be178f3a5951fb345ded8c002eb6e5 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Wed, 13 Aug 2025 11:43:40 +0800
Subject: [PATCH 1/2] lib/crypto: Introduce new HMAC functions to reuse buffers

To enable more efficient buffer reuse for HMAC operations, three new
functions have been introduced. This change prevents the need to
reallocate memory for each HMAC operation.

* grub_crypto_hmac_reset(): Reinitializes the hash contexts in the HMAC
  handle.

* grub_crypto_hmac_final(): Provides the final HMAC result without
  freeing the handle, allowing it to be reused immediately.

* grub_crypto_hmac_free(): Deallocates the HMAC handle and its
  associated memory.

To further facilitate buffer reuse, 'ctx2' is now included within the HMAC
handle struct, and the initialization of 'ctx2' is moved to
grub_crypto_hmac_init().

The intermediate hash states ('ctx' and 'ctx2') for the inner and outer
padded keys are now cached. grub_crypto_hmac_reset() restores these cached
states for new operations, which avoids redundant hashing of the keys.

Signed-off-by: Gary Lin <glin@suse.com>
---
 grub-core/disk/geli.c  |  4 +-
 grub-core/lib/crypto.c | 91 ++++++++++++++++++++++++++++++------------
 include/grub/crypto.h  |  8 +++-
 3 files changed, 74 insertions(+), 29 deletions(-)

Index: grub-2.12/grub-core/disk/geli.c
===================================================================
--- grub-2.12.orig/grub-core/disk/geli.c
+++ grub-2.12/grub-core/disk/geli.c
@@ -464,9 +464,7 @@ geli_recover_key (grub_disk_t source, gr
       grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
       grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
 
-      gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
-      if (gcry_err)
-	return grub_crypto_gcry_error (gcry_err);
+      grub_crypto_hmac_fini (hnd, geomkey);
     }
 
   gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
Index: grub-2.12/grub-core/lib/crypto.c
===================================================================
--- grub-2.12.orig/grub-core/lib/crypto.c
+++ grub-2.12/grub-core/lib/crypto.c
@@ -31,7 +31,9 @@ struct grub_crypto_hmac_handle
 {
   const struct gcry_md_spec *md;
   void *ctx;
-  void *opad;
+  void *ctx2;
+  void *ctx_cache;
+  void *ctx2_cache;
 };
 
 static gcry_cipher_spec_t *grub_ciphers = NULL;
@@ -307,7 +309,8 @@ grub_crypto_hmac_init (const struct gcry
 {
   grub_uint8_t *helpkey = NULL;
   grub_uint8_t *ipad = NULL, *opad = NULL;
-  void *ctx = NULL;
+  void *ctx = NULL, *ctx2 = NULL;
+  void *ctx_cache = NULL, *ctx2_cache = NULL;
   struct grub_crypto_hmac_handle *ret = NULL;
   unsigned i;
 
@@ -318,6 +321,18 @@ grub_crypto_hmac_init (const struct gcry
   if (!ctx)
     goto err;
 
+  ctx2 = grub_malloc (md->contextsize);
+  if (!ctx2)
+    goto err;
+
+  ctx_cache = grub_malloc (md->contextsize);
+  if (!ctx_cache)
+    goto err;
+
+  ctx2_cache = grub_malloc (md->contextsize);
+  if (!ctx2_cache)
+    goto err;
+
   if ( keylen > md->blocksize )
     {
       helpkey = grub_malloc (md->mdlen);
@@ -347,26 +362,40 @@ grub_crypto_hmac_init (const struct gcry
   grub_free (helpkey);
   helpkey = NULL;
 
+  /* inner pad */
   md->init (ctx);
-
-  md->write (ctx, ipad, md->blocksize); /* inner pad */
+  md->write (ctx, ipad, md->blocksize);
+  grub_memcpy (ctx_cache, ctx, md->contextsize);
   grub_memset (ipad, 0, md->blocksize);
   grub_free (ipad);
   ipad = NULL;
 
+  /* outer pad */
+  md->init (ctx2);
+  md->write (ctx2, opad, md->blocksize);
+  grub_memcpy (ctx2_cache, ctx2, md->contextsize);
+  grub_memset (opad, 0, md->blocksize);
+  grub_free (opad);
+  opad = NULL;
+
   ret = grub_malloc (sizeof (*ret));
   if (!ret)
     goto err;
 
   ret->md = md;
   ret->ctx = ctx;
-  ret->opad = opad;
+  ret->ctx2 = ctx2;
+  ret->ctx_cache = ctx_cache;
+  ret->ctx2_cache = ctx2_cache;
 
   return ret;
 
  err:
   grub_free (helpkey);
   grub_free (ctx);
+  grub_free (ctx2);
+  grub_free (ctx_cache);
+  grub_free (ctx2_cache);
   grub_free (ipad);
   grub_free (opad);
   return NULL;
@@ -380,37 +409,48 @@ grub_crypto_hmac_write (struct grub_cryp
   hnd->md->write (hnd->ctx, data, datalen);
 }
 
-gcry_err_code_t
+void
 grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
 {
-  grub_uint8_t *p;
-  grub_uint8_t *ctx2;
+  grub_crypto_hmac_final (hnd, out);
+  grub_crypto_hmac_free (hnd);
+}
 
-  ctx2 = grub_malloc (hnd->md->contextsize);
-  if (!ctx2)
-    return GPG_ERR_OUT_OF_MEMORY;
+void
+grub_crypto_hmac_reset (struct grub_crypto_hmac_handle *hnd)
+{
+  grub_memcpy (hnd->ctx, hnd->ctx_cache, hnd->md->contextsize);
+  grub_memcpy (hnd->ctx2, hnd->ctx2_cache, hnd->md->contextsize);
+}
+
+void
+grub_crypto_hmac_final (struct grub_crypto_hmac_handle *hnd, void *out)
+{
+  grub_uint8_t *p;
 
   hnd->md->final (hnd->ctx);
   hnd->md->read (hnd->ctx);
   p = hnd->md->read (hnd->ctx);
 
-  hnd->md->init (ctx2);
-  hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
-  hnd->md->write (ctx2, p, hnd->md->mdlen);
-  hnd->md->final (ctx2);
-  grub_memset (hnd->opad, 0, hnd->md->blocksize);
-  grub_free (hnd->opad);
-  grub_memset (hnd->ctx, 0, hnd->md->contextsize);
-  grub_free (hnd->ctx);
+  hnd->md->write (hnd->ctx2, p, hnd->md->mdlen);
+  hnd->md->final (hnd->ctx2);
 
-  grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
-  grub_memset (ctx2, 0, hnd->md->contextsize);
-  grub_free (ctx2);
+  grub_memcpy (out, hnd->md->read (hnd->ctx2), hnd->md->mdlen);
+}
 
+void
+grub_crypto_hmac_free (struct grub_crypto_hmac_handle *hnd)
+{
+  grub_memset (hnd->ctx, 0, hnd->md->contextsize);
+  grub_free (hnd->ctx);
+  grub_memset (hnd->ctx2, 0, hnd->md->contextsize);
+  grub_free (hnd->ctx2);
+  grub_memset (hnd->ctx_cache, 0, hnd->md->contextsize);
+  grub_free (hnd->ctx_cache);
+  grub_memset (hnd->ctx2_cache, 0, hnd->md->contextsize);
+  grub_free (hnd->ctx2_cache);
   grub_memset (hnd, 0, sizeof (*hnd));
   grub_free (hnd);
-
-  return GPG_ERR_NO_ERROR;
 }
 
 gcry_err_code_t
@@ -425,7 +465,8 @@ grub_crypto_hmac_buffer (const struct gc
     return GPG_ERR_OUT_OF_MEMORY;
 
   grub_crypto_hmac_write (hnd, data, datalen);
-  return grub_crypto_hmac_fini (hnd, out);
+  grub_crypto_hmac_fini (hnd, out);
+  return GPG_ERR_NO_ERROR;
 }
 
 
Index: grub-2.12/include/grub/crypto.h
===================================================================
--- grub-2.12.orig/include/grub/crypto.h
+++ grub-2.12/include/grub/crypto.h
@@ -358,8 +358,14 @@ void
 grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
 			const void *data,
 			grub_size_t datalen);
-gcry_err_code_t
+void
 grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out);
+void
+grub_crypto_hmac_reset (struct grub_crypto_hmac_handle *hnd);
+void
+grub_crypto_hmac_final (struct grub_crypto_hmac_handle *hnd, void *out);
+void
+grub_crypto_hmac_free (struct grub_crypto_hmac_handle *hnd);
 
 gcry_err_code_t
 grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
openSUSE Build Service is sponsored by