grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
From: Vladimir Serbinenko <phcoder@gmail.com>
To: grub-devel@gnu.org
Cc: Vladimir Serbinenko <phcoder@gmail.com>
Subject: [PATCH 2/3] Adjust import script, definitions and API users for libgcrypt 1.10
Date: Thu, 16 May 2024 21:27:42 +0300	[thread overview]
Message-ID: <20240516182743.2350-2-phcoder@gmail.com> (raw)
In-Reply-To: <20240516182743.2350-1-phcoder@gmail.com>

---
 autogen.sh                                 |   1 +
 conf/Makefile.common                       |   4 +-
 grub-core/Makefile.core.def                |  36 +-
 grub-core/commands/hashsum.c               |   2 +-
 grub-core/commands/legacycfg.c             |   6 +-
 grub-core/commands/pgp.c                   | 114 +---
 grub-core/commands/xnu_uuid.c              |   2 +-
 grub-core/disk/cryptodisk.c                |   2 +-
 grub-core/io/gzio.c                        |   2 +-
 grub-core/io/lzopio.c                      |   2 +-
 grub-core/lib/adler32.c                    |  21 +-
 grub-core/lib/b64dec.c                     | 293 +++++++++
 grub-core/lib/crc64.c                      |  24 +-
 grub-core/lib/crypto.c                     | 245 +++++++-
 grub-core/lib/libgcrypt/src/gcrypt-int.h   |  51 --
 grub-core/lib/libgcrypt_wrap/cipher_wrap.h |  12 +-
 grub-core/lib/libgcrypt_wrap/md.c          | 687 +++++++++++++++++++++
 grub-core/lib/libgcrypt_wrap/mem.c         |  83 ++-
 grub-core/lib/xzembed/xz_dec_stream.c      |  18 +-
 grub-core/tests/dsa_sexp_test.c            | 107 ++++
 grub-core/tests/rsa_sexp_test.c            |  81 +++
 include/grub/crypto.h                      | 261 ++++++--
 include/grub/gcrypt/gpg-error.h            |   9 +
 util/grub-fstest.c                         |   2 +-
 util/import_gcry.py                        | 122 ++--
 util/import_gcrypt_inth.sed                |  17 +
 util/import_gcrypth.sed                    |   2 -
 27 files changed, 1942 insertions(+), 264 deletions(-)
 create mode 100644 grub-core/lib/b64dec.c
 create mode 100644 grub-core/lib/libgcrypt_wrap/md.c
 create mode 100644 grub-core/tests/dsa_sexp_test.c
 create mode 100644 grub-core/tests/rsa_sexp_test.c
 create mode 100644 util/import_gcrypt_inth.sed

diff --git a/autogen.sh b/autogen.sh
index 195daa541..04779c955 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -35,6 +35,7 @@ ${PYTHON} util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.t
 echo "Importing libgcrypt..."
 ${PYTHON} util/import_gcry.py grub-core/lib/libgcrypt/ grub-core
 sed -n -f util/import_gcrypth.sed < grub-core/lib/libgcrypt/src/gcrypt.h.in > include/grub/gcrypt/gcrypt.h
+sed -n -f util/import_gcrypt_inth.sed < grub-core/lib/libgcrypt/src/gcrypt-int.h >> include/grub/gcrypt/gcrypt.h
 if [ -f include/grub/gcrypt/g10lib.h ]; then
     rm include/grub/gcrypt/g10lib.h
 fi
diff --git a/conf/Makefile.common b/conf/Makefile.common
index b8f216f6c..1fd3fc9da 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -81,8 +81,8 @@ CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-co
 CFLAGS_POSIX = -fno-builtin
 CPPFLAGS_POSIX = -I$(top_srcdir)/grub-core/lib/posix_wrap
 
-CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX)
-CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -I$(top_srcdir)/include/grub/gcrypt
+CFLAGS_GCRY = -Wno-error=sign-compare -Wno-error=shift-count-overflow -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX)
+CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -D_GCRYPT_CONFIG_H_INCLUDED=1 -DHAVE_STRTOUL=1 -I$(top_srcdir)/include/grub/gcrypt
 
 CPPFLAGS_EFIEMU = -I$(top_srcdir)/grub-core/efiemu/runtime
 
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1571421d7..59270fc9a 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -971,8 +971,8 @@ module = {
 module = {
   name = pgp;
   common = commands/pgp.c;
-  cflags = '$(CFLAGS_POSIX)';
-  cppflags = '-I$(srcdir)/lib/posix_wrap';
+  cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
+  cppflags = '$(CPPFLAGS_GCRY)';
 };
 
 module = {
@@ -2165,6 +2165,22 @@ module = {
   common = tests/setjmp_test.c;
 };
 
+module = {
+  name = dsa_sexp_test;
+  common = tests/dsa_sexp_test.c;
+
+  cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
+  cppflags = '$(CPPFLAGS_GCRY)';
+};
+
+module = {
+  name = rsa_sexp_test;
+  common = tests/rsa_sexp_test.c;
+
+  cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
+  cppflags = '$(CPPFLAGS_GCRY)';
+};
+
 module = {
   name = signature_test;
   common = tests/signature_test.c;
@@ -2519,7 +2535,23 @@ module = {
   common = lib/libgcrypt-grub/mpi/mpicoder.c;
   common = lib/libgcrypt-grub/mpi/mpih-rshift.c;
   common = lib/libgcrypt-grub/mpi/mpi-inline.c;
+  common = lib/libgcrypt-grub/mpi/mpih-const-time.c;
+  common = lib/libgcrypt-grub/mpi/mpi-scan.c;
+  common = lib/libgcrypt-grub/src/const-time.c;
   common = lib/libgcrypt_wrap/mem.c;
+  common = lib/libgcrypt_wrap/md.c;
+
+  cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare -Wno-unused-but-set-variable';
+  cppflags = '$(CPPFLAGS_GCRY)';
+};
+
+module = {
+  name = pubkey;
+  common = lib/libgcrypt-grub/cipher/pubkey-util.c;
+  common = lib/libgcrypt-grub/cipher/rsa-common.c;
+  common = lib/libgcrypt-grub/cipher/dsa-common.c;
+  common = lib/libgcrypt-grub/src/sexp.c;
+  common = lib/b64dec.c;
 
   cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
   cppflags = '$(CPPFLAGS_GCRY)';
diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c
index d56b5b0bb..b6f8e3d1a 100644
--- a/grub-core/commands/hashsum.c
+++ b/grub-core/commands/hashsum.c
@@ -73,7 +73,7 @@ hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result)
   if (!readbuf || !context)
     goto fail;
 
-  hash->init (context);
+  hash->init (context, 0);
   while (1)
     {
       grub_ssize_t r;
diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
index e9e9d94ef..052bb110d 100644
--- a/grub-core/commands/legacycfg.c
+++ b/grub-core/commands/legacycfg.c
@@ -625,7 +625,7 @@ check_password_md5_real (const char *entered,
   if (!ctx)
     return 0;
 
-  GRUB_MD_MD5->init (ctx);
+  GRUB_MD_MD5->init (ctx, 0);
   GRUB_MD_MD5->write (ctx, entered, enteredlen);
   GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
   GRUB_MD_MD5->write (ctx, entered, enteredlen);
@@ -633,7 +633,7 @@ check_password_md5_real (const char *entered,
   GRUB_MD_MD5->final (ctx);
   grub_memcpy (alt_result, digest, MD5_HASHLEN);
 
-  GRUB_MD_MD5->init (ctx);
+  GRUB_MD_MD5->init (ctx, 0);
   GRUB_MD_MD5->write (ctx, entered, enteredlen);
   GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */
   for (i = enteredlen; i > 16; i -= 16)
@@ -649,7 +649,7 @@ check_password_md5_real (const char *entered,
     {
       grub_memcpy (alt_result, digest, 16);
 
-      GRUB_MD_MD5->init (ctx);
+      GRUB_MD_MD5->init (ctx, 0);
       if ((i & 1) != 0)
 	GRUB_MD_MD5->write (ctx, entered, enteredlen);
       else
diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
index c6766f044..22eca97ff 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -136,41 +136,27 @@ struct signature_v4_header
   grub_uint16_t hashed_sub;
 } GRUB_PACKED;
 
-const char *hashes[] = {
-  [0x01] = "md5",
-  [0x02] = "sha1",
-  [0x03] = "ripemd160",
-  [0x08] = "sha256",
-  [0x09] = "sha384",
-  [0x0a] = "sha512",
-  [0x0b] = "sha224"
-};
-
 struct gcry_pk_spec *grub_crypto_pk_dsa;
 struct gcry_pk_spec *grub_crypto_pk_ecdsa;
 struct gcry_pk_spec *grub_crypto_pk_rsa;
 
-static int
-dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
-	 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
-static int
-rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
-	 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
-
 struct
 {
   const char *name;
+  const char *sigsexp;
   grub_size_t nmpisig;
+  const char *pubsexp;
   grub_size_t nmpipub;
   struct gcry_pk_spec **algo;
-  int (*pad) (gcry_mpi_t *hmpi, grub_uint8_t *hval,
-	      const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
+  const char *padding;
   const char *module;
 } pkalgos[] =
   {
-    [1] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" },
-    [3] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" },
-    [17] = { "dsa", 2, 4, &grub_crypto_pk_dsa, dsa_pad, "gcry_dsa" },
+    [1] = { "rsa", "(sig-val (rsa (s %M)))", 1, "(public-key (dsa (n %M) (e %M)))", 2, &grub_crypto_pk_rsa, "pkcs1", "gcry_rsa" },
+    [3] = { "rsa", "(sig-val (rsa (s %M)))", 1, "(public-key (dsa (n %M) (e %M)))", 2, &grub_crypto_pk_rsa, "pkcs1", "gcry_rsa" },
+    [17] = { "dsa", "(sig-val (dsa (r %M) (s %M)))", 2,
+	     "(public-key (dsa (p %M) (q %M) (g %M) (y %M)))",
+	     4, &grub_crypto_pk_dsa, "raw", "gcry_dsa" },
   };
 
 struct grub_public_key
@@ -196,7 +182,7 @@ free_pk (struct grub_public_key *pk)
       grub_size_t i;
       for (i = 0; i < ARRAY_SIZE (sk->mpis); i++)
 	if (sk->mpis[i])
-	  gcry_mpi_release (sk->mpis[i]);
+	  _gcry_mpi_release (sk->mpis[i]);
       nsk = sk->next;
       grub_free (sk);
     }
@@ -303,7 +289,7 @@ grub_load_public_key (grub_file_t f)
 	goto fail;
 
       grub_memset (fingerprint_context, 0, GRUB_MD_SHA1->contextsize);
-      GRUB_MD_SHA1->init (fingerprint_context);
+      GRUB_MD_SHA1->init (fingerprint_context, 0);
       GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1);
       len_be = grub_cpu_to_be16 (len);
       GRUB_MD_SHA1->write (fingerprint_context, &len_be, sizeof (len_be));
@@ -336,7 +322,7 @@ grub_load_public_key (grub_file_t f)
 
 	  GRUB_MD_SHA1->write (fingerprint_context, buffer, lb + sizeof (grub_uint16_t));
 
-	  if (gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP,
+	  if (_gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP,
 			     buffer, lb + sizeof (grub_uint16_t), 0))
 	    {
 	      grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
@@ -394,51 +380,6 @@ grub_crypto_pk_locate_subkey_in_trustdb (grub_uint64_t keyid)
   return 0;
 }
 
-
-static int
-dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
-	 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
-{
-  unsigned nbits = gcry_mpi_get_nbits (sk->mpis[1]);
-  grub_dprintf ("crypt", "must be %u bits got %d bits\n", nbits,
-		(int)(8 * hash->mdlen));
-  return gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, hval,
-			nbits / 8 < (unsigned) hash->mdlen ? nbits / 8
-			: (unsigned) hash->mdlen, 0);
-}
-
-static int
-rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
-	 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
-{
-  grub_size_t tlen, emlen, fflen;
-  grub_uint8_t *em, *emptr;
-  unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]);
-  int ret;
-  tlen = hash->mdlen + hash->asnlen;
-  emlen = (nbits + 7) / 8;
-  if (emlen < tlen + 11)
-    return 1;
-
-  em = grub_malloc (emlen);
-  if (!em)
-    return 1;
-
-  em[0] = 0x00;
-  em[1] = 0x01;
-  fflen = emlen - tlen - 3;
-  for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
-    *emptr = 0xff;
-  *emptr++ = 0x00;
-  grub_memcpy (emptr, hash->asnoid, hash->asnlen);
-  emptr += hash->asnlen;
-  grub_memcpy (emptr, hval, hash->mdlen);
-
-  ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
-  grub_free (em);
-  return ret;
-}
-
 struct grub_pubkey_context
 {
   grub_file_t sig;
@@ -483,15 +424,12 @@ grub_verify_signature_init (struct grub_pubkey_context *ctxt, grub_file_t sig)
   if (t != 0)
     return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
 
-  if (h >= ARRAY_SIZE (hashes) || hashes[h] == NULL)
-    return grub_error (GRUB_ERR_BAD_SIGNATURE, "unknown hash");
-
   if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL)
     return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
 
-  ctxt->hash = grub_crypto_lookup_md_by_name (hashes[h]);
+  ctxt->hash = grub_crypto_lookup_md_by_algo (h);
   if (!ctxt->hash)
-    return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]);
+    return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%d' not loaded", h);
 
   grub_dprintf ("crypt", "alive\n");
 
@@ -499,7 +437,7 @@ grub_verify_signature_init (struct grub_pubkey_context *ctxt, grub_file_t sig)
   if (!ctxt->hash_context)
     return grub_errno;
 
-  ctxt->hash->init (ctxt->hash_context);
+  ctxt->hash->init (ctxt->hash_context, 0);
   ctxt->sig = sig;
 
   return GRUB_ERR_NONE;
@@ -528,7 +466,6 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt,
   grub_uint16_t unhashed_sub;
   grub_ssize_t r;
   grub_uint8_t hash_start[2];
-  gcry_mpi_t hmpi;
   grub_uint64_t keyid = 0;
   struct grub_public_subkey *sk;
 
@@ -620,7 +557,7 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt,
       grub_memcpy (readbuf, &l, sizeof (l));
       grub_dprintf ("crypt", "alive\n");
 
-      if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP,
+      if (_gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP,
 			 readbuf, lb + sizeof (grub_uint16_t), 0))
 	goto fail;
       grub_dprintf ("crypt", "alive\n");
@@ -638,8 +575,6 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt,
       goto fail;
     }
 
-  if (pkalgos[pk].pad (&hmpi, hval, ctxt->hash, sk))
-    goto fail;
   if (!*pkalgos[pk].algo)
     {
       grub_dl_load (pkalgos[pk].module);
@@ -652,7 +587,24 @@ grub_verify_signature_real (struct grub_pubkey_context *ctxt,
 		  pkalgos[pk].module);
       goto fail;
     }
