]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
lib/pbkdf2: Optimize PBKDF2 by reusing HMAC handle
authorGary Lin <glin@suse.com>
Thu, 14 Aug 2025 06:32:42 +0000 (14:32 +0800)
committerDaniel Kiper <daniel.kiper@oracle.com>
Thu, 23 Oct 2025 17:14:59 +0000 (19:14 +0200)
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 <glin@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/lib/pbkdf2.c

index 28aa96c46c2bd452da309edd1716f7601c091ace..410eff580fefa93ca66ff9d763d2bd1ee2a92e2e 100644 (file)
@@ -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;