The previous PBKDF2 implementation used grub_crypto_hmac_buffer(), which
allocates and frees an HMAC handle on every call. This approach caused
significant performance overhead, slowing down the boot process
considerably.

This commit refactors the PBKDF2 code to use the new HMAC functions,
allowing the HMAC handle and its buffers to be allocated once and reused
across multiple operations. This change significantly reduces disk
unlocking time.

In a QEMU/OVMF test environment, this patch reduced the time to unlock a
LUKS2(*) partition from approximately 15 seconds to 4 seconds.

(*) PBKDF2 SHA256 with 3454944 iterations

Signed-off-by: Gary Lin <g...@suse.com>
---
 grub-core/lib/pbkdf2.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/grub-core/lib/pbkdf2.c b/grub-core/lib/pbkdf2.c
index 28aa96c46..410eff580 100644
--- a/grub-core/lib/pbkdf2.c
+++ b/grub-core/lib/pbkdf2.c
@@ -39,6 +39,7 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
                    unsigned int c,
                    grub_uint8_t *DK, grub_size_t dkLen)
 {
+  struct grub_crypto_hmac_handle *hnd = NULL;
   unsigned int hLen = md->mdlen;
   grub_uint8_t U[GRUB_CRYPTO_MAX_MDLEN];
   grub_uint8_t T[GRUB_CRYPTO_MAX_MDLEN];
@@ -47,7 +48,6 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
   unsigned int r;
   unsigned int i;
   unsigned int k;
-  gcry_err_code_t rc;
   grub_uint8_t *tmp;
   grub_size_t tmplen = Slen + 4;
 
@@ -72,6 +72,13 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
 
   grub_memcpy (tmp, S, Slen);
 
+  hnd = grub_crypto_hmac_init (md, P, Plen);
+  if (hnd == NULL)
+    {
+      grub_free (tmp);
+      return GPG_ERR_OUT_OF_MEMORY;
+    }
+
   for (i = 1; i - 1 < l; i++)
     {
       grub_memset (T, 0, hLen);
@@ -85,16 +92,13 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
              tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
              tmp[Slen + 3] = (i & 0x000000ff) >> 0;
 
-             rc = grub_crypto_hmac_buffer (md, P, Plen, tmp, tmplen, U);
+             grub_crypto_hmac_write (hnd, tmp, tmplen);
            }
          else
-           rc = grub_crypto_hmac_buffer (md, P, Plen, U, hLen, U);
+           grub_crypto_hmac_write (hnd, U, hLen);
 
-         if (rc != GPG_ERR_NO_ERROR)
-           {
-             grub_free (tmp);
-             return rc;
-           }
+         grub_crypto_hmac_final (hnd, U);
+         grub_crypto_hmac_reset (hnd);
 
          for (k = 0; k < hLen; k++)
            T[k] ^= U[k];
@@ -103,6 +107,7 @@ grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
       grub_memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen);
     }
 
+  grub_crypto_hmac_free (hnd);
   grub_free (tmp);
 
   return GPG_ERR_NO_ERROR;
-- 
2.43.0


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to