-  if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0))
+
+  gcry_sexp_t hsexp, pubkey, sig;
+  grub_size_t errof;
+
+  if(_gcry_sexp_build(&hsexp, &errof, "(data (flags %s) (hash %s %b))", pkalgos[pk].padding, ctxt->hash->name, ctxt->hash->mdlen, hval))
+    goto fail;
+
+  if(_gcry_sexp_build(&pubkey, &errof, pkalgos[pk].pubsexp, sk->mpis[0], sk->mpis[1], sk->mpis[2], sk->mpis[3]))
+    goto fail;
+
+  if(_gcry_sexp_build(&sig, &errof, pkalgos[pk].sigsexp, mpis[0], mpis[1]))
+    goto fail;
+
+  _gcry_sexp_dump(sig);
+  _gcry_sexp_dump(hsexp);
+  _gcry_sexp_dump(pubkey);
+
+  if ((*pkalgos[pk].algo)->verify (sig, hsexp, pubkey))
     goto fail;
 
   grub_free (readbuf);
diff --git a/grub-core/commands/xnu_uuid.c b/grub-core/commands/xnu_uuid.c
index ae4b3a415..1406c43f5 100644
--- a/grub-core/commands/xnu_uuid.c
+++ b/grub-core/commands/xnu_uuid.c
@@ -68,7 +68,7 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
   ctx = grub_zalloc (GRUB_MD_MD5->contextsize);
   if (!ctx)
     return grub_errno;
-  GRUB_MD_MD5->init (ctx);
+  GRUB_MD_MD5->init (ctx, 0);
   GRUB_MD_MD5->write (ctx, hash_prefix, sizeof (hash_prefix));
   GRUB_MD_MD5->write (ctx, &serial, sizeof (serial));
   GRUB_MD_MD5->final (ctx);
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 2246af51b..7ff1c5322 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -296,7 +296,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	      return GPG_ERR_OUT_OF_MEMORY;
 
 	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
-	    dev->iv_hash->init (ctx);
+	    dev->iv_hash->init (ctx, 0);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
 	    dev->iv_hash->final (ctx);
diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index ca9355751..30c863e5b 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -1184,7 +1184,7 @@ initialize_tables (grub_gzio_t gzio)
   gzio->td = NULL;
 
   if (gzio->hcontext)
-    gzio->hdesc->init(gzio->hcontext);
+    gzio->hdesc->init(gzio->hcontext, 0);
 }
 
 
diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c
index a7d442543..cea942308 100644
--- a/grub-core/io/lzopio.c
+++ b/grub-core/io/lzopio.c
@@ -345,7 +345,7 @@ test_header (grub_file_t file)
     if (! context)
       return 0;
 
-    hcheck->init(context);
+    hcheck->init(context, 0);
 
     /* MAGIC is not included in check calculation.  */
     hcheck->write(context, &header.lzop_version, sizeof(header)- LZOP_MAGIC_SIZE);
diff --git a/grub-core/lib/adler32.c b/grub-core/lib/adler32.c
index 43b68af62..f849ccee6 100644
--- a/grub-core/lib/adler32.c
+++ b/grub-core/lib/adler32.c
@@ -29,10 +29,12 @@ struct adler32_context
 };
 
 static void
-adler32_init (void *context)
+adler32_init (void *context, unsigned int flags)
 {
   struct adler32_context *ctx = context;
 
+  (void) flags;
+
   ctx->a = 1;
   ctx->b = 0;
 }
@@ -81,13 +83,22 @@ adler32_read (void *context)
 
 static gcry_md_spec_t spec_adler32 =
   {
-    "ADLER32", 0, 0, 0, 4,
-    adler32_init, adler32_write, adler32_final, adler32_read,
-    sizeof (struct adler32_context),
+    .algo = GCRY_MD_ADLER32,
+    .flags = {.disabled = 0, .fips = 0},
+    .name = "ADLER32",
+    .asnoid = NULL,
+    .asnlen = 0,
+    .oids = NULL,
+    .mdlen = 4,
+    .init = adler32_init,
+    .write = adler32_write,
+    .final = adler32_final,
+    .read = adler32_read,
+    .contextsize = sizeof (struct adler32_context),
+    .blocksize = 64,
 #ifdef GRUB_UTIL
     .modname = "adler32",
 #endif
-    .blocksize = 64
   };
 
 
diff --git a/grub-core/lib/b64dec.c b/grub-core/lib/b64dec.c
new file mode 100644
index 000000000..8aafa9700
--- /dev/null
+++ b/grub-core/lib/b64dec.c
@@ -0,0 +1,293 @@
+/* b64dec.c - Simple Base64 decoder.
+ * Copyright (C) 2008, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2008, 2011, 2016 g10 Code GmbH
+ *
+ * This file is part of Libgpg-error.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This file was originally a part of GnuPG.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <grub/crypto.h>
+
+struct _gpgrt_b64state
+{
+  int idx;
+  int quad_count;
+  char *title;
+  unsigned char radbuf[4];
+  unsigned int crc;
+  gpg_err_code_t lasterr;
+  unsigned int flags;
+  unsigned int stop_seen:1;
+  unsigned int invalid_encoding:1;
+  unsigned int using_decoder:1;
+};
+
+
+/* The reverse base-64 list used for base-64 decoding. */
+static unsigned char const asctobin[128] =
+  {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+    0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+    0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+    0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+    0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+    0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
+  };
+
+enum decoder_states
+  {
+    s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin,
+    s_b64_0, s_b64_1, s_b64_2, s_b64_3,
+    s_waitendtitle, s_waitend
+  };
+
+
+
+/* Allocate and initialize the context for the base64 decoder.  If
+   TITLE is NULL a plain base64 decoding is done.  If it is the empty
+   string the decoder will skip everything until a "-----BEGIN " line
+   has been seen, decoding ends at a "----END " line.  */
+gpgrt_b64state_t
+gpgrt_b64dec_start (const char *title)
+{
+  gpgrt_b64state_t state;
+  char *t = NULL;
+
+  if (title)
+    {
+      t = grub_strdup (title);
+      if (!t)
+        return NULL;
+    }
+
+  state = grub_calloc (1, sizeof (struct _gpgrt_b64state));
+  if (!state)
+    {
+      grub_free (t);
+      return NULL;
+    }
+
+  if (t)
+    {
+      state->title = t;
+      state->idx = s_init;
+    }
+  else
+    state->idx = s_b64_0;
+
+  state->using_decoder = 1;
+
+  return state;
+}
+
+
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER.  Stores the
+   new length of the buffer at R_NBYTES. */
+gpg_err_code_t
+gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length,
+                    size_t *r_nbytes)
+{
+  enum decoder_states ds = state->idx;
+  unsigned char val = state->radbuf[0];
+  int pos = state->quad_count;
+  char *d, *s;
+
+  if (state->lasterr)
+    return state->lasterr;
+
+  if (state->stop_seen)
+    {
+      *r_nbytes = 0;
+      state->lasterr = GPG_ERR_EOF;
+      grub_free (state->title);
+      state->title = NULL;
+      return state->lasterr;
+    }
+
+  for (s=d=buffer; length && !state->stop_seen; length--, s++)
+    {
+    again:
+      switch (ds)
+        {
+        case s_idle:
+          if (*s == '\n')
+            {
+              ds = s_lfseen;
+              pos = 0;
+            }
+          break;
+        case s_init:
+          ds = s_lfseen;
+          /* Fall through */
+        case s_lfseen:
+          if (*s != "-----BEGIN "[pos])
+            {
+              ds = s_idle;
+              goto again;
+            }
+          else if (pos == 10)
+            {
+              pos = 0;
+              ds = s_beginseen;
+            }
+          else
+            pos++;
+          break;
+        case s_beginseen:
+          if (*s != "PGP "[pos])
+            ds = s_begin; /* Not a PGP armor.  */
+          else if (pos == 3)
+            ds = s_waitheader;
+          else
+            pos++;
+          break;
+        case s_waitheader:
+          if (*s == '\n')
+            ds = s_waitblank;
+          break;
+        case s_waitblank:
+          if (*s == '\n')
+            ds = s_b64_0; /* blank line found.  */
+          else if (*s == ' ' || *s == '\r' || *s == '\t')
+            ; /* Ignore spaces. */
+          else
+            {
+              /* Armor header line.  Note that we don't care that our
+               * FSM accepts a header prefixed with spaces.  */
+              ds = s_waitheader; /* Wait for next header.  */
+            }
+          break;
+        case s_begin:
+          if (*s == '\n')
+            ds = s_b64_0;
+          break;
+        case s_b64_0:
+        case s_b64_1:
+        case s_b64_2:
+        case s_b64_3:
+          {
+            int c;
+
+            if (*s == '-' && state->title)
+              {
+                /* Not a valid Base64 character: assume end
+                   header.  */
+                ds = s_waitend;
+              }
+            else if (*s == '=')
+              {
+                /* Pad character: stop */
+                if (ds == s_b64_1)
+                  *d++ = val;
+                ds = state->title? s_waitendtitle : s_waitend;
+              }
+            else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
+              ; /* Skip white spaces. */
+            else if ( (*s & 0x80)
+                      || (c = asctobin[*(unsigned char *)s]) == 255)
+              {
+                /* Skip invalid encodings.  */
+                state->invalid_encoding = 1;
+              }
+            else if (ds == s_b64_0)
+              {
+                val = c << 2;
+                ds = s_b64_1;
+              }
+            else if (ds == s_b64_1)
+              {
+                val |= (c>>4)&3;
+                *d++ = val;
+                val = (c<<4)&0xf0;
+                ds = s_b64_2;
+              }
+            else if (ds == s_b64_2)
+              {
+                val |= (c>>2)&15;
+                *d++ = val;
+                val = (c<<6)&0xc0;
+                ds = s_b64_3;
+              }
+            else
+              {
+                val |= c&0x3f;
+                *d++ = val;
+                ds = s_b64_0;
+              }
+          }
+          break;
+        case s_waitendtitle:
+          if (*s == '-')
+            ds = s_waitend;
+          break;
+        case s_waitend:
+          if ( *s == '\n')
+            state->stop_seen = 1;
+          break;
+        default:
+          grub_fatal ("invalid state");
+        }
+    }
+
+
+  state->idx = ds;
+  state->radbuf[0] = val;
+  state->quad_count = pos;
+  *r_nbytes = (d -(char*) buffer);
+  return 0;
+}
+
+
+/* Return an error code in case an encoding error has been found
+   during decoding. */
+gpg_err_code_t
+gpgrt_b64dec_finish (gpgrt_b64state_t state)
+{
+  gpg_error_t err;
+
+  if (!state)
+    return 0;  /* Already released.  */
+
+  if (!state->using_decoder)
+    err = GPG_ERR_CONFLICT;  /* State was allocated for the encoder.  */
+  else if (state->lasterr)
+    err = state->lasterr;
+  else
+    {
+      grub_free (state->title);
+      err = state->invalid_encoding? GPG_ERR_BAD_DATA : 0;
+    }
+  grub_free (state);
+
+  return err;
+}
diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c
index 4960f3f89..c231fa97c 100644
--- a/grub-core/lib/crc64.c
+++ b/grub-core/lib/crc64.c
@@ -61,8 +61,10 @@ init_crc64_table (void)
 }
 
 static void
-crc64_init (void *context)
+crc64_init (void *context, unsigned int flags)
 {
+  (void) flags;
+
   if (! crc64_table[1])
     init_crc64_table ();
   *(grub_uint64_t *) context = 0;
@@ -97,10 +99,22 @@ crc64_final (void *context __attribute__ ((unused)))
 
 gcry_md_spec_t _gcry_digest_spec_crc64 =
   {
-    "CRC64", 0, 0, 0, 8,
-    crc64_init, crc64_write, crc64_final, crc64_read,
-    sizeof (grub_uint64_t),
-    .blocksize = 64
+    .algo = GCRY_MD_CRC64,
+    .flags = {.disabled = 0, .fips = 0},
+    .name = "CRC64",
+    .asnoid = NULL,
+    .asnlen = 0,
+    .oids = NULL,
+    .mdlen = 8,
+    .init = crc64_init,
+    .write = crc64_write,
+    .final = crc64_final,
+    .read = crc64_read,
+    .contextsize = sizeof (grub_uint64_t),
+    .blocksize = 64,
+#ifdef GRUB_UTIL
+    .modname = "crc64",
+#endif
   };
 
 GRUB_MOD_INIT(crc64)
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
index 396f76410..dd60dd4ac 100644
--- a/grub-core/lib/crypto.c
+++ b/grub-core/lib/crypto.c
@@ -37,6 +37,8 @@ struct grub_crypto_hmac_handle
 static gcry_cipher_spec_t *grub_ciphers = NULL;
 static gcry_md_spec_t *grub_digests = NULL;
 
+int _gcry_no_fips_mode_required = 1;
+
 void (*grub_crypto_autoload_hook) (const char *name) = NULL;
 
 /* Based on libgcrypt-1.4.4/src/misc.c.  */
@@ -56,6 +58,17 @@ _gcry_burn_stack (int size)
   grub_burn_stack (size);
 }
 
+void
+__gcry_burn_stack (unsigned int size)
+{
+  grub_burn_stack (size);
+}
+
+void
+__gcry_burn_stack_dummy (void)
+{
+}
+
 void __attribute__ ((noreturn))
 _gcry_assert_failed (const char *expr, const char *file, int line,
 		     const char *func)
@@ -64,6 +77,12 @@ _gcry_assert_failed (const char *expr, const char *file, int line,
   grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func);
 }
 
+void
+_gcry_bug( const char *file, int line, const char *func )
+{
+    grub_fatal ("... this is a bug (%s:%d:%s)\n", file, line, func);
+}
+
 
 void _gcry_log_error (const char *fmt, ...)
 {
@@ -83,6 +102,36 @@ void _gcry_log_error (const char *fmt, ...)
     }
 }
 
+void _gcry_log_info (const char *fmt, ...)
+{
+  va_list args;
+  const char *debug = grub_env_get ("debug");
+
+  if (! debug)
+    return;
+
+  if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt"))
+    {
+      grub_printf ("gcrypt info: ");
+      va_start (args, fmt);
+      grub_vprintf (fmt, args);
+      va_end (args);
+      grub_refresh ();
+    }
+}
+
+void
+_gcry_fast_wipememory2 (void *ptr, int set, grub_size_t len)
+{
+  grub_memset(ptr, set, len);
+}
+
+void
+_gcry_fast_wipememory (void *ptr, grub_size_t len)
+{
+  grub_memset(ptr, 0, len);
+}
+
 void
 grub_cipher_register (gcry_cipher_spec_t *cipher)
 {
@@ -129,7 +178,7 @@ grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
 
   if (hash->contextsize > sizeof (ctx))
     grub_fatal ("Too large md context");
-  hash->init (&ctx);
+  hash->init (&ctx, 0);
   hash->write (&ctx, in, inlen);
   hash->final (&ctx);
   grub_memcpy (out, hash->read (&ctx), hash->mdlen);
@@ -153,6 +202,91 @@ grub_crypto_lookup_md_by_name (const char *name)
     }
 }
 
+const gcry_md_spec_t *
+grub_crypto_lookup_md_by_oid (const char *oid)
+{
+  const gcry_md_spec_t *md;
+
+  if (!oid)
+    return NULL;
+
+  if (grub_strncmp (oid, "oid.", 4) == 0 || grub_strncmp (oid, "OID.", 4) == 0)
+    oid += 4;
+
+
+  for (md = grub_digests; md; md = md->next)
+    {
+      const gcry_md_oid_spec_t *oid_specs = md->oids;
+      if (oid_specs)
+        {
+          for (int j = 0; oid_specs[j].oidstring; j++)
+            if (grub_strcasecmp (oid, oid_specs[j].oidstring) == 0)
+              return md;
+        }
+    }
+
+  return NULL;
+}
+
+static const char *md_algos[] = {
+    [1] = "MD5",
+    [2] = "SHA1",
+    [3] = "RIPEMD160",
+    [6] = "TIGER",
+    [8] = "SHA256",
+    [9] = "SHA384",
+    [10] = "SHA512",
+    [11] = "SHA224",
+
+    [301] = "MD4",
+    [302] = "CRC32",
+    [303] = "CRC32RFC1510",
+    [304] = "CRC24RFC2440",
+    [305] = "WHIRLPOOL",
+    [306] = "TIGER1",
+    [307] = "TIGER2",
+    [308] = "GOSTR3411_94",
+    [309] = "STRIBOG256",
+    [310] = "STRIBOG512",
+    [311] = "GOSTR3411_CP",
+    [312] = "SHA3-224",
+    [313] = "SHA3-256",
+    [314] = "SHA3-384",
+    [315] = "SHA3-512",
+    [316] = "SHAKE128",
+    [317] = "SHAKE256",
+    [318] = "BLAKE2B_512",
+    [319] = "BLAKE2B_384",
+    [320] = "BLAKE2B_256",
+    [321] = "BLAKE2B_160",
+    [322] = "BLAKE2S_256",
+    [323] = "BLAKE2S_224",
+    [324] = "BLAKE2S_160",
+    [325] = "BLAKE2S_128",
+    [326] = "SM3",
+    [327] = "SHA512_256",
+    [328] = "SHA512_224",
+};
+
+
+const gcry_md_spec_t *
+grub_crypto_lookup_md_by_algo (int algo)
+{
+  const gcry_md_spec_t *md;
+  int first = 1;
+  while (1)
+    {
+      for (md = grub_digests; md; md = md->next)
+	if (algo == md->algo)
+	  return md;
+      if (grub_crypto_autoload_hook && first && algo > 0 && algo < (int)ARRAY_SIZE(md_algos) && md_algos[algo]) {
+	grub_crypto_autoload_hook (md_algos[algo]);
+      } else
+	return NULL;
+      first = 0;
+    }
+}
+
 const gcry_cipher_spec_t *
 grub_crypto_lookup_cipher_by_name (const char *name)
 {
@@ -196,7 +330,9 @@ grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
 			    const unsigned char *key,
 			    unsigned keylen)
 {
-  return cipher->cipher->setkey (cipher->ctx, key, keylen);
+  /* TODO: Fix this. It's ugly as hell.  */
+  void *bulk_ops[100];
+  return cipher->cipher->setkey (cipher->ctx, key, keylen, (void *) bulk_ops);
 }
 
 gcry_err_code_t
@@ -343,7 +479,7 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md,
   grub_free (helpkey);
   helpkey = NULL;
 
-  md->init (ctx);
+  md->init (ctx, 0);
 
   md->write (ctx, ipad, md->blocksize); /* inner pad */
   grub_memset (ipad, 0, md->blocksize);
@@ -390,7 +526,7 @@ grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
   hnd->md->read (hnd->ctx);
   p = hnd->md->read (hnd->ctx);
 
-  hnd->md->init (ctx2);
+  hnd->md->init (ctx2, 0);
   hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
   hnd->md->write (ctx2, p, hnd->md->mdlen);
   hnd->md->final (ctx2);
@@ -433,19 +569,106 @@ grub_crypto_gcry_error (gcry_err_code_t in)
   return GRUB_ACCESS_DENIED;
 }
 
+
+/*
+ * Compare byte arrays of length LEN, return 1 if it's not same,
+ * 0, otherwise.
+ */
 int
-grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
+grub_crypto_memcmp (const void *b1, const void *b2, grub_size_t len)
 {
-  register grub_size_t counter = 0;
-  const grub_uint8_t *pa, *pb;
+  const grub_uint8_t *a = b1;
+  const grub_uint8_t *b = b2;
+  int ab, ba;
+  grub_size_t i;
 
-  for (pa = a, pb = b; n; pa++, pb++, n--)
+  /* Constant-time compare. */
+  for (i = 0, ab = 0, ba = 0; i < len; i++)
     {
-      if (*pa != *pb)
-	counter++;
+      /* If a[i] != b[i], either ab or ba will be negative. */
+      ab |= a[i] - b[i];
+      ba |= b[i] - a[i];
     }
 
-  return !!counter;
+  /* 'ab | ba' is negative when buffers are not equal, extract sign bit.  */
+  return ((unsigned int)(ab | ba) >> (sizeof(unsigned int) * 8 - 1)) & 1;
+}
+
+
+void *
+_gcry_malloc_secure (grub_size_t n)
+{
+  return grub_malloc(n);
+}
+
+void *
+_gcry_malloc (grub_size_t n)
+{
+  return grub_malloc(n);
+}
+
+void *
+_gcry_xmalloc(grub_size_t n)
+{
+  void *ret = grub_malloc(n);
+  if (ret == NULL)
+    grub_fatal("_gcry_xmalloc failed");
+  return ret;
+}
+
+void *
+_gcry_xmalloc_secure(grub_size_t n)
+{
+  void *ret = grub_malloc(n);
+  if (ret == NULL)
+    grub_fatal("_gcry_xmalloc_secure failed");
+  return ret;
+}
+
+void _gcry_free (void *p)
+{
+  grub_free (p);
+}
+
+void *
+_gcry_xrealloc (void *a, grub_size_t n)
+{
+  void *ret = grub_realloc(a, n);
+  if (ret == NULL)
+    grub_fatal("_gcry_xrealloc failed");
+  return ret;
+}
+
+void *
+_gcry_xcalloc (grub_size_t n, grub_size_t m)
+{
+  void *ret = grub_calloc(n, m);
+  if (ret == NULL)
+    grub_fatal("_gcry_xcalloc failed");
+  return ret;
+}
+
+void *
+_gcry_xcalloc_secure (grub_size_t n, grub_size_t m)
+{
+  void *ret = grub_calloc(n, m);
+  if (ret == NULL)
+    grub_fatal("_gcry_xcalloc_secure failed");
+  return ret;
+}
+
+
+int
+_gcry_is_secure (const void *a)
+{
+  (void) a;
+
+  return 0;
+}
+
+void _gcry_divide_by_zero (void)
+{
+  grub_fatal("gcrypt division by zero");
 }
 
 #ifndef GRUB_UTIL
diff --git a/grub-core/lib/libgcrypt/src/gcrypt-int.h b/grub-core/lib/libgcrypt/src/gcrypt-int.h
index 3071b421e..1ca4f21fe 100644
--- a/grub-core/lib/libgcrypt/src/gcrypt-int.h
+++ b/grub-core/lib/libgcrypt/src/gcrypt-int.h
@@ -265,57 +265,6 @@ void _gcry_set_log_handler (gcry_handler_log_t f, void *opaque);
 void _gcry_set_gettext_handler (const char *(*f)(const char*));
 void _gcry_set_progress_handler (gcry_handler_progress_t cb, void *cb_data);
 
-\f
-/* Return a pointer to a string containing a description of the error
-   code in the error value ERR.  */
-static inline const char *
-_gcry_strerror (gcry_error_t err)
-{
-  return gpg_strerror (err);
-}
-
-/* Return a pointer to a string containing a description of the error
-   source in the error value ERR.  */
-static inline const char *
-_gcry_strsource (gcry_error_t err)
-{
-  return gpg_strsource (err);
-}
-
-/* Retrieve the error code for the system error ERR.  This returns
-   GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
-   this).  */
-static inline gcry_err_code_t
-_gcry_err_code_from_errno (int err)
-{
-  return gpg_err_code_from_errno (err);
-}
-
-/* Retrieve the system error for the error code CODE.  This returns 0
-   if CODE is not a system error code.  */
-static inline int
-_gcry_err_code_to_errno (gcry_err_code_t code)
-{
-  return gpg_err_code_to_errno (code);
-}
-
-/* Return an error value with the error source SOURCE and the system
-   error ERR.  */
-static inline gcry_error_t
-_gcry_err_make_from_errno (gpg_err_source_t source, int err)
-{
-  return gpg_err_make_from_errno (source, err);
-}
-
-
-/* Return an error value with the system error ERR.  */
-static inline gcry_error_t
-_gcry_error_from_errno (int err)
-{
-  return gpg_error (gpg_err_code_from_errno (err));
-}
-
-
 \f
 gpg_err_code_t _gcry_sexp_new (gcry_sexp_t *retsexp,
                                const void *buffer, size_t length,
diff --git a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h
index 42835493d..225eb7919 100644
--- a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h
+++ b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h
@@ -35,9 +35,7 @@
 #undef __GNU_LIBRARY__
 #define __GNU_LIBRARY__ 1
 
-#define U64_C(c) (c ## ULL)
-
-#define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
+#define UINT64_C(c) (c ## ULL)
 
 #define CIPHER_INFO_NO_WEAK_KEY    1
 
@@ -74,4 +72,12 @@ _gcry_fips_mode (void)
 
 #define gcry_mpi_mod _gcry_mpi_mod
 
+#define strtol grub_strtol
+#define strtoul grub_strtoul
+#define atoi(nptr) (strtol((nptr), NULL, 10))
+
+#define stpcpy grub_stpcpy
+
+#define spec_from_algo grub_crypto_lookup_md_by_algo
+
 #endif
diff --git a/grub-core/lib/libgcrypt_wrap/md.c b/grub-core/lib/libgcrypt_wrap/md.c
new file mode 100644
index 000000000..c24c74672
--- /dev/null
+++ b/grub-core/lib/libgcrypt_wrap/md.c
@@ -0,0 +1,687 @@
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+
+typedef struct gcry_md_list
+{
+  const gcry_md_spec_t *spec;
+  struct gcry_md_list *next;
+  size_t actual_struct_size;     /* Allocated size of this structure. */
+  PROPERLY_ALIGNED_TYPE context[1];
+} GcryDigestEntry;
+
+/* This structure is put right after the gcry_md_hd_t buffer, so that
+ * only one memory block is needed. */
+struct gcry_md_context
+{
+  int  magic;
+  struct {
+    unsigned int secure:1;
+    unsigned int finalized:1;
+    unsigned int bugemu1:1;
+    unsigned int hmac:1;
+  } flags;
+  size_t actual_handle_size;     /* Allocated size of this handle. */
+  GcryDigestEntry *list;
+};
+
+#define CTX_MAGIC_NORMAL 0x11071961
+#define CTX_MAGIC_SECURE 0x16917011
+
+static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo);
+static void md_close (gcry_md_hd_t a);
+static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen);
+static byte *md_read( gcry_md_hd_t a, int algo );
+///static int md_get_algo( gcry_md_hd_t a );
+static int md_digest_length( int algo );
+
+int
+_gcry_md_map_name (const char *string)
+{
+  const gcry_md_spec_t *spec;
+
+  if (!string)
+    return 0;
+
+  /* If the string starts with a digit (optionally prefixed with
+     either "OID." or "oid."), we first look into our table of ASN.1
+     object identifiers to figure out the algorithm */
+  spec = grub_crypto_lookup_md_by_oid (string);
+  if (spec)
+    return spec->algo;
+
+  /* Not found, search a matching digest name.  */
+  spec = grub_crypto_lookup_md_by_name (string);
+  if (spec)
+    return spec->algo;
+
+  return 0;
+}
+
+static gcry_err_code_t
+check_digest_algo (int algorithm)
+{
+  const gcry_md_spec_t *spec;
+
+  spec = spec_from_algo (algorithm);
+  if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()))
+    return 0;
+
+  return GPG_ERR_DIGEST_ALGO;
+
+}
+
+/****************
+ * Open a message digest handle for use with algorithm ALGO.
+ * More algorithms may be added by md_enable(). The initial algorithm
+ * may be 0.
+ */
+static gcry_err_code_t
+md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
+{
+  gcry_err_code_t err = 0;
+  int secure = !!(flags & GCRY_MD_FLAG_SECURE);
+  int hmac =   !!(flags & GCRY_MD_FLAG_HMAC);
+  int bufsize = secure ? 512 : 1024;
+  gcry_md_hd_t hd;
+  size_t n;
+
+  /* Allocate a memory area to hold the caller visible buffer with it's
+   * control information and the data required by this module. Set the
+   * context pointer at the beginning to this area.
+   * We have to use this strange scheme because we want to hide the
+   * internal data but have a variable sized buffer.
+   *
+   *	+---+------+---........------+-------------+
+   *	!ctx! bctl !  buffer	     ! private	   !
+   *	+---+------+---........------+-------------+
+   *	  !			      ^
+   *	  !---------------------------!
+   *
+   * We have to make sure that private is well aligned.
+   */
+  n = offsetof (struct gcry_md_handle, buf) + bufsize;
+  n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1)
+       / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE);
+
+  /* Allocate and set the Context pointer to the private data */
+  if (secure)
+    hd = xtrymalloc_secure (n + sizeof (struct gcry_md_context));
+  else
+    hd = xtrymalloc (n + sizeof (struct gcry_md_context));
+
+  if (! hd)
+    err = gpg_err_code_from_errno (errno);
+
+  if (! err)
+    {
+      struct gcry_md_context *ctx;
+
+      ctx = (void *) (hd->buf - offsetof (struct gcry_md_handle, buf) + n);
+      /* Setup the globally visible data (bctl in the diagram).*/
+      hd->ctx = ctx;
+      hd->bufsize = n - offsetof (struct gcry_md_handle, buf);
+      hd->bufpos = 0;
+
+      /* Initialize the private data. */
+      wipememory2 (ctx, 0, sizeof *ctx);
+      ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
+      ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
+      ctx->flags.secure = secure;
+      ctx->flags.hmac = hmac;
+      ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1);
+    }
+
+  if (! err)
+    {
+      if (algo)
+	{
+	  err = md_enable (hd, algo);
+	  if (err)
+	    md_close (hd);
+	}
+    }
+
+  if (! err)
+    *h = hd;
+
+  return err;
+}
+
+/* Create a message digest object for algorithm ALGO.  FLAGS may be
+   given as an bitwise OR of the gcry_md_flags values.  ALGO may be
+   given as 0 if the algorithms to be used are later set using
+   gcry_md_enable. H is guaranteed to be a valid handle or NULL on
+   error.  */
+gcry_err_code_t
+_gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
+{
+  gcry_err_code_t rc;
+  gcry_md_hd_t hd;
+
+  if ((flags & ~(GCRY_MD_FLAG_SECURE
+                 | GCRY_MD_FLAG_HMAC
+                 | GCRY_MD_FLAG_BUGEMU1)))
+    rc = GPG_ERR_INV_ARG;
+  else
+    rc = md_open (&hd, algo, flags);
+
+  *h = rc? NULL : hd;
+  return rc;
+}
+
+static gcry_err_code_t
+md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
+{
+  gcry_err_code_t err = 0;
+  struct gcry_md_context *a = ahd->ctx;
+  struct gcry_md_context *b;
+  GcryDigestEntry *ar, *br;
+  gcry_md_hd_t bhd;
+  size_t n;
+
+  if (ahd->bufpos)
+    md_write (ahd, NULL, 0);
+
+  n = (char *) ahd->ctx - (char *) ahd;
+  if (a->flags.secure)
+    bhd = xtrymalloc_secure (n + sizeof (struct gcry_md_context));
+  else
+    bhd = xtrymalloc (n + sizeof (struct gcry_md_context));
+
+  if (!bhd)
+    {
+      err = gpg_err_code_from_syserror ();
+      goto leave;
+    }
+
+  bhd->ctx = b = (void *) ((char *) bhd + n);
+  /* No need to copy the buffer due to the write above. */
+  gcry_assert (ahd->bufsize == (n - offsetof (struct gcry_md_handle, buf)));
+  bhd->bufsize = ahd->bufsize;
+  bhd->bufpos = 0;
+  gcry_assert (! ahd->bufpos);
+  memcpy (b, a, sizeof *a);
+  b->list = NULL;
+
+  /* Copy the complete list of algorithms.  The copied list is
+     reversed, but that doesn't matter. */
+  for (ar = a->list; ar; ar = ar->next)
+    {
+      if (a->flags.secure)
+        br = xtrymalloc_secure (ar->actual_struct_size);
+      else
+        br = xtrymalloc (ar->actual_struct_size);
+      if (!br)
+        {
+          err = gpg_err_code_from_syserror ();
+          md_close (bhd);
+          goto leave;
+        }
+
+      memcpy (br, ar, ar->actual_struct_size);
+      br->next = b->list;
+      b->list = br;
+    }
+
+  *b_hd = bhd;
+
+ leave:
+  return err;
+}
+
+gcry_err_code_t
+_gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd)
+{
+  gcry_err_code_t rc;
+
+  rc = md_copy (hd, handle);
+  if (rc)
+    *handle = NULL;
+  return rc;
+}
+
+
+/*
+ * Reset all contexts and discard any buffered stuff.  This may be used
+ * instead of a md_close(); md_open().
+ */
+void
+_gcry_md_reset (gcry_md_hd_t a)
+{
+  GcryDigestEntry *r;
+
+  /* Note: We allow this even in fips non operational mode.  */
+
+  a->bufpos = a->ctx->flags.finalized = 0;
+
+  if (a->ctx->flags.hmac)
+    for (r = a->ctx->list; r; r = r->next)
+      {
+        memcpy (r->context, (char *)r->context + r->spec->contextsize,
+                r->spec->contextsize);
+      }
+  else
+    for (r = a->ctx->list; r; r = r->next)
+      {
+        memset (r->context, 0, r->spec->contextsize);
+        (*r->spec->init) (r->context,
+                          a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
+      }
+}
+
+static void
+md_close (gcry_md_hd_t a)
+{
+  GcryDigestEntry *r, *r2;
+
+  if (! a)
+    return;
+  for (r = a->ctx->list; r; r = r2)
+    {
+      r2 = r->next;
+      wipememory (r, r->actual_struct_size);
+      xfree (r);
+    }
+
+  wipememory (a, a->ctx->actual_handle_size);
+  xfree(a);
+}
+
+
+void
+_gcry_md_close (gcry_md_hd_t hd)
+{
+  /* Note: We allow this even in fips non operational mode.  */
+  md_close (hd);
+}
+
+static void
+md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen)
+{
+  GcryDigestEntry *r;
+
+  for (r = a->ctx->list; r; r = r->next)
+    {
+      if (a->bufpos)
+	(*r->spec->write) (r->context, a->buf, a->bufpos);
+      (*r->spec->write) (r->context, inbuf, inlen);
+    }
+  a->bufpos = 0;
+}
+
+
+/* Note that this function may be used after finalize and read to keep
+   on writing to the transform function so to mitigate timing
+   attacks.  */
+void
+_gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen)
+{
+  md_write (hd, inbuf, inlen);
+}
+
+static void
+md_final (gcry_md_hd_t a)
+{
+  GcryDigestEntry *r;
+
+  if (a->ctx->flags.finalized)
+    return;
+
+  if (a->bufpos)
+    md_write (a, NULL, 0);
+
+  for (r = a->ctx->list; r; r = r->next)
+    (*r->spec->final) (r->context);
+
+  a->ctx->flags.finalized = 1;
+
+  if (!a->ctx->flags.hmac)
+    return;
+
+  for (r = a->ctx->list; r; r = r->next)
+    {
+      byte *p;
+      size_t dlen = r->spec->mdlen;
+      byte *hash;
+      gcry_err_code_t err;
+
+      if (r->spec->read == NULL)
+        continue;
+
+      p = r->spec->read (r->context);
+
+      if (a->ctx->flags.secure)
+        hash = xtrymalloc_secure (dlen);
+      else
+        hash = xtrymalloc (dlen);
+      if (!hash)
+        {
+          err = gpg_err_code_from_errno (errno);
+          _gcry_fatal_error (err, NULL);
+        }
+
+      memcpy (hash, p, dlen);
+      memcpy (r->context, (char *)r->context + r->spec->contextsize * 2,
+              r->spec->contextsize);
+      (*r->spec->write) (r->context, hash, dlen);
+      (*r->spec->final) (r->context);
+      xfree (hash);
+    }
+}
+
+static gcry_err_code_t
+md_enable (gcry_md_hd_t hd, int algorithm)
+{
+  struct gcry_md_context *h = hd->ctx;
+  const gcry_md_spec_t *spec;
+  GcryDigestEntry *entry;
+  gcry_err_code_t err = 0;
+
+  for (entry = h->list; entry; entry = entry->next)
+    if (entry->spec->algo == algorithm)
+      return 0; /* Already enabled */
+
+  spec = spec_from_algo (algorithm);
+  if (!spec)
+    {
+      log_debug ("md_enable: algorithm %d not available\n", algorithm);
+      err = GPG_ERR_DIGEST_ALGO;
+    }
+
+  if (!err && spec->flags.disabled)
+    err = GPG_ERR_DIGEST_ALGO;
+
+  /* Any non-FIPS algorithm should go this way */
+  if (!err && !spec->flags.fips && fips_mode ())
+    err = GPG_ERR_DIGEST_ALGO;
+
+  if (!err && h->flags.hmac && spec->read == NULL)
+    {
+      /* Expandable output function cannot act as part of HMAC. */
+      err = GPG_ERR_DIGEST_ALGO;
+    }
+
+  if (!err)
+    {
+      size_t size = (sizeof (*entry)
+                     + spec->contextsize * (h->flags.hmac? 3 : 1)
+                     - sizeof (entry->context));
+
+      /* And allocate a new list entry. */
+      if (h->flags.secure)
+	entry = xtrymalloc_secure (size);
+      else
+	entry = xtrymalloc (size);
+
+      if (! entry)
+	err = gpg_err_code_from_errno (errno);
+      else
+	{
+	  entry->spec = spec;
+	  entry->next = h->list;
+          entry->actual_struct_size = size;
+	  h->list = entry;
+
+	  /* And init this instance. */
+	  entry->spec->init (entry->context,
+                             h->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
+	}
+    }
+
+  return err;
+}
+
+
+gcry_err_code_t
+_gcry_md_enable (gcry_md_hd_t hd, int algorithm)
+{
+  return md_enable (hd, algorithm);
+}
+
+gcry_err_code_t
+_gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
+{
+  gcry_err_code_t rc = 0;
+
+  (void)buflen; /* Currently not used.  */
+  (void)buffer;
+
+  switch (cmd)
+    {
+    case GCRYCTL_FINALIZE:
+      md_final (hd);
+      break;
+    case GCRYCTL_START_DUMP:
+      break;
+    case GCRYCTL_STOP_DUMP:
+      break;
+    default:
+      rc = GPG_ERR_INV_OP;
+    }
+  return rc;
+}
+
+/****************
+ * If ALGO is null get the digest for the used algo (which should be
+ * only one)
+ */
+static byte *
+md_read( gcry_md_hd_t a, int algo )
+{
+  GcryDigestEntry *r = a->ctx->list;
+
+  if (! algo)
+    {
+      /* Return the first algorithm */
+      if (r)
+        {
+          if (r->next)
+            log_debug ("more than one algorithm in md_read(0)\n");
+          if (r->spec->read)
+            return r->spec->read (r->context);
+        }
+    }
+  else
+    {
+      for (r = a->ctx->list; r; r = r->next)
+	if (r->spec->algo == algo)
+	  {
+	    if (r->spec->read)
+              return r->spec->read (r->context);
+            break;
+	  }
+    }
+
+  if (r && !r->spec->read)
+    _gcry_fatal_error (GPG_ERR_DIGEST_ALGO,
+                       "requested algo has no fixed digest length");
+  else
+    _gcry_fatal_error (GPG_ERR_DIGEST_ALGO, "requested algo not in md context");
+  return NULL;
+}
+
+
+/*
+ * Read out the complete digest, this function implictly finalizes
+ * the hash.
+ */
+byte *
+_gcry_md_read (gcry_md_hd_t hd, int algo)
+{
+  /* This function is expected to always return a digest, thus we
+     can't return an error which we actually should do in
+     non-operational state.  */
+  _gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
+  return md_read (hd, algo);
+}
+
+/*
+ * Shortcut function to hash a buffer with a given algo. The only
+ * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The
+ * supplied digest buffer must be large enough to store the resulting
+ * hash.  No error is returned, the function will abort on an invalid
+ * algo.  DISABLED_ALGOS are ignored here.  */
+void
+_gcry_md_hash_buffer (int algo, void *digest,
+                      const void *buffer, size_t length)
+{
+  const gcry_md_spec_t *spec;
+
+  spec = spec_from_algo (algo);
+  if (!spec)
+    {
+      log_debug ("md_hash_buffer: algorithm %d not available\n", algo);
+      return;
+    }
+
+  /*  if (spec->hash_buffers != NULL)
+    {
+      gcry_buffer_t iov;
+
+      iov.size = 0;
+      iov.data = (void *)buffer;
+      iov.off = 0;
+      iov.len = length;
+
+      if (spec->flags.disabled || (!spec->flags.fips && fips_mode ()))
+        log_bug ("gcry_md_hash_buffer failed for algo %d: %s",
+                algo, gpg_strerror (gcry_error (GPG_ERR_DIGEST_ALGO)));
+
+      spec->hash_buffers (digest, spec->mdlen, &iov, 1);
+    }
+    else*/
+    {
+      /* For the others we do not have a fast function, so we use the
+         normal functions. */
+      gcry_md_hd_t h;
+      gpg_err_code_t err;
+
+      err = md_open (&h, algo, 0);
+      if (err)
+        log_bug ("gcry_md_open failed for algo %d: %s",
+                algo, gpg_strerror (gcry_error(err)));
+      md_write (h, (byte *) buffer, length);
+      md_final (h);
+      memcpy (digest, md_read (h, algo), md_digest_length (algo));
+      md_close (h);
+    }
+}
+
+/****************
+ * Return the length of the digest
+ */
+static int
+md_digest_length (int algorithm)
+{
+  const gcry_md_spec_t *spec;
+
+  spec = spec_from_algo (algorithm);
+  return spec? spec->mdlen : 0;
+}
+
+
+/****************
+ * Return the length of the digest in bytes.
+ * This function will return 0 in case of errors.
+ */
+unsigned int
+_gcry_md_get_algo_dlen (int algorithm)
+{
+  return md_digest_length (algorithm);
+}
+
+/* Hmmm: add a mode to enumerate the OIDs
+ *	to make g10/sig-check.c more portable */
+static const byte *
+md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen)
+{
+  const gcry_md_spec_t *spec;
+  const byte *asnoid = NULL;
+
+  spec = spec_from_algo (algorithm);
+  if (spec)
+    {
+      if (asnlen)
+	*asnlen = spec->asnlen;
+      if (mdlen)
+	*mdlen = spec->mdlen;
+      asnoid = spec->asnoid;
+    }
+  else
+    log_bug ("no ASN.1 OID for md algo %d\n", algorithm);
+
+  return asnoid;
+}
+
+
+/****************
+ * Return information about the given cipher algorithm
+ * WHAT select the kind of information returned:
+ *  GCRYCTL_TEST_ALGO:
+ *	Returns 0 when the specified algorithm is available for use.
+ *	buffer and nbytes must be zero.
+ *  GCRYCTL_GET_ASNOID:
+ *	Return the ASNOID of the algorithm in buffer. if buffer is NULL, only
+ *	the required length is returned.
+ *  GCRYCTL_SELFTEST
+ *      Helper for the regression tests - shall not be used by applications.
+ *
+ * Note:  Because this function is in most cases used to return an
+ * integer value, we can make it easier for the caller to just look at
+ * the return value.  The caller will in all cases consult the value
+ * and thereby detecting whether a error occurred or not (i.e. while checking
+ * the block size)
+ */
+gcry_err_code_t
+_gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes)
+{
+  gcry_err_code_t rc;
+
+  switch (what)
+    {
+    case GCRYCTL_TEST_ALGO:
+      if (buffer || nbytes)
+	rc = GPG_ERR_INV_ARG;
+      else
+	rc = check_digest_algo (algo);
+      break;
+
+    case GCRYCTL_GET_ASNOID:
+      /* We need to check that the algo is available because
+         md_asn_oid would otherwise raise an assertion. */
+      rc = check_digest_algo (algo);
+      if (!rc)
+        {
+          const char unsigned *asn;
+          size_t asnlen;
+
+          asn = md_asn_oid (algo, &asnlen, NULL);
+          if (buffer && (*nbytes >= asnlen))
+            {
+              memcpy (buffer, asn, asnlen);
+              *nbytes = asnlen;
+            }
+          else if (!buffer && nbytes)
+            *nbytes = asnlen;
+          else
+            {
+              if (buffer)
+                rc = GPG_ERR_TOO_SHORT;
+              else
+                rc = GPG_ERR_INV_ARG;
+            }
+        }
+      break;
+
+    default:
+      rc = GPG_ERR_INV_OP;
+      break;
+  }
+
+  return rc;
+}
diff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c
index 74c6eafe5..ab0cf4ad3 100644
--- a/grub-core/lib/libgcrypt_wrap/mem.c
+++ b/grub-core/lib/libgcrypt_wrap/mem.c
@@ -46,6 +46,15 @@ gcry_xcalloc (size_t n, size_t m)
   return ret;
 }
 
+void *
+_gcry_calloc (size_t n, size_t m)
+{
+  size_t sz;
+  if (grub_mul (n, m, &sz))
+    return NULL;
+  return grub_zalloc (sz);
+}
+
 void *
 gcry_xmalloc_secure (size_t n)
 {
@@ -69,6 +78,15 @@ gcry_xcalloc_secure (size_t n, size_t m)
   return ret;
 }
 
+void *
+_gcry_calloc_secure (size_t n, size_t m)
+{
+  size_t sz;
+  if (grub_mul (n, m, &sz))
+    return NULL;
+  return grub_zalloc (sz);
+}
+
 void *
 gcry_xmalloc (size_t n)
 {
@@ -89,6 +107,12 @@ gcry_xrealloc (void *a, size_t n)
   return ret;
 }
 
+void *
+_gcry_realloc (void *a, size_t n)
+{
+  return grub_realloc (a, n);
+}
+
 void
 _gcry_check_heap (const void *a __attribute__ ((unused)))
 {
@@ -113,6 +137,24 @@ void _gcry_log_printf (const char *fmt, ...)
     }
 }
 
+void _gcry_log_debug (const char *fmt, ...)
+{
+  va_list args;
+  const char *debug = grub_env_get ("debug");
+
+  if (! debug)
+    return;
+
+  if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt"))
+    {
+      grub_printf ("gcrypt: ");
+      va_start (args, fmt);
+      grub_vprintf (fmt, args);
+      va_end (args);
+      grub_refresh ();
+    }
+}
+
 void _gcry_log_bug (const char *fmt, ...)
 {
   va_list args;
@@ -126,9 +168,9 @@ void _gcry_log_bug (const char *fmt, ...)
 }
 
 gcry_err_code_t
-gpg_error_from_syserror (void)
+gpg_err_code_from_errno (int err)
 {
-  switch (grub_errno)
+  switch (err)
     {
     case GRUB_ERR_NONE:
       return GPG_ERR_NO_ERROR;
@@ -138,3 +180,40 @@ gpg_error_from_syserror (void)
       return GPG_ERR_GENERAL;
     }
 }
+
+gcry_err_code_t
+gpg_error_from_syserror (void)
+{
+  return gpg_err_code_from_errno(grub_errno);
+}
+
+gcry_err_code_t
+gpg_err_code_from_syserror (void)
+{
+  return gpg_error_from_syserror ();
+}
+
+void _gcry_fatal_error(int rc, const char *text )
+{
+  grub_fatal("gcry fatal %d: %s", rc, text);
+}
+
+
+void _gcry_randomize (void *buffer __attribute__((unused)), size_t length __attribute__((unused)),
+                      enum gcry_random_level level __attribute__((unused)))
+{
+  grub_fatal("Attempt to get secure random numbers");
+}
+
+
+void *_gcry_random_bytes_secure (size_t nbytes __attribute__((unused)), enum gcry_random_level level __attribute__((unused)))
+{
+  grub_fatal("Attempt to get secure random numbers");
+}
+
+const char *gpg_strerror (gpg_error_t err)
+{
+  static char buf[256];
+  grub_snprintf(buf, sizeof(buf) - 5, "gpg error %d\n", err);
+  return buf;
+}
diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c
index 832d8af9a..f2dd42dc2 100644
--- a/grub-core/lib/xzembed/xz_dec_stream.c
+++ b/grub-core/lib/xzembed/xz_dec_stream.c
@@ -425,9 +425,9 @@ static enum xz_ret hash_validate(struct xz_dec *s, struct xz_buf *b,
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
 	if (s->hash)
-		s->hash->init(s->hash_context);
+		s->hash->init(s->hash_context, 0);
 	if (s->crc32)
-		s->crc32->init(s->crc32_context);
+		s->crc32->init(s->crc32_context, 0);
 #endif
 	s->have_hash_value = 0;
 	s->pos = 0;
@@ -493,7 +493,7 @@ static enum xz_ret dec_stream_header(struct xz_dec *s)
 		s->crc32_context = kmalloc(s->crc32->contextsize, GFP_KERNEL);
 		if (s->crc32_context == NULL)
 			return XZ_MEMLIMIT_ERROR;
-		s->crc32->init(s->crc32_context);
+		s->crc32->init(s->crc32_context, 0);
 	}
 #endif
 
@@ -531,9 +531,9 @@ static enum xz_ret dec_stream_header(struct xz_dec *s)
 				return XZ_MEMLIMIT_ERROR;
 			}
 
-			s->hash->init(s->hash_context);
-			s->hash->init(s->index.hash.hash_context);
- 			s->hash->init(s->block.hash.hash_context);
+			s->hash->init(s->hash_context, 0);
+			s->hash->init(s->index.hash.hash_context, 0);
+ 			s->hash->init(s->block.hash.hash_context, 0);
 		}
 #endif
 	}
@@ -1014,9 +1014,9 @@ void xz_dec_reset(struct xz_dec *s)
 #ifndef GRUB_EMBED_DECOMPRESSOR
 	if (s->hash)
 	{
-		s->hash->init(s->hash_context);
-		s->hash->init(s->index.hash.hash_context);
-		s->hash->init(s->block.hash.hash_context);
+		s->hash->init(s->hash_context, 0);
+		s->hash->init(s->index.hash.hash_context, 0);
+		s->hash->init(s->block.hash.hash_context, 0);
 	}
 #endif
 	s->have_hash_value = 0;
diff --git a/grub-core/tests/dsa_sexp_test.c b/grub-core/tests/dsa_sexp_test.c
new file mode 100644
index 000000000..ea233bf0c
--- /dev/null
+++ b/grub-core/tests/dsa_sexp_test.c
@@ -0,0 +1,107 @@
+#include <grub/test.h>
+#include <grub/crypto.h>
+#include <grub/gcrypt/gcrypt.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static char pubkey_dump[] = {
+  0x28, 0x31, 0x30, 0x3a, 0x70, 0x75, 0x62, 0x6c, 
+  0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x28, 0x33, 
+  0x3a, 0x64, 0x73, 0x61, 0x28, 0x31, 0x3a, 0x70, 
+  0x31, 0x32, 0x39, 0x3a, 0x00, 0xc0, 0x50, 0x14, 
+  0x4c, 0x97, 0x10, 0x69, 0x07, 0xa7, 0xe9, 0x2b, 
+  0xe5, 0xc6, 0x88, 0xe1, 0x6d, 0xd8, 0x38, 0x28, 
+  0x09, 0x49, 0x5b, 0xe8, 0xa3, 0x04, 0xb8, 0xc4, 
+  0x6e, 0x98, 0xc1, 0xc2, 0xb0, 0x2a, 0xe0, 0xe2, 
+  0x1a, 0x30, 0xd2, 0xdb, 0x45, 0x1a, 0x88, 0x80, 
+  0x28, 0x24, 0xb0, 0xbf, 0xc2, 0xbd, 0xe9, 0xf6, 
+  0x9d, 0xa2, 0x01, 0x94, 0xe6, 0x7f, 0xa0, 0xb6, 
+  0xe4, 0x39, 0xfc, 0x54, 0xba, 0x99, 0xb6, 0xbe, 
+  0x39, 0xee, 0xa5, 0xd9, 0xa0, 0x35, 0x3c, 0x2d, 
+  0x3e, 0x96, 0xc3, 0x96, 0xa5, 0x0d, 0x2b, 0xbf, 
+  0x3b, 0xa3, 0xe2, 0xe8, 0x89, 0xed, 0x60, 0xe0, 
+  0x43, 0x61, 0xb6, 0x73, 0xf6, 0xa7, 0xb4, 0x56, 
+  0x76, 0x04, 0xf7, 0x8b, 0xf1, 0x84, 0xaa, 0x3e, 
+  0xe0, 0x08, 0xad, 0xdd, 0xc2, 0x36, 0xfd, 0x3d, 
+  0xd0, 0xad, 0xf4, 0x3a, 0x7e, 0x80, 0x8c, 0x52, 
+  0x2b, 0x04, 0xa8, 0x03, 0x27, 0x29, 0x28, 0x31, 
+  0x3a, 0x71, 0x32, 0x31, 0x3a, 0x00, 0xd5, 0x34, 
+  0xd2, 0xc5, 0x1c, 0x26, 0xdf, 0xb0, 0xba, 0x78, 
+  0x75, 0xe5, 0xe9, 0x36, 0x6b, 0x04, 0x03, 0xe2, 
+  0x57, 0x3f, 0x29, 0x28, 0x31, 0x3a, 0x67, 0x31, 
+  0x32, 0x38, 0x3a, 0x3b, 0xa0, 0xac, 0xa3, 0xa1, 
+  0xd1, 0x04, 0x23, 0x5f, 0x9f, 0xbc, 0x6d, 0x9e, 
+  0x88, 0x2a, 0x28, 0xc1, 0x48, 0xaf, 0xa5, 0x17, 
+  0x59, 0x3a, 0x17, 0x33, 0x56, 0xaa, 0x8d, 0x27, 
+  0x64, 0xfe, 0x8e, 0x8a, 0x2e, 0xba, 0xf2, 0x66, 
+  0xcc, 0x66, 0xbd, 0xa4, 0xfe, 0xa9, 0x07, 0x0d, 
+  0xae, 0x8c, 0x9f, 0x70, 0xf7, 0x87, 0xaa, 0x01, 
+  0x47, 0x6b, 0xf9, 0x0f, 0x09, 0x18, 0x42, 0x76, 
+  0xc4, 0xa3, 0xb9, 0x55, 0x11, 0x8d, 0xa3, 0xa5, 
+  0x69, 0x30, 0x91, 0xb7, 0x03, 0xef, 0x7f, 0x12, 
+  0xe6, 0xb9, 0x78, 0x73, 0xe0, 0xc0, 0x4f, 0xc6, 
+  0xd9, 0x43, 0x99, 0x95, 0x0b, 0x4d, 0x58, 0xd3, 
+  0x6b, 0x76, 0xb0, 0x6a, 0xcf, 0x68, 0x6d, 0xf0, 
+  0xd9, 0xc1, 0x88, 0x43, 0x9d, 0xf9, 0x04, 0xcb, 
+  0xc9, 0x82, 0x6c, 0xee, 0xd4, 0x9c, 0xbd, 0x1c, 
+  0x4d, 0x54, 0x29, 0x83, 0xa9, 0x5e, 0xaa, 0x10, 
+  0xa7, 0xc1, 0x04, 0x29, 0x28, 0x31, 0x3a, 0x79, 
+  0x31, 0x32, 0x39, 0x3a, 0x00, 0x82, 0x33, 0xf1, 
+  0x91, 0xe3, 0xf2, 0x12, 0x93, 0x5a, 0xed, 0x0c, 
+  0x9d, 0xec, 0x67, 0xaa, 0xa7, 0x97, 0x7f, 0x9f, 
+  0x5e, 0xef, 0x6a, 0x3e, 0xa4, 0x7f, 0x9b, 0xed, 
+  0x65, 0xd7, 0xba, 0x40, 0x6d, 0xe1, 0xde, 0xc1, 
+  0x14, 0x4c, 0x9b, 0x28, 0x5c, 0x03, 0x8e, 0x1a, 
+  0xd4, 0x1b, 0x80, 0x1b, 0x07, 0xd6, 0x84, 0x04, 
+  0x49, 0x6c, 0x1b, 0x08, 0x84, 0x15, 0x54, 0x62, 
+  0xca, 0xd5, 0x75, 0xff, 0xc8, 0xb3, 0x81, 0x76, 
+  0x82, 0x91, 0x35, 0x80, 0x20, 0x73, 0x2a, 0x21, 
+  0xca, 0x22, 0x06, 0xa7, 0x73, 0x99, 0x75, 0x7e, 
+  0x5e, 0xa6, 0x09, 0x59, 0x66, 0x2c, 0xcd, 0xb1, 
+  0x8d, 0x3b, 0xc0, 0x68, 0xc5, 0x41, 0xa0, 0x9d, 
+  0x82, 0x15, 0xc4, 0xdd, 0x47, 0x1c, 0x5b, 0xa9, 
+  0x74, 0x18, 0xaf, 0x72, 0x63, 0x6b, 0x0a, 0x4e, 
+  0x95, 0x09, 0x7a, 0xb5, 0x4b, 0x98, 0x85, 0xb9, 
+  0x6d, 0x9d, 0x3b, 0x73, 0x8c, 0x29, 0x29, 0x29, 
+};
+
+static char sig_dump[] = {
+  0x28, 0x37, 0x3a, 0x73, 0x69, 0x67, 0x2d, 0x76, 
+  0x61, 0x6c, 0x28, 0x33, 0x3a, 0x64, 0x73, 0x61, 
+  0x28, 0x31, 0x3a, 0x72, 0x32, 0x30, 0x3a, 0xb6, 
+  0x60, 0x37, 0xef, 0x02, 0x7c, 0x7c, 0x6e, 0x4f, 
+  0x66, 0x8c, 0x7c, 0x26, 0x77, 0xd9, 0x33, 0x90, 
+  0xba, 0x7c, 0xfb, 0x29, 0x28, 0x31, 0x3a, 0x73, 
+  0x32, 0x30, 0x3a, 0x83, 0xc0, 0x84, 0x72, 0xc6, 
+  0x1c, 0x85, 0x6f, 0x8b, 0x9b, 0xb0, 0x38, 0x38, 
+  0xb2, 0xb6, 0xdf, 0x1c, 0x52, 0x96, 0x1b, 0x29, 
+  0x29, 0x29,
+};
+
+extern gcry_pk_spec_t _gcry_pubkey_spec_dsa;
+
+static void
+dsa_sexp_test (void)
+{
+  gcry_sexp_t sign_parms, sign_parms_invalid, pubkey, sig;
+  int rc;
+  grub_size_t errof;
+
+  rc = _gcry_sexp_build (&sign_parms_invalid, &errof,
+			"(data (value \"hi\"))\n");
+  grub_test_assert (rc == 0, "sexp build failed");
+
+  rc = _gcry_sexp_build (&sign_parms, &errof,
+			"(data (value \"hello\"))\n");
+  grub_test_assert (rc == 0, "sexp build failed");
+  rc = _gcry_sexp_new (&pubkey, pubkey_dump, sizeof(pubkey_dump), 0);
+  grub_test_assert (rc == 0, "sexp new failed");
+  rc = _gcry_sexp_new (&sig, sig_dump, sizeof(sig_dump), 0);
+  grub_test_assert (rc == 0, "sexp new failed");
+  rc = _gcry_pubkey_spec_dsa.verify (sig, sign_parms, pubkey);
+  grub_test_assert (rc == 0, "signature verification failed: %d", rc);
+  rc = _gcry_pubkey_spec_dsa.verify (sig, sign_parms_invalid, pubkey);
+  grub_test_assert (rc != 0, "signature verification succeded wrongly");
+}
+
+GRUB_FUNCTIONAL_TEST (dsa_sexp_test, dsa_sexp_test);
diff --git a/grub-core/tests/rsa_sexp_test.c b/grub-core/tests/rsa_sexp_test.c
new file mode 100644
index 000000000..e00befe4e
--- /dev/null
+++ b/grub-core/tests/rsa_sexp_test.c
@@ -0,0 +1,81 @@
+#include <grub/test.h>
+#include <grub/crypto.h>
+#include <grub/gcrypt/gcrypt.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static char pubkey_dump[] = {
+  0x28, 0x31, 0x30, 0x3a, 0x70, 0x75, 0x62, 0x6c, 
+  0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x28, 0x33, 
+  0x3a, 0x72, 0x73, 0x61, 0x28, 0x31, 0x3a, 0x6e, 
+  0x31, 0x32, 0x39, 0x3a, 0x00, 0xe1, 0x35, 0xc1, 
+  0x97, 0x90, 0xe8, 0x54, 0xa8, 0x3b, 0x97, 0x05, 
+  0xaf, 0x45, 0xaf, 0x67, 0xbf, 0xec, 0x07, 0xbe, 
+  0x9b, 0x55, 0x9c, 0x3f, 0x47, 0xae, 0x25, 0xb6, 
+  0xe3, 0x23, 0x99, 0x10, 0x5e, 0x17, 0x1a, 0xda, 
+  0x33, 0xe6, 0x73, 0x0d, 0x96, 0x9c, 0x5c, 0x25, 
+  0x13, 0x5d, 0x49, 0xb9, 0x86, 0xc0, 0xb1, 0x80, 
+  0x29, 0x20, 0xb2, 0x91, 0x72, 0x43, 0xcc, 0x2a, 
+  0x67, 0xd3, 0x11, 0xe8, 0x7b, 0x21, 0x75, 0xf6, 
+  0x1b, 0xc0, 0xb2, 0x01, 0xc8, 0x35, 0xaa, 0xfb, 
+  0xa7, 0x29, 0xb4, 0xb9, 0x94, 0x4e, 0x53, 0x49, 
+  0x82, 0x74, 0xe9, 0x23, 0x69, 0xa4, 0xf6, 0xdf, 
+  0x40, 0x2a, 0x73, 0x01, 0xfa, 0xe7, 0xf8, 0x32, 
+  0x6b, 0x57, 0xfe, 0xb9, 0x7d, 0x02, 0xc2, 0xfb, 
+  0x7f, 0x99, 0x1f, 0x6e, 0x8d, 0x53, 0x01, 0x56, 
+  0xaf, 0x46, 0x62, 0xb3, 0xe0, 0xa8, 0xa6, 0x0a, 
+  0x55, 0x2c, 0x4b, 0x85, 0x5b, 0x29, 0x28, 0x31, 
+  0x3a, 0x65, 0x33, 0x3a, 0x01, 0x00, 0x01, 0x29, 
+  0x29, 0x29, 
+};
+
+static char sig_dump[] = {
+  0x28, 0x37, 0x3a, 0x73, 0x69, 0x67, 0x2d, 0x76, 
+  0x61, 0x6c, 0x28, 0x33, 0x3a, 0x72, 0x73, 0x61, 
+  0x28, 0x31, 0x3a, 0x73, 0x31, 0x32, 0x38, 0x3a, 
+  0x5b, 0x2d, 0xeb, 0xa5, 0x4b, 0x8b, 0xd9, 0x92, 
+  0x66, 0x57, 0x89, 0xd8, 0x31, 0xc0, 0x0e, 0x53, 
+  0xf8, 0x1c, 0x4f, 0xc8, 0x79, 0x67, 0xb9, 0x10, 
+  0xe5, 0x63, 0x5f, 0xef, 0xb1, 0x0b, 0x0e, 0x7f, 
+  0xed, 0x86, 0x06, 0xa8, 0x05, 0xbf, 0x6b, 0xd1, 
+  0x36, 0x41, 0x08, 0x3b, 0xd0, 0xbd, 0xef, 0xb7, 
+  0xc2, 0x69, 0xb8, 0xb4, 0x3e, 0x2c, 0xb5, 0x39, 
+  0x13, 0x03, 0xca, 0xad, 0x5f, 0xd2, 0x57, 0x23, 
+  0x19, 0xdd, 0x71, 0xdd, 0x93, 0xe1, 0x3e, 0x43, 
+  0xaf, 0xdd, 0x94, 0x07, 0xf3, 0x78, 0xb3, 0x2a, 
+  0x57, 0x24, 0x97, 0x04, 0x58, 0xc1, 0xaf, 0xd3, 
+  0xe7, 0xa7, 0x65, 0xd1, 0x23, 0xa3, 0x93, 0x18, 
+  0xc7, 0x52, 0x70, 0x53, 0x60, 0x8b, 0x5a, 0x5d, 
+  0x6e, 0xf9, 0x83, 0x52, 0x99, 0xbb, 0x0a, 0x53, 
+  0x0e, 0x2a, 0x7f, 0x81, 0x52, 0x02, 0x32, 0xa4, 
+  0xfc, 0xe0, 0x17, 0x0c, 0x0e, 0x96, 0xbd, 0x01, 
+  0x29, 0x29, 0x29, 
+};
+
+extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
+
+static void
+rsa_sexp_test (void)
+{
+  gcry_sexp_t sign_parms, sign_parms_invalid, pubkey, sig;
+  int rc;
+  grub_size_t errof;
+
+  rc = _gcry_sexp_build (&sign_parms_invalid, &errof,
+			"(data (flags) (value \"hi\"))\n");
+  grub_test_assert (rc == 0, "sexp build failed");
+
+  rc = _gcry_sexp_build (&sign_parms, &errof,
+			"(data (flags) (value \"hello\"))\n");
+  grub_test_assert (rc == 0, "sexp build failed");
+  rc = _gcry_sexp_new (&pubkey, pubkey_dump, sizeof(pubkey_dump), 0);
+  grub_test_assert (rc == 0, "sexp new failed");
+  rc = _gcry_sexp_new (&sig, sig_dump, sizeof(sig_dump), 0);
+  grub_test_assert (rc == 0, "sexp new failed");
+  rc = _gcry_pubkey_spec_rsa.verify (sig, sign_parms, pubkey);
+  grub_test_assert (rc == 0, "signature verification failed: %d", rc);
+  rc = _gcry_pubkey_spec_rsa.verify (sig, sign_parms_invalid, pubkey);
+  grub_test_assert (rc != 0, "signature verification succeded wrongly");
+}
+
+GRUB_FUNCTIONAL_TEST (rsa_sexp_test, rsa_sexp_test);
diff --git a/include/grub/crypto.h b/include/grub/crypto.h
index 31c87c302..01f86be71 100644
--- a/include/grub/crypto.h
+++ b/include/grub/crypto.h
@@ -65,7 +65,31 @@ typedef enum
     GPG_ERR_WRONG_PUBKEY_ALGO,
     GPG_ERR_OUT_OF_MEMORY,
     GPG_ERR_TOO_LARGE,
-    GPG_ERR_ENOMEM
+    GPG_ERR_ENOMEM,
+    GPG_ERR_CHECKSUM,
+    GPG_ERR_INV_LENGTH,
+    GPG_ERR_VALUE_NOT_FOUND,
+    GPG_ERR_ERANGE,
+    GPG_ERR_INV_DATA,
+    GPG_ERR_ENCODING_PROBLEM,
+    GPG_ERR_BUFFER_TOO_SHORT,
+    GPG_ERR_SYNTAX,
+    GPG_ERR_SEXP_INV_LEN_SPEC,
+    GPG_ERR_SEXP_UNMATCHED_DH,
+    GPG_ERR_SEXP_UNMATCHED_PAREN,
+    GPG_ERR_SEXP_ZERO_PREFIX,
+    GPG_ERR_SEXP_NESTED_DH,
+    GPG_ERR_SEXP_UNEXPECTED_PUNC,
+    GPG_ERR_SEXP_BAD_CHARACTER,
+    GPG_ERR_SEXP_NOT_CANONICAL,
+    GPG_ERR_SEXP_STRING_TOO_LONG,
+    GPG_ERR_SEXP_BAD_QUOTATION,
+    GPG_ERR_SEXP_ODD_HEX_NUMBERS,
+    GPG_ERR_SEXP_BAD_HEX_CHAR,
+    GPG_ERR_LIMIT_REACHED,
+    GPG_ERR_EOF,
+    GPG_ERR_BAD_DATA,
+    GPG_ERR_EINVAL,
   } gpg_err_code_t;
 typedef gpg_err_code_t gpg_error_t;
 typedef gpg_error_t gcry_error_t;
@@ -84,37 +108,60 @@ enum gcry_cipher_modes
   };
 #endif
 
+/* Extra algo IDs not coming from gcrypt.  */
+#define GCRY_MD_ADLER32 10301
+#define GCRY_MD_CRC64 10302
+
 /* Don't rely on this. Check!  */
 #define GRUB_CRYPTO_MAX_MDLEN 64
 #define GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE 16
 #define GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE 256
 
 /* Type for the cipher_setkey function.  */
+struct cipher_bulk_ops;
+
 typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c,
 						 const unsigned char *key,
-						 unsigned keylen);
+						 unsigned keylen,
+						 struct cipher_bulk_ops *bulk_ops);
 
 /* Type for the cipher_encrypt function.  */
-typedef void (*gcry_cipher_encrypt_t) (void *c,
-				       unsigned char *outbuf,
-				       const unsigned char *inbuf);
+typedef unsigned int (*gcry_cipher_encrypt_t) (void *c,
+					       unsigned char *outbuf,
+					       const unsigned char *inbuf);
 
 /* Type for the cipher_decrypt function.  */
-typedef void (*gcry_cipher_decrypt_t) (void *c,
-				       unsigned char *outbuf,
-				       const unsigned char *inbuf);
+typedef unsigned int (*gcry_cipher_decrypt_t) (void *c,
+					       unsigned char *outbuf,
+					       const unsigned char *inbuf);
 
 /* Type for the cipher_stencrypt function.  */
 typedef void (*gcry_cipher_stencrypt_t) (void *c,
 					 unsigned char *outbuf,
 					 const unsigned char *inbuf,
-					 unsigned int n);
+					 grub_size_t n);
 
 /* Type for the cipher_stdecrypt function.  */
 typedef void (*gcry_cipher_stdecrypt_t) (void *c,
 					 unsigned char *outbuf,
 					 const unsigned char *inbuf,
-					 unsigned int n);
+					 grub_size_t n);
+
+typedef void (*selftest_report_func_t)(const char *domain,
+                                       int algo,
+                                       const char *what,
+                                       const char *errdesc);
+
+/* The type used to convey additional information to a cipher.  */
+typedef gpg_err_code_t (*gcry_cipher_set_extra_info_t)
+     (void *c, int what, const void *buffer, grub_size_t buflen);
+
+/* The type used to set an IV directly in the algorithm module.  */
+typedef void (*gcry_cipher_setiv_func_t)(void *c, const grub_uint8_t *iv, grub_size_t ivlen);
+
+/* Definition of the selftest functions.  */
+typedef gpg_err_code_t (*gcry_selftest_func_t)
+     (int algo, int extended, selftest_report_func_t report);
 
 typedef struct gcry_cipher_oid_spec
 {
@@ -125,9 +172,14 @@ typedef struct gcry_cipher_oid_spec
 /* Module specification structure for ciphers.  */
 typedef struct gcry_cipher_spec
 {
+  int algo;
+  struct {
+    unsigned int disabled:1;
+    unsigned int fips:1;
+  } flags;
   const char *name;
   const char **aliases;
-  gcry_cipher_oid_spec_t *oids;
+  const gcry_cipher_oid_spec_t *oids;
   grub_size_t blocksize;
   grub_size_t keylen;
   grub_size_t contextsize;
@@ -136,6 +188,10 @@ typedef struct gcry_cipher_spec
   gcry_cipher_decrypt_t decrypt;
   gcry_cipher_stencrypt_t stencrypt;
   gcry_cipher_stdecrypt_t stdecrypt;
+  gcry_selftest_func_t selftest;
+  gcry_cipher_set_extra_info_t set_extra_info;
+  gcry_cipher_setiv_func_t setiv;
+
 #ifdef GRUB_UTIL
   const char *modname;
 #endif
@@ -143,7 +199,7 @@ typedef struct gcry_cipher_spec
 } gcry_cipher_spec_t;
 
 /* Type for the md_init function.  */
-typedef void (*gcry_md_init_t) (void *c);
+typedef void (*gcry_md_init_t) (void *c, unsigned int flags);
 
 /* Type for the md_write function.  */
 typedef void (*gcry_md_write_t) (void *c, const void *buf, grub_size_t nbytes);
@@ -162,16 +218,24 @@ typedef struct gcry_md_oid_spec
 /* Module specification structure for message digests.  */
 typedef struct gcry_md_spec
 {
+  int algo;
+  struct {
+    unsigned int disabled:1;
+    unsigned int fips:1;
+  } flags;
   const char *name;
-  unsigned char *asnoid;
+  const unsigned char *asnoid;
   int asnlen;
-  gcry_md_oid_spec_t *oids;
+  const gcry_md_oid_spec_t *oids;
   grub_size_t mdlen;
   gcry_md_init_t init;
   gcry_md_write_t write;
   gcry_md_final_t final;
   gcry_md_read_t read;
+  void *extract;
+  void *hash_buffers;
   grub_size_t contextsize; /* allocate this amount of context */
+
   /* Block size, needed for HMAC.  */
   grub_size_t blocksize;
 #ifdef GRUB_UTIL
@@ -180,54 +244,123 @@ typedef struct gcry_md_spec
   struct gcry_md_spec *next;
 } gcry_md_spec_t;
 
+typedef struct gcry_md_handle*gcry_md_hd_t;
+
 struct gcry_mpi;
 typedef struct gcry_mpi *gcry_mpi_t;
 
+struct gcry_sexp;
+typedef struct gcry_sexp *gcry_sexp_t;
+
+
+#define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
+#define PUBKEY_FLAG_RFC6979        (1 << 1)
+#define PUBKEY_FLAG_FIXEDLEN       (1 << 2)
+#define PUBKEY_FLAG_LEGACYRESULT   (1 << 3)
+#define PUBKEY_FLAG_RAW_FLAG       (1 << 4)
+#define PUBKEY_FLAG_TRANSIENT_KEY  (1 << 5)
+#define PUBKEY_FLAG_USE_X931       (1 << 6)
+#define PUBKEY_FLAG_USE_FIPS186    (1 << 7)
+#define PUBKEY_FLAG_USE_FIPS186_2  (1 << 8)
+#define PUBKEY_FLAG_PARAM          (1 << 9)
+#define PUBKEY_FLAG_COMP           (1 << 10)
+#define PUBKEY_FLAG_NOCOMP         (1 << 11)
+#define PUBKEY_FLAG_EDDSA          (1 << 12)
+#define PUBKEY_FLAG_GOST           (1 << 13)
+#define PUBKEY_FLAG_NO_KEYTEST     (1 << 14)
+#define PUBKEY_FLAG_DJB_TWEAK      (1 << 15)
+#define PUBKEY_FLAG_SM2            (1 << 16)
+#define PUBKEY_FLAG_PREHASH        (1 << 17)
+
+enum pk_operation
+  {
+    PUBKEY_OP_ENCRYPT,
+    PUBKEY_OP_DECRYPT,
+    PUBKEY_OP_SIGN,
+    PUBKEY_OP_VERIFY
+  };
+
+enum pk_encoding
+  {
+    PUBKEY_ENC_RAW,
+    PUBKEY_ENC_PKCS1,
+    PUBKEY_ENC_PKCS1_RAW,
+    PUBKEY_ENC_OAEP,
+    PUBKEY_ENC_PSS,
+    PUBKEY_ENC_UNKNOWN
+  };
+
+struct pk_encoding_ctx
+{
+  enum pk_operation op;
+  unsigned int nbits;
+
+  enum pk_encoding encoding;
+  int flags;
+
+  int hash_algo;
+
+  /* for OAEP */
+  unsigned char *label;
+  grub_size_t labellen;
+
+  /* for PSS */
+  grub_size_t saltlen;
+
+  int (* verify_cmp) (void *opaque, gcry_mpi_t tmp);
+  void *verify_arg;
+};
+
 /* Type for the pk_generate function.  */
-typedef gcry_err_code_t (*gcry_pk_generate_t) (int algo,
-					       unsigned int nbits,
-					       unsigned long use_e,
-					       gcry_mpi_t *skey,
-					       gcry_mpi_t **retfactors);
+typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms,
+                                               gcry_sexp_t *r_skey);
 
 /* Type for the pk_check_secret_key function.  */
-typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo,
-						       gcry_mpi_t *skey);
+typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (gcry_sexp_t keyparms);
 
 /* Type for the pk_encrypt function.  */
-typedef gcry_err_code_t (*gcry_pk_encrypt_t) (int algo,
-					      gcry_mpi_t *resarr,
-					      gcry_mpi_t data,
-					      gcry_mpi_t *pkey,
-					      int flags);
+typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph,
+                                              gcry_sexp_t s_data,
+                                              gcry_sexp_t keyparms);
 
 /* Type for the pk_decrypt function.  */
-typedef gcry_err_code_t (*gcry_pk_decrypt_t) (int algo,
-					      gcry_mpi_t *result,
-					      gcry_mpi_t *data,
-					      gcry_mpi_t *skey,
-					      int flags);
+typedef gcry_err_code_t (*gcry_pk_decrypt_t) (gcry_sexp_t *r_plain,
+                                              gcry_sexp_t s_data,
+                                              gcry_sexp_t keyparms);
 
 /* Type for the pk_sign function.  */
-typedef gcry_err_code_t (*gcry_pk_sign_t) (int algo,
-					   gcry_mpi_t *resarr,
-					   gcry_mpi_t data,
-					   gcry_mpi_t *skey);
+typedef gcry_err_code_t (*gcry_pk_sign_t) (gcry_sexp_t *r_sig,
+                                           gcry_sexp_t s_data,
+                                           gcry_sexp_t keyparms);
 
 /* Type for the pk_verify function.  */
-typedef gcry_err_code_t (*gcry_pk_verify_t) (int algo,
-					     gcry_mpi_t hash,
-					     gcry_mpi_t *data,
-					     gcry_mpi_t *pkey,
-					     int (*cmp) (void *, gcry_mpi_t),
-					     void *opaquev);
+typedef gcry_err_code_t (*gcry_pk_verify_t) (gcry_sexp_t s_sig,
+                                             gcry_sexp_t s_data,
+                                             gcry_sexp_t keyparms);
 
 /* Type for the pk_get_nbits function.  */
-typedef unsigned (*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey);
+typedef unsigned (*gcry_pk_get_nbits_t) (gcry_sexp_t keyparms);
+
+/* The type used to compute the keygrip.  */
+typedef gpg_err_code_t (*pk_comp_keygrip_t) (gcry_md_hd_t md,
+                                             gcry_sexp_t keyparm);
+
+/* The type used to query an ECC curve name.  */
+typedef const char *(*pk_get_curve_t)(gcry_sexp_t keyparms, int iterator,
+                                      unsigned int *r_nbits);
+
+/* The type used to query ECC curve parameters by name.  */
+typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name);
 
 /* Module specification structure for message digests.  */
 typedef struct gcry_pk_spec
 {
+  int algo;
+  struct {
+    unsigned int disabled:1;
+    unsigned int fips:1;
+  } flags;
+  int use;
   const char *name;
   const char **aliases;
   const char *elements_pkey;
@@ -235,7 +368,6 @@ typedef struct gcry_pk_spec
   const char *elements_enc;
   const char *elements_sig;
   const char *elements_grip;
-  int use;
   gcry_pk_generate_t generate;
   gcry_pk_check_secret_key_t check_secret_key;
   gcry_pk_encrypt_t encrypt;
@@ -243,6 +375,10 @@ typedef struct gcry_pk_spec
   gcry_pk_sign_t sign;
   gcry_pk_verify_t verify;
   gcry_pk_get_nbits_t get_nbits;
+  pk_comp_keygrip_t comp_keygrip;
+  pk_get_curve_t get_curve;
+  pk_get_curve_param_t get_curve_param;
+
 #ifdef GRUB_UTIL
   const char *modname;
 #endif
@@ -345,6 +481,10 @@ grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
 		  grub_size_t inlen);
 const gcry_md_spec_t *
 grub_crypto_lookup_md_by_name (const char *name);
+const gcry_md_spec_t *
+grub_crypto_lookup_md_by_algo (int algo);
+const gcry_md_spec_t *
+grub_crypto_lookup_md_by_oid (const char *oid);
 
 grub_err_t
 grub_crypto_gcry_error (gcry_err_code_t in);
@@ -408,7 +548,35 @@ void _gcry_assert_failed (const char *expr, const char *file, int line,
 
 void _gcry_burn_stack (int bytes);
 void _gcry_log_error( const char *fmt, ... )  __attribute__ ((format (__printf__, 1, 2)));
+void _gcry_log_info (const char *fmt, ...);
+void __gcry_burn_stack (unsigned int size);
+void __gcry_burn_stack_dummy (void);
+void _gcry_bug( const char *file, int line, const char *func );
+void
+_gcry_fast_wipememory (void *ptr, grub_size_t len);
+void
+_gcry_fast_wipememory2 (void *ptr, int set, grub_size_t len);
+unsigned int
+_gcry_ct_memequal (const void *b1, const void *b2, grub_size_t len);
+unsigned int
+_gcry_ct_not_memequal (const void *b1, const void *b2, grub_size_t len);
+
+
+static inline unsigned int _gcry_get_hw_features(void)
+{
+  return 0;
+}
 
+void *_gcry_malloc(grub_size_t n);
+void *_gcry_malloc_secure(grub_size_t n);
+void *_gcry_xmalloc(grub_size_t n);
+void *_gcry_xmalloc_secure(grub_size_t n);
+void _gcry_free (void *p);
+void *_gcry_xrealloc (void *a, grub_size_t n);
+int _gcry_is_secure (const void *a);
+void *_gcry_xcalloc (grub_size_t n, grub_size_t m);
+void *_gcry_xcalloc_secure (grub_size_t n, grub_size_t m);
+void _gcry_divide_by_zero (void);
 
 #ifdef GRUB_UTIL
 void grub_gcry_init_all (void);
@@ -419,4 +587,11 @@ grub_get_random (void *out, grub_size_t len);
 
 #endif
 
+typedef struct _gpgrt_b64state *gpgrt_b64state_t;
+gpgrt_b64state_t gpgrt_b64dec_start (const char *title);
+gpg_error_t      gpgrt_b64dec_proc (gpgrt_b64state_t state,
+				    void *buffer, grub_size_t length,
+                                    grub_size_t *r_nbytes);
+gpg_error_t      gpgrt_b64dec_finish (gpgrt_b64state_t state);
+const char *gpg_strerror (gpg_error_t err);
 #endif
diff --git a/include/grub/gcrypt/gpg-error.h b/include/grub/gcrypt/gpg-error.h
index 1e4250284..444bef221 100644
--- a/include/grub/gcrypt/gpg-error.h
+++ b/include/grub/gcrypt/gpg-error.h
@@ -29,4 +29,13 @@ gpg_err_source (gpg_error_t err __attribute__ ((unused)))
 gcry_err_code_t
 gpg_error_from_syserror (void);
 
+gcry_err_code_t
+gpg_err_code_from_syserror (void);
+
+gcry_err_code_t
+gpg_error_from_errno (int err);
+
+gcry_err_code_t
+gpg_err_code_from_errno (int err);
+
 #endif
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
index 25ae52ab6..7e6706976 100644
--- a/util/grub-fstest.c
+++ b/util/grub-fstest.c
@@ -364,7 +364,7 @@ static void
 cmd_crc (char *pathname)
 {
   grub_uint8_t *crc32_context = xmalloc (GRUB_MD_CRC32->contextsize);
-  GRUB_MD_CRC32->init(crc32_context);
+  GRUB_MD_CRC32->init(crc32_context, 0);
 
   read_file (pathname, crc_hook, crc32_context);
   GRUB_MD_CRC32->final(crc32_context);
diff --git a/util/import_gcry.py b/util/import_gcry.py
index 2b3322d3a..5422afa11 100644
--- a/util/import_gcry.py
+++ b/util/import_gcry.py
@@ -62,6 +62,12 @@ confutil.write ("  cflags = '$(CFLAGS_GCRY)';\n");
 confutil.write ("  cppflags = '$(CPPFLAGS_GCRY)';\n");
 confutil.write ("  extra_dist = grub-core/lib/libgcrypt-grub/cipher/ChangeLog;\n");
 confutil.write ("\n");
+
+for src in ['src/const-time.c']:
+    confutil.write ("  common = grub-core/lib/libgcrypt-grub/%s;\n" % src)
+
+confutil.write ("\n");
+
 chlog = ""
 modules_sym_md = []
 
@@ -79,10 +85,23 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
                 "_gcry_digest_spec_sha256" : 64,
                 "_gcry_digest_spec_sha384" : 128,
                 "_gcry_digest_spec_sha512" : 128,
+                "_gcry_digest_spec_sha512_256": 128,
+                "_gcry_digest_spec_sha512_224": 128,
                 "_gcry_digest_spec_tiger" : 64,
                 "_gcry_digest_spec_tiger1" : 64,
                 "_gcry_digest_spec_tiger2" : 64,
-                "_gcry_digest_spec_whirlpool" : 64}
+                "_gcry_digest_spec_whirlpool" : 64,
+                "_gcry_digest_spec_shake128": 64,
+                "_gcry_digest_spec_shake256": 64,
+                "_gcry_digest_spec_sm3": 64,
+                "_gcry_digest_spec_stribog_256": 64,
+                "_gcry_digest_spec_stribog_512": 64,
+                "_gcry_digest_spec_sha3_224": 1152 / 8,
+                "_gcry_digest_spec_sha3_256": 1088 / 8,
+                "_gcry_digest_spec_sha3_384": 832 / 8,
+                "_gcry_digest_spec_sha3_512": 576 / 8,
+                "_gcry_digest_spec_gost3411_94": 32,
+                "_gcry_digest_spec_gost3411_cp": 32}
 
 cryptolist = codecs.open (os.path.join (cipher_dir_out, "crypto.lst"), "w", "utf-8")
 
@@ -99,13 +118,32 @@ cryptolist.write ("AES-256: gcry_rijndael\n");
 cryptolist.write ("ADLER32: adler32\n");
 cryptolist.write ("CRC64: crc64\n");
 
+extra_files = {
+    "gcry_camellia": ["camellia.c"], # Main file is camellia-glue.c
+    "gcry_sha512"  : ["hash-common.c"],
+}
+extra_files_list = [x for xs in extra_files.values() for x in xs] + ["pubkey-util.c", "rsa-common.c", "dsa-common.c"]
+
 for cipher_file in cipher_files:
     infile = os.path.join (cipher_dir_in, cipher_file)
     outfile = os.path.join (cipher_dir_out, cipher_file)
     if cipher_file == "ChangeLog" or cipher_file == "ChangeLog-2011":
         continue
     chlognew = "	* %s" % cipher_file
-    if re.match ("(Manifest|Makefile\.am|ac\.c|cipher\.c|hash-common\.c|hmac-tests\.c|md\.c|pubkey\.c)$", cipher_file) or cipher_file == "kdf.c" or cipher_file == "elgamal.c" or cipher_file == "primegen.c" or cipher_file == "ecc.c" or cipher_file == "test-getrusage.c":
+    # Unused generic support files
+    if re.match ("(Makefile\.am|md\.c|cipher\.c|cipher-.*\.c|mac-.*\.c|mac\.c|pubkey\.c)$", cipher_file):
+        chlog = "%s%s: Removed\n" % (chlog, chlognew)
+        continue
+    # TODO: Support KDF
+    if re.match ("(kdf\.c|scrypt\.c)$", cipher_file):
+        chlog = "%s%s: Removed\n" % (chlog, chlognew)
+        continue
+    # TODO: Support chacha20 and poly1305
+    if cipher_file in ["chacha20.c", "ecc.c", "elgamal.c"]:
+        chlog = "%s%s: Removed\n" % (chlog, chlognew)
+        continue        
+    # TODO: Use optimized versions
+    if re.match ("(.*\.[sS]|.*-intel-shaext\.c|.*-ssse3-i386\.c|.*-ppc\.c|.*-ssse3-amd64\.c|.*-s390x\.c|rijndael-aesni\.c|crc-intel-pclmul\.c|.*-armv8-ce\.c|.*-p10le\.c|rijndael-padlock.c|rijndael-ppc9le.c|rijndael-vaes.c)$", cipher_file):
         chlog = "%s%s: Removed\n" % (chlog, chlognew)
         continue
     # Autogenerated files. Not even worth mentionning in ChangeLog
@@ -148,14 +186,10 @@ for cipher_file in cipher_files:
         iscipher = False
         iscryptostart = False
         iscomma = False
-        isglue = False
         skip_statement = False
+        skip_comma = False
         if isc:
-            modname = cipher_file [0:len(cipher_file) - 2]
-            if re.match (".*-glue$", modname):
-                modname = modname.replace ("-glue", "")
-                isglue = True
-            modname = "gcry_%s" % modname
+            modname = "gcry_%s" % cipher_file.removesuffix(".c").removesuffix("-glue").replace("-", "_")
         for line in f:
             line = line
             if skip_statement:
@@ -171,7 +205,7 @@ for cipher_file in cipher_files:
                     skip2 = False
                 continue
             if iscryptostart:
-                s = re.search (" *\"([A-Z0-9_a-z]*)\"", line)
+                s = re.search (" *\"([A-Z0-9_a-z-]*)\"", line)
                 if not s is None:
                     sg = s.groups()[0]
                     cryptolist.write (("%s: %s\n") % (sg, modname))
@@ -212,11 +246,14 @@ for cipher_file in cipher_files:
                     chlognew = "%s %s" % (chlognew, chmsg)
                     nch = True
                 continue
+            if (not hold) and (re.match (r"[ \t]*(run_selftests|do_tripledes_set_extra_info),?", line) is not None):
+                iscomma = True
+                line = ""
             if hold:
                 hold = False
                 # We're optimising for size and exclude anything needing good
                 # randomness.
-                if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info|_gcry_rmd160_mixblock|serpent_test|dsa_generate_ext|test_keys|gen_k|sign|gen_x931_parm_xp|generate_x931|generate_key|dsa_generate|dsa_sign|ecc_sign|generate|generate_fips186|_gcry_register_pk_dsa_progress|_gcry_register_pk_ecc_progress|progress|scanval|ec2os|ecc_generate_ext|ecc_generate|compute_keygrip|ecc_get_param|_gcry_register_pk_dsa_progress|gen_x931_parm_xp|gen_x931_parm_xi|rsa_decrypt|rsa_sign|rsa_generate_ext|rsa_generate|secret|check_exponent|rsa_blind|rsa_unblind|extract_a_from_sexp|curve_free|curve_copy|point_set)", line) is None:
+                if re.match ("(_gcry_hash_selftest_check_one|bulk_selftest_setkey|run_selftests|do_tripledes_set_extra_info|selftest|sm4_selftest|_gcry_[a-z0-9_]*_hash_buffer|tripledes_set2keys|_gcry_rmd160_mixblock|serpent_test|dsa_generate_ext|test_keys|gen_k|sign|gen_x931_parm_xp|generate_x931|generate_key|dsa_generate|dsa_sign|ecc_sign|generate|generate_fips186|_gcry_register_pk_dsa_progress|_gcry_register_pk_ecc_progress|progress|scanval|ec2os|ecc_generate_ext|ecc_generate|ecc_get_param|_gcry_register_pk_dsa_progress|gen_x931_parm_xp|gen_x931_parm_xi|rsa_decrypt|rsa_sign|rsa_generate_ext|rsa_generate|secret|check_exponent|rsa_blind|rsa_unblind|extract_a_from_sexp|curve_free|curve_copy|point_set|_gcry_dsa_gen_rfc6979_k|bits2octets|int2octets)", line) is not None:
 
                     skip = 1
                     if not re.match ("selftest", line) is None and cipher_file == "idea.c":
@@ -224,6 +261,11 @@ for cipher_file in cipher_files:
 
                     if not re.match ("serpent_test", line) is None:
                         fw.write ("static const char *serpent_test (void) { return 0; }\n");
+                    if not re.match ("sm4_selftest", line) is None:
+                        fw.write ("static const char *sm4_selftest (void) { return 0; }\n");
+                    hash_buf = re.match ("(_gcry_[a-z0-9_]*_hash_buffers)", line)
+                    if hash_buf is not None:
+                        fw.write ("#define %s 0" % (hash_buf.group(0)))
                     if not re.match ("dsa_generate", line) is None:
                         fw.write ("#define dsa_generate 0");
                     if not re.match ("ecc_generate", line) is None:
@@ -257,37 +299,38 @@ for cipher_file in cipher_files:
                     chlognew = "%s: %s" % (chlognew, chmsg)
                     nch = True
                 continue
-            m = re.match ("gcry_cipher_spec_t", line)
+            m = re.match ("(const )?gcry_cipher_spec_t", line)
             if isc and not m is None:
                 assert (not ismd)
                 assert (not ispk)
                 assert (not iscipher)
                 assert (not iscryptostart)
-                ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
+                ciphername = line.removeprefix("const ").removeprefix("gcry_cipher_spec_t").strip ()
                 ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
                 ciphernames.append (ciphername)
                 iscipher = True
                 iscryptostart = True
 
-            m = re.match ("gcry_pk_spec_t", line)
+            m = re.match ("(const )?gcry_pk_spec_t", line)
             if isc and not m is None:
                 assert (not ismd)
                 assert (not ispk)
                 assert (not iscipher)
                 assert (not iscryptostart)
-                pkname = line [len ("gcry_pk_spec_t"):].strip ()
+                pkname = line.removeprefix("const ").removeprefix("gcry_pk_spec_t").strip ()
                 pkname = re.match("[a-zA-Z0-9_]*",pkname).group ()
                 pknames.append (pkname)
                 ispk = True
                 iscryptostart = True
 
-            m = re.match ("gcry_md_spec_t", line)
+            m = re.match ("(const )?gcry_md_spec_t", line)
             if isc and not m is None:
                 assert (not ismd)
                 assert (not ispk)
                 assert (not iscipher)
                 assert (not iscryptostart)
-                mdname = line [len ("gcry_md_spec_t"):].strip ()
+                line = line.removeprefix("const ")
+                mdname = line.removeprefix("const ").removeprefix("gcry_md_spec_t").strip ()
                 mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
                 mdnames.append (mdname)
                 ismd = True
@@ -350,7 +393,7 @@ for cipher_file in cipher_files:
                     nch = True
                 continue
 
-            m = re.match ("(static const char( |)\*|static gpg_err_code_t|void|static int|static gcry_err_code_t|static gcry_mpi_t|static void|void|static elliptic_curve_t) *$", line)
+            m = re.match ("((static )?const char( |)\*|(static )?gpg_err_code_t|void|static int|(static )?gcry_err_code_t|static gcry_mpi_t|static void|void|static elliptic_curve_t) *$", line)
             if not m is None:
                 hold = True
                 holdline = line
@@ -421,11 +464,9 @@ for cipher_file in cipher_files:
                 continue
             fw.write (line)
         if len (ciphernames) > 0 or len (mdnames) > 0 or len (pknames) > 0:
-            if isglue:
-                modfiles = "lib/libgcrypt-grub/cipher/%s lib/libgcrypt-grub/cipher/%s" \
-                    % (cipher_file, cipher_file.replace ("-glue.c", ".c"))
-            else:
-                modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file
+            modfiles = [cipher_file]
+            if modname in extra_files.keys():
+                modfiles += extra_files[modname]
             if len (ciphernames) > 0 or len (mdnames) > 0:
                 modules_sym_md.append (modname)
             chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
@@ -447,7 +488,7 @@ for cipher_file in cipher_files:
                 chlognew = "%s\n	%s" % (chlognew, chmsg)
                 fw.write ("  grub_md_register (&%s);\n" % mdname)
             for pkname in pknames:
-                chmsg = "Register pk %s" % mdname
+                chmsg = "Register pk %s" % pkname
                 chlognew = "%s\n	%s" % (chlognew, chmsg)
                 fw.write ("  grub_crypto_pk_%s = &%s;\n"
                           % (pkname.replace ("_gcry_pubkey_spec_", ""), pkname))
@@ -465,17 +506,17 @@ for cipher_file in cipher_files:
                 chlognew = "%s\n	%s" % (chlognew, chmsg)
                 fw.write ("  grub_md_unregister (&%s);\n" % mdname)
             for pkname in pknames:
-                chmsg = "Unregister pk %s" % mdname
+                chmsg = "Unregister pk %s" % pkname
                 chlognew = "%s\n	%s" % (chlognew, chmsg)
                 fw.write ("  grub_crypto_pk_%s = 0;\n"
                           % (pkname.replace ("_gcry_pubkey_spec_", "")))
             fw.write ("}\n")
             conf.write ("module = {\n")
             conf.write ("  name = %s;\n" % modname)
-            for src in modfiles.split():
-                conf.write ("  common = %s;\n" % src)
+            for src in modfiles:
+                conf.write ("  common = lib/libgcrypt-grub/cipher/%s;\n" % src)
                 if len (ciphernames) > 0 or len (mdnames) > 0:
-                    confutil.write ("  common = grub-core/%s;\n" % src)
+                    confutil.write ("  common = grub-core/lib/libgcrypt-grub/cipher/%s;\n" % src)
             if modname == "gcry_ecc":
                 conf.write ("  common = lib/libgcrypt-grub/mpi/ec.c;\n")
                 conf.write ("  cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';\n")
@@ -490,7 +531,7 @@ for cipher_file in cipher_files:
             fw.close ()
             if nch:
                 chlog = "%s%s\n" % (chlog, chlognew)
-        elif isc and cipher_file != "camellia.c":
+        elif isc and cipher_file not in extra_files_list:
             print ("WARNING: C file isn't a module: %s" % cipher_file)
             f.close ()
             fw.close ()
@@ -512,7 +553,7 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))):
             or src == "libgcrypt.vers" or src == "Makefile.am" \
             or src == "Manifest" or src == "misc.c" \
             or src == "missing-string.c" or src == "module.c" \
-            or src == "secmem.c" or src == "sexp.c" \
+            or src == "secmem.c" \
             or src == "stdmem.c" or src == "visibility.c":
         continue
     outfile = os.path.join (basedir, "src", src)
@@ -534,8 +575,17 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))):
         fw.close ()
         continue
 
+    if src == "cipher-proto.h":
+        fw.write("#include <grub/crypto.h>\n")
+        fw.write("typedef gcry_selftest_func_t selftest_func_t;")
+        f.close ()
+        fw.close ()
+        continue
+
     if src == "g10lib.h":
-        fw.write (f.read ().replace ("(printf,f,a)", "(__printf__,f,a)"))
+        fw.write("#include <cipher_wrap.h>\n")
+        fw.write("#include <grub/crypto.h>\n")
+        fw.write (f.read ().replace ("(printf,f,a)", "(__printf__,f,a)").replace ("#include \"../compat/libcompat.h\"", "").replace("#define N_(a) (a)", ""))
         f.close ()
         fw.close ()
         continue
@@ -546,7 +596,7 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))):
 
 for src in sorted (os.listdir (os.path.join (indir, "mpi"))):
     if src == "config.links" or src == "ChangeLog-2011" \
-            or src == "mpi-scan.c" or src == "Manifest" \
+            or src == "Manifest" \
             or src == "Makefile.am":
         continue
     infile = os.path.join (indir, "mpi", src)
@@ -568,7 +618,7 @@ for src in sorted (os.listdir (os.path.join (indir, "mpi"))):
             hold = False
             # We're optimising for size and exclude anything needing good
             # randomness.
-            if not re.match ("(_gcry_mpi_get_hw_config|gcry_mpi_randomize)", line) is None:
+            if not re.match ("(_gcry_mpi_get_hw_config|gcry_mpi_randomize|_gcry_mpi_randomize)", line) is None:
                 skip = 1
                 continue
             else:
@@ -612,9 +662,6 @@ fw.write ("#include <cipher_wrap.h>\n")
 chlog = "%s	* g10lib.h: Likewise.\n" % chlog
 fw.close ()
 
-infile = os.path.join (cipher_dir_in, "ChangeLog")
-outfile = os.path.join (cipher_dir_out, "ChangeLog")
-
 conf.close ();
 
 initfile = codecs.open (os.path.join (cipher_dir_out, "init.c"), "w", "utf-8")
@@ -643,7 +690,7 @@ confutil.write ("};\n");
 confutil.close ();
 
 
-f=codecs.open (infile, "r", "utf-8")
+outfile = os.path.join (cipher_dir_out, "ChangeLog")
 fw=codecs.open (outfile, "w", "utf-8")
 dt = datetime.date.today ()
 fw.write ("%04d-%02d-%02d  Automatic import tool\n" % \
@@ -653,7 +700,4 @@ fw.write ("	Imported ciphers to GRUB\n")
 fw.write ("\n")
 fw.write (chlog)
 fw.write ("\n")
-for line in f:
-    fw.write (line)
-f.close ()
 fw.close ()
diff --git a/util/import_gcrypt_inth.sed b/util/import_gcrypt_inth.sed
new file mode 100644
index 000000000..ebe9371ee
--- /dev/null
+++ b/util/import_gcrypt_inth.sed
@@ -0,0 +1,17 @@
+/^#@INSERT_SYS_SELECT_H@/ d
+/^@FALLBACK_SOCKLEN_T@/ d
+/^# *include <stdlib\.h>/ d
+/^# *include <string\.h>/ d
+/^# *include <winsock2\.h>/ d
+/^# *include <ws2tcpip\.h>/ d
+/^# *include <time\.h>/ d
+/^# *include <sys\/socket\.h>/ d
+/^# *include <sys\/time\.h>/ d
+/^  typedef long ssize_t;/ d
+/^  typedef int  pid_t;/ d
+/^# *include <gpg-error\.h>/ s,#include <gpg-error.h>,#include <grub/gcrypt/gpg-error.h>,
+/^typedef gpg_error_t gcry_error_t;/ d
+/^typedef gpg_err_code_t gcry_err_code_t;/ d
+/^typedef struct gcry_mpi \*gcry_mpi_t;/ d
+/^#error  gcrypt.h already included/ d
+p
diff --git a/util/import_gcrypth.sed b/util/import_gcrypth.sed
index fe6d1a072..503b4b547 100644
--- a/util/import_gcrypth.sed
+++ b/util/import_gcrypth.sed
@@ -13,6 +13,4 @@
 /^typedef gpg_error_t gcry_error_t;/ d
 /^typedef gpg_err_code_t gcry_err_code_t;/ d
 /^typedef struct gcry_mpi \*gcry_mpi_t;/ d
-/^struct gcry_thread_cbs/ d
-s,_gcry_mpi_invm,gcry_mpi_invm,g
 p
\ No newline at end of file
-- 
2.39.2


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

  reply	other threads:[~2024-05-16 18:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-16 18:27 [PATCH 1/3] Import libgcrypt 1.10.3 Vladimir Serbinenko
2024-05-16 18:27 ` Vladimir Serbinenko [this message]
2024-05-17 11:12   ` [PATCH 2/3] Adjust import script, definitions and API users for libgcrypt 1.10 Daniel Kiper
2024-05-16 18:27 ` [PATCH 3/3] keccak: Disable acceleration with SSE asm Vladimir Serbinenko
2024-05-17 11:15   ` Daniel Kiper
2024-05-17 11:24     ` Vladimir 'phcoder' Serbinenko
2024-05-20 17:17       ` Daniel Kiper
2024-05-17 10:52 ` [PATCH 1/3] Import libgcrypt 1.10.3 Daniel Kiper
2024-05-21  7:32 ` Gary Lin via Grub-devel
2024-05-21 10:36   ` Vladimir 'phcoder' Serbinenko
2024-05-22  5:45     ` Gary Lin via Grub-devel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240516182743.2350-2-phcoder@gmail.com \
    --to=phcoder@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).