From: Mate Kukri <mate.kukri@canonical.com>
Date: Thu, 24 Jul 2025 10:36:23 +0100
Subject: Check out missing distfiles from upstream git branch

These files are missing from the release tarball due to upstream
Makefile mistakes.

Should be fixed by the real 2.14 release, so this is just a temporary
workaround that we will drop.
---
 grub-core/lib/libgcrypt-patches/01_md.patch        |  124 +
 .../lib/libgcrypt-patches/02_keccak_sse.patch      |   25 +
 .../lib/libgcrypt-patches/03_mpiutil_alloc.patch   |   18 +
 grub-core/lib/libgcrypt-patches/03_sexp_free.patch |   35 +
 grub-core/lib/libgcrypt-patches/04_aria.patch      |   22 +
 .../libgcrypt-patches/05_disable_rsa_shake.patch   |   36 +
 grub-core/lib/libgcrypt-patches/06_blake.patch     |   80 +
 .../lib/libgcrypt-patches/07_disable_64div.patch   |   15 +
 grub-core/lib/libgcrypt-patches/08_sexp_leak.patch |   21 +
 ...-libtasn1-disable-code-not-needed-in-grub.patch |  320 +++
 ...place-strcat-with-strcpy-in-_asn1_str_cat.patch |   33 +
 ...ibtasn1-replace-strcat-with-_asn1_str_cat.patch |   71 +
 ...sn1-adjust-the-header-paths-in-libtasn1.h.patch |   39 +
 ...5-libtasn1-Use-grub_divmod64-for-division.patch |   31 +
 ...libtasn1-fix-the-potential-buffer-overrun.patch |   36 +
 .../0007-asn1_test-include-asn1_test.h-only.patch  |  164 ++
 ...ename-the-main-functions-to-the-test-name.patch |  129 +
 ...eturn-either-0-or-1-to-reflect-the-result.patch |   78 +
 ...remove-verbose-and-the-unnecessary-printf.patch |  173 ++
 ...print-the-error-messages-with-grub_printf.patch |  485 ++++
 ...use-the-grub-specific-functions-and-types.patch |  263 ++
 ...nable-the-testcase-only-when-GRUB_LONG_MA.patch |   48 +
 grub-core/lib/libtasn1/COPYING                     |   16 +
 grub-core/lib/libtasn1/README.md                   |   98 +
 grub-core/lib/libtasn1/lib/coding.c                | 1425 +++++++++++
 grub-core/lib/libtasn1/lib/decoding.c              | 2501 ++++++++++++++++++++
 grub-core/lib/libtasn1/lib/element.c               | 1109 +++++++++
 grub-core/lib/libtasn1/lib/errors.c                |  100 +
 grub-core/lib/libtasn1/lib/gstr.c                  |   74 +
 grub-core/lib/libtasn1/lib/parser_aux.c            | 1178 +++++++++
 grub-core/lib/libtasn1/lib/structure.c             | 1225 ++++++++++
 grub-core/lib/libtasn1/tests/CVE-2018-1000654.c    |   72 +
 grub-core/lib/libtasn1/tests/Test_overflow.c       |  168 ++
 grub-core/lib/libtasn1/tests/Test_simple.c         |  226 ++
 grub-core/lib/libtasn1/tests/Test_strings.c        |  156 ++
 grub-core/lib/libtasn1/tests/object-id-decoding.c  |  121 +
 grub-core/lib/libtasn1/tests/object-id-encoding.c  |  133 ++
 grub-core/lib/libtasn1/tests/octet-string.c        |  230 ++
 grub-core/lib/libtasn1/tests/reproducers.c         |   90 +
 util/import_gcrypt_inth.sed                        |   17 +
 40 files changed, 11185 insertions(+)
 create mode 100644 grub-core/lib/libgcrypt-patches/01_md.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/02_keccak_sse.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/03_sexp_free.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/04_aria.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/05_disable_rsa_shake.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/06_blake.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/07_disable_64div.patch
 create mode 100644 grub-core/lib/libgcrypt-patches/08_sexp_leak.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0002-libtasn1-replace-strcat-with-strcpy-in-_asn1_str_cat.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0003-libtasn1-replace-strcat-with-_asn1_str_cat.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0004-libtasn1-adjust-the-header-paths-in-libtasn1.h.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0005-libtasn1-Use-grub_divmod64-for-division.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0006-libtasn1-fix-the-potential-buffer-overrun.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0007-asn1_test-include-asn1_test.h-only.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0008-asn1_test-rename-the-main-functions-to-the-test-name.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0009-asn1_test-return-either-0-or-1-to-reflect-the-result.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0011-asn1_test-print-the-error-messages-with-grub_printf.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0012-asn1_test-use-the-grub-specific-functions-and-types.patch
 create mode 100644 grub-core/lib/libtasn1-patches/0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch
 create mode 100644 grub-core/lib/libtasn1/COPYING
 create mode 100644 grub-core/lib/libtasn1/README.md
 create mode 100644 grub-core/lib/libtasn1/lib/coding.c
 create mode 100644 grub-core/lib/libtasn1/lib/decoding.c
 create mode 100644 grub-core/lib/libtasn1/lib/element.c
 create mode 100644 grub-core/lib/libtasn1/lib/errors.c
 create mode 100644 grub-core/lib/libtasn1/lib/gstr.c
 create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.c
 create mode 100644 grub-core/lib/libtasn1/lib/structure.c
 create mode 100644 grub-core/lib/libtasn1/tests/CVE-2018-1000654.c
 create mode 100644 grub-core/lib/libtasn1/tests/Test_overflow.c
 create mode 100644 grub-core/lib/libtasn1/tests/Test_simple.c
 create mode 100644 grub-core/lib/libtasn1/tests/Test_strings.c
 create mode 100644 grub-core/lib/libtasn1/tests/object-id-decoding.c
 create mode 100644 grub-core/lib/libtasn1/tests/object-id-encoding.c
 create mode 100644 grub-core/lib/libtasn1/tests/octet-string.c
 create mode 100644 grub-core/lib/libtasn1/tests/reproducers.c
 create mode 100644 util/import_gcrypt_inth.sed

diff --git a/grub-core/lib/libgcrypt-patches/01_md.patch b/grub-core/lib/libgcrypt-patches/01_md.patch
new file mode 100644
index 0000000..8ac902a
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/01_md.patch
@@ -0,0 +1,124 @@
+--- a/grub-core/lib/libgcrypt-grub/cipher/md.c
++++ b/grub-core/lib/libgcrypt-grub/cipher/md.c
+@@ -20,11 +20,25 @@
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+  */
++#include <config.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
+ 
+ 
+ #include "g10lib.h"
+ #include "cipher.h"
+ 
++#define _gcry_md_selftest(a,b,c) 0
++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 is the list of the digest implementations included in
+    libgcrypt.  */
+@@ -53,7 +67,6 @@
+ 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 );
+ static void md_start_debug ( gcry_md_hd_t a, const char *suffix );
+ static void md_stop_debug ( gcry_md_hd_t a );
+@@ -186,9 +199,6 @@
+ 
+   if (! err)
+     {
+-      /* Hmmm, should we really do that? - yes [-wk] */
+-      _gcry_fast_random_poll ();
+-
+       if (algo)
+ 	{
+ 	  err = md_enable (hd, algo);
+@@ -437,14 +447,6 @@
+ {
+   GcryDigestEntry *r;
+ 
+-  if (a->ctx->debug)
+-    {
+-      if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1)
+-	BUG();
+-      if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1)
+-	BUG();
+-    }
+-
+   for (r = a->ctx->list; r; r = r->next)
+     {
+       if (a->bufpos)
+@@ -695,6 +697,7 @@
+       return;
+     }
+ 
++#if 0
+   if (spec->hash_buffers != NULL)
+     {
+       gcry_buffer_t iov;
+@@ -711,6 +714,7 @@
+       spec->hash_buffers (digest, spec->mdlen, &iov, 1);
+     }
+   else
++#endif
+     {
+       /* For the others we do not have a fast function, so we use the
+          normal functions. */
+@@ -893,43 +896,15 @@
+ static void
+ md_start_debug ( gcry_md_hd_t md, const char *suffix )
+ {
+-  static int idx=0;
+-  char buf[50];
+-
+-  if (fips_mode ())
+-    return;
+-
+-  if ( md->ctx->debug )
+-    {
+-      log_debug("Oops: md debug already started\n");
+-      return;
+-    }
+-  idx++;
+-  snprintf (buf, DIM(buf)-1, "dbgmd-%05d.%.10s", idx, suffix );
+-  md->ctx->debug = fopen(buf, "w");
+-  if ( !md->ctx->debug )
+-    log_debug("md debug: can't open %s\n", buf );
++  (void) md;
++  (void) suffix;
+ }
+ 
+ 
+ static void
+ md_stop_debug( gcry_md_hd_t md )
+ {
+-  if ( md->ctx->debug )
+-    {
+-      if ( md->bufpos )
+-        md_write ( md, NULL, 0 );
+-      fclose (md->ctx->debug);
+-      md->ctx->debug = NULL;
+-    }
+-
+-  {  /* a kludge to pull in the __muldi3 for Solaris */
+-    volatile u32 a = (u32)(uintptr_t)md;
+-    volatile u64 b = 42;
+-    volatile u64 c;
+-    c = a * b;
+-    (void)c;
+-  }
++  (void) md;
+ }
+ 
+ 
diff --git a/grub-core/lib/libgcrypt-patches/02_keccak_sse.patch b/grub-core/lib/libgcrypt-patches/02_keccak_sse.patch
new file mode 100644
index 0000000..4deda12
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/02_keccak_sse.patch
@@ -0,0 +1,25 @@
+commit b0cf06271da5fe20360953a53a47c69da89669cd
+Author: Vladimir Serbinenko <phcoder@gmail.com>
+Date:   Sun Apr 7 03:33:11 2024 +0000
+
+    keccak: Disable acceleration with SSE asm
+
+    Libgcrypt code assumes that on x64 all SSE registers are fair game.
+    While it's true that CPUs in question support it, we disable it in
+    our compilation options. Disable the offending optimization.
+
+    Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+diff --git a/grub-core/lib/libgcrypt/cipher/keccak.c b/grub-core/lib/libgcrypt/cipher/keccak.c
+index 11e64b3e7..8b570263b 100644
+--- a/grub-core/lib/libgcrypt-grub/cipher/keccak.c
++++ b/grub-core/lib/libgcrypt-grub/cipher/keccak.c
+@@ -275,7 +275,7 @@ keccak_absorb_lane32bi(u32 *lane, u32 x0, u32 x1)
+ /* Construct generic 64-bit implementation. */
+ #ifdef USE_64BIT
+ 
+-#if __GNUC__ >= 4 && defined(__x86_64__)
++#if __GNUC__ >= 4 && defined(__x86_64__) && 0
+ 
+ static inline void absorb_lanes64_8(u64 *dst, const byte *in)
+ {
diff --git a/grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch b/grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch
new file mode 100644
index 0000000..42c6b2b
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch
@@ -0,0 +1,18 @@
+mpiutil: Fix NULL pointer dereference in case of failed alloc
+
+Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+diff --git a/grub-core/lib/libgcrypt/mpi/mpiutil.c b/grub-core/lib/libgcrypt/mpi/mpiutil.c
+index 3a372374f..dc53db09d 100644
+--- a/grub-core/lib/libgcrypt-grub/mpi/mpiutil.c
++++ b/grub-core/lib/libgcrypt-grub/mpi/mpiutil.c
+@@ -432,6 +432,9 @@ _gcry_mpi_alloc_like( gcry_mpi_t a )
+ 	int n = (a->sign+7)/8;
+ 	void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n)
+                                        : xtrymalloc (n);
++	if ( !p ) {
++            _gcry_fatal_error (GPG_ERR_ENOMEM, NULL);
++	}
+ 	memcpy( p, a->d, n );
+ 	b = mpi_set_opaque( NULL, p, a->sign );
+     }
diff --git a/grub-core/lib/libgcrypt-patches/03_sexp_free.patch b/grub-core/lib/libgcrypt-patches/03_sexp_free.patch
new file mode 100644
index 0000000..1c0ffd6
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/03_sexp_free.patch
@@ -0,0 +1,35 @@
+sexp: Add missing free on error path
+
+Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+diff --git a/grub-core/lib/libgcrypt/src/sexp.c b/grub-core/lib/libgcrypt/src/sexp.c
+index d15f1a790..250559f75 100644
+--- a/grub-core/lib/libgcrypt-grub/src/sexp.c
++++ b/grub-core/lib/libgcrypt-grub/src/sexp.c
+@@ -1157,6 +1157,17 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+                               }                                            \
+                        } while (0)
+ 
++#define MAKE_SPACE_EXTRA_CLEANUP(n, cleanup)  do {				\
++                            gpg_err_code_t _ms_err = make_space (&c, (n)); \
++                            if (_ms_err)                                   \
++                              {                                            \
++                                err = _ms_err;                             \
++                                *erroff = p - buffer;                      \
++				cleanup;				   \
++                                goto leave;                                \
++                              }                                            \
++                       } while (0)
++
+   /* The STORE_LEN macro is used to store the length N at buffer P. */
+ #define STORE_LEN(p,n) do {						   \
+ 			    DATALEN ashort = (n);			   \
+@@ -1368,7 +1379,7 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
+                   goto leave;
+                 }
+ 
+-              MAKE_SPACE (datalen);
++              MAKE_SPACE_EXTRA_CLEANUP (datalen, xfree (b64buf));
+               *c.pos++ = ST_DATA;
+               STORE_LEN (c.pos, datalen);
+               for (i = 0; i < datalen; i++)
diff --git a/grub-core/lib/libgcrypt-patches/04_aria.patch b/grub-core/lib/libgcrypt-patches/04_aria.patch
new file mode 100644
index 0000000..b2f6e88
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/04_aria.patch
@@ -0,0 +1,22 @@
+diff --git a/grub-core/lib/libgcrypt/cipher/aria.c b/grub-core/lib/libgcrypt/cipher/aria.c
+index bc2d43841..cfc5a74f2 100644
+--- a/grub-core/lib/libgcrypt-grub/cipher/aria.c
++++ b/grub-core/lib/libgcrypt-grub/cipher/aria.c
+@@ -1013,7 +1013,7 @@ aria_crypt(ARIA_context *ctx, byte *out, const byte *in,
+   return 4 * sizeof(void *) + 4 * sizeof(u32); /* stack burn depth */
+ }
+ 
+-unsigned int
++static unsigned int
+ aria_encrypt(void *c, byte *outbuf, const byte *inbuf)
+ {
+   ARIA_context *ctx = (ARIA_context *)c;
+@@ -1023,7 +1023,7 @@ aria_encrypt(void *c, byte *outbuf, const byte *inbuf)
+   return aria_crypt (ctx, outbuf, inbuf, ctx->enc_key);
+ }
+ 
+-unsigned int
++static unsigned int
+ aria_decrypt(void *c, byte *outbuf, const byte *inbuf)
+ {
+   ARIA_context *ctx = (ARIA_context *)c;
diff --git a/grub-core/lib/libgcrypt-patches/05_disable_rsa_shake.patch b/grub-core/lib/libgcrypt-patches/05_disable_rsa_shake.patch
new file mode 100644
index 0000000..aaddb4e
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/05_disable_rsa_shake.patch
@@ -0,0 +1,36 @@
+diff --git a/grub-core/lib/libgcrypt/cipher/rsa-common.c b/grub-core/lib/libgcrypt/cipher/rsa-common.c
+index 1920eedd8..c4819208b 100644
+--- a/grub-core/lib/libgcrypt-grub/cipher/rsa-common.c
++++ b/grub-core/lib/libgcrypt-grub/cipher/rsa-common.c
+@@ -912,6 +912,7 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
+   memcpy (p, salt, saltlen);
+ 
+   /* Step 9: dbmask = MGF(H, emlen - hlen - 1).  */
++#if 0
+   if (algo == GCRY_MD_SHAKE128 || algo == GCRY_MD_SHAKE256)
+     {
+       gcry_buffer_t iov;
+@@ -925,6 +926,7 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
+                                      &iov, 1);
+     }
+   else
++#endif
+     mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo);
+ 
+   /* Step 10: maskedDB = DB ^ dbMask */
+@@ -1086,6 +1088,7 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already,
+     }
+ 
+   /* Step 7: dbmask = MGF(H, emlen - hlen - 1).  */
++#if 0
+   if (algo == GCRY_MD_SHAKE128 || algo == GCRY_MD_SHAKE256)
+     {
+       gcry_buffer_t iov;
+@@ -1099,6 +1202,7 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already,
+                                      &iov, 1);
+     }
+   else
++#endif
+     mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo);
+ 
+   /* Step 8: maskedDB = DB ^ dbMask.  */
diff --git a/grub-core/lib/libgcrypt-patches/06_blake.patch b/grub-core/lib/libgcrypt-patches/06_blake.patch
new file mode 100644
index 0000000..c3b9d6f
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/06_blake.patch
@@ -0,0 +1,80 @@
+--- a/grub-core/lib/libgcrypt-grub/cipher/blake2.c
++++ b/grub-core/lib/libgcrypt-grub/cipher/blake2.c
+@@ -841,68 +841,6 @@
+   return blake2s_init(c, key, keylen);
+ }
+ 
+-/* Selftests from "RFC 7693, Appendix E. BLAKE2b and BLAKE2s Self-Test
+- * Module C Source". */
+-static void selftest_seq(byte *out, size_t len, u32 seed)
+-{
+-  size_t i;
+-  u32 t, a, b;
+-
+-  a = 0xDEAD4BAD * seed;
+-  b = 1;
+-
+-  for (i = 0; i < len; i++)
+-    {
+-      t = a + b;
+-      a = b;
+-      b = t;
+-      out[i] = (t >> 24) & 0xFF;
+-    }
+-}
+-
+-
+-
+-
+-gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags,
+-					   const unsigned char *key,
+-					   size_t keylen, int algo)
+-{
+-  gcry_err_code_t rc;
+-  switch (algo)
+-    {
+-    case GCRY_MD_BLAKE2B_512:
+-      rc = blake2b_init_ctx (ctx, flags, key, keylen, 512);
+-      break;
+-    case GCRY_MD_BLAKE2B_384:
+-      rc = blake2b_init_ctx (ctx, flags, key, keylen, 384);
+-      break;
+-    case GCRY_MD_BLAKE2B_256:
+-      rc = blake2b_init_ctx (ctx, flags, key, keylen, 256);
+-      break;
+-    case GCRY_MD_BLAKE2B_160:
+-      rc = blake2b_init_ctx (ctx, flags, key, keylen, 160);
+-      break;
+-    case GCRY_MD_BLAKE2S_256:
+-      rc = blake2s_init_ctx (ctx, flags, key, keylen, 256);
+-      break;
+-    case GCRY_MD_BLAKE2S_224:
+-      rc = blake2s_init_ctx (ctx, flags, key, keylen, 224);
+-      break;
+-    case GCRY_MD_BLAKE2S_160:
+-      rc = blake2s_init_ctx (ctx, flags, key, keylen, 160);
+-      break;
+-    case GCRY_MD_BLAKE2S_128:
+-      rc = blake2s_init_ctx (ctx, flags, key, keylen, 128);
+-      break;
+-    default:
+-      rc = GPG_ERR_DIGEST_ALGO;
+-      break;
+-    }
+-
+-  return rc;
+-}
+-
+-
+ #define DEFINE_BLAKE2_VARIANT(bs, BS, dbits, oid_branch) \
+   static void blake2##bs##_##dbits##_init(void *ctx, unsigned int flags) \
+   { \
+@@ -936,7 +874,7 @@
+       dbits / 8, blake2##bs##_##dbits##_init, blake2##bs##_write, \
+       blake2##bs##_final, blake2##bs##_read, NULL, \
+       _gcry_blake2##bs##_##dbits##_hash_buffers, \
+-      sizeof (BLAKE2##BS##_CONTEXT), selftests_blake2##bs \
++      sizeof (BLAKE2##BS##_CONTEXT) \
+     , \
+     GRUB_UTIL_MODNAME("gcry_blake2") \
+     .blocksize = GRUB_BLAKE2 ## BS ## _BLOCK_SIZE \
diff --git a/grub-core/lib/libgcrypt-patches/07_disable_64div.patch b/grub-core/lib/libgcrypt-patches/07_disable_64div.patch
new file mode 100644
index 0000000..bb47bdf
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/07_disable_64div.patch
@@ -0,0 +1,15 @@
+Don't use 64-bit division on platforms where it's slow
+
+diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h
+index 21bd1a7ef..672448724 100644
+--- a/grub-core/lib/libgcrypt-grub/mpi/longlong.h
++++ b/grub-core/lib/libgcrypt-grub/mpi/longlong.h
+@@ -1711,7 +1711,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
+   } while (0)
+ 
+ /* Use double word type if available. */
+-#if !defined (udiv_qrnnd) && defined (UDWtype)
++#if !defined (udiv_qrnnd) && defined (UDWtype) && !defined(__arm__) && !defined(__mips__) && !defined(__powerpc__)
+ #  define udiv_qrnnd(q, r, nh, nl, d) \
+   do {									\
+     UWtype __d = (d);							\
diff --git a/grub-core/lib/libgcrypt-patches/08_sexp_leak.patch b/grub-core/lib/libgcrypt-patches/08_sexp_leak.patch
new file mode 100644
index 0000000..eefd031
--- /dev/null
+++ b/grub-core/lib/libgcrypt-patches/08_sexp_leak.patch
@@ -0,0 +1,21 @@
+sexp: Fix a memory leak
+
+Fixes: CID 468917
+
+Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
+
+diff -ur ../libgcrypt-1.11.0/src/sexp.c grub-core/lib/libgcrypt/src/sexp.c
+--- a/grub-core/lib/libgcrypt-grub/src/sexp.c	2024-03-28 10:07:27.000000000 +0000
++++ b/grub-core/lib/libgcrypt-grub/src/sexp.c	2025-07-02 17:10:32.714864459 +0000
+@@ -2725,8 +2725,10 @@
+   length = 0;
+   for (s=string; *s; s +=2 )
+     {
+-      if (!hexdigitp (s) || !hexdigitp (s+1))
++      if (!hexdigitp (s) || !hexdigitp (s+1)) {
++	free (buffer);
+         return NULL;           /* Invalid hex digits. */
++      }
+       ((unsigned char*)buffer)[length++] = xtoi_2 (s);
+     }
+   *r_length = length;
diff --git a/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch b/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
new file mode 100644
index 0000000..85bfa07
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
@@ -0,0 +1,320 @@
+From f534b3c0902adf207b7e51b8364284fe6a06731b Mon Sep 17 00:00:00 2001
+From: Daniel Axtens <dja@axtens.net>
+Date: Fri, 1 May 2020 17:12:23 +1000
+Subject: [PATCH 01/13] libtasn1: disable code not needed in grub
+
+We don't expect to be able to write ASN.1, only read it,
+so we can disable some code.
+
+Do that with #if 0/#endif, rather than deletion. This means
+that the difference between upstream and grub is smaller,
+which should make updating libtasn1 easier in the future.
+
+With these exclusions we also avoid the need for minmax.h,
+which is convenient because it means we don't have to
+import it from gnulib.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/libtasn1-grub/lib/coding.c    | 12 ++++++++++--
+ grub-core/lib/libtasn1-grub/lib/decoding.c  |  2 ++
+ grub-core/lib/libtasn1-grub/lib/element.c   |  6 +++---
+ grub-core/lib/libtasn1-grub/lib/errors.c    |  3 +++
+ grub-core/lib/libtasn1-grub/lib/structure.c | 10 ++++++----
+ grub-core/lib/libtasn1-grub/libtasn1.h      | 15 +++++++++++++++
+ 6 files changed, 39 insertions(+), 9 deletions(-)
+
+diff --git a/grub-core/lib/libtasn1-grub/lib/coding.c b/grub-core/lib/libtasn1-grub/lib/coding.c
+index ea5bc370e..5d03bca9d 100644
+--- a/grub-core/lib/libtasn1-grub/lib/coding.c
++++ b/grub-core/lib/libtasn1-grub/lib/coding.c
+@@ -30,11 +30,11 @@
+ #include "parser_aux.h"
+ #include <gstr.h>
+ #include "element.h"
+-#include "minmax.h"
+ #include <structure.h>
+ 
+ #define MAX_TAG_LEN 16
+ 
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /******************************************************/
+ /* Function : _asn1_error_description_value_not_found */
+ /* Description: creates the ErrorDescription string   */
+@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node,
+   Estrcat (ErrorDescription, "' not found");
+ 
+ }
++#endif
+ 
+ /**
+  * asn1_length_der:
+@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
+   return ASN1_SUCCESS;
+ }
+ 
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /******************************************************/
+ /* Function : _asn1_time_der                          */
+ /* Description: creates the DER coding for a TIME     */
+@@ -278,7 +280,7 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned char *der,
+ 
+   return ASN1_SUCCESS;
+ }
+-
++#endif
+ 
+ /*
+ void
+@@ -519,6 +521,7 @@ asn1_bit_der (const unsigned char *str, int bit_len,
+ }
+ 
+ 
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /******************************************************/
+ /* Function : _asn1_complete_explicit_tag             */
+ /* Description: add the length coding to the EXPLICIT */
+@@ -595,6 +598,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
+ 
+   return ASN1_SUCCESS;
+ }
++#endif
+ 
+ const tag_and_class_st _asn1_tags[] = {
+   [ASN1_ETYPE_GENERALSTRING] =
+@@ -647,6 +651,8 @@ const tag_and_class_st _asn1_tags[] = {
+ 
+ unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]);
+ 
++
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /******************************************************/
+ /* Function : _asn1_insert_tag_der                    */
+ /* Description: creates the DER coding of tags of one */
+@@ -1423,3 +1429,5 @@ error:
+   asn1_delete_structure (&node);
+   return err;
+ }
++
++#endif
+diff --git a/grub-core/lib/libtasn1-grub/lib/decoding.c b/grub-core/lib/libtasn1-grub/lib/decoding.c
+index b9245c486..bf9cb13ac 100644
+--- a/grub-core/lib/libtasn1-grub/lib/decoding.c
++++ b/grub-core/lib/libtasn1-grub/lib/decoding.c
+@@ -1620,6 +1620,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
+   return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription);
+ }
+ 
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /**
+  * asn1_der_decoding_element:
+  * @structure: pointer to an ASN1 structure
+@@ -1650,6 +1651,7 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
+ {
+   return asn1_der_decoding (structure, ider, len, errorDescription);
+ }
++#endif
+ 
+ /**
+  * asn1_der_decoding_startEnd:
+diff --git a/grub-core/lib/libtasn1-grub/lib/element.c b/grub-core/lib/libtasn1-grub/lib/element.c
+index d4c558e10..bc4c3c8d7 100644
+--- a/grub-core/lib/libtasn1-grub/lib/element.c
++++ b/grub-core/lib/libtasn1-grub/lib/element.c
+@@ -118,7 +118,7 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
+ 	value_out[k2 - k] = val[k2];
+     }
+ 
+-#if 0
++#if 0 /* GRUB SKIPPED IMPORTING */
+   printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
+   for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
+     printf (", vOut[%d]=%d", k, value_out[k]);
+@@ -191,7 +191,7 @@ _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache)
+   return ASN1_SUCCESS;
+ }
+ 
+-
++#if 0
+ /**
+  * asn1_write_value:
+  * @node_root: pointer to a structure
+@@ -646,7 +646,7 @@ asn1_write_value (asn1_node node_root, const char *name,
+ 
+   return ASN1_SUCCESS;
+ }
+-
++#endif
+ 
+ #define PUT_VALUE( ptr, ptr_size, data, data_size) \
+ 	*len = data_size; \
+diff --git a/grub-core/lib/libtasn1-grub/lib/errors.c b/grub-core/lib/libtasn1-grub/lib/errors.c
+index aef5dfe6f..2b2322152 100644
+--- a/grub-core/lib/libtasn1-grub/lib/errors.c
++++ b/grub-core/lib/libtasn1-grub/lib/errors.c
+@@ -57,6 +57,8 @@ static const libtasn1_error_entry error_algorithms[] = {
+   {0, 0}
+ };
+ 
++
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /**
+  * asn1_perror:
+  * @error: is an error returned by a libtasn1 function.
+@@ -73,6 +75,7 @@ asn1_perror (int error)
+   const char *str = asn1_strerror (error);
+   fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)");
+ }
++#endif
+ 
+ /**
+  * asn1_strerror:
+diff --git a/grub-core/lib/libtasn1-grub/lib/structure.c b/grub-core/lib/libtasn1-grub/lib/structure.c
+index 512dd601f..f5a947d57 100644
+--- a/grub-core/lib/libtasn1-grub/lib/structure.c
++++ b/grub-core/lib/libtasn1-grub/lib/structure.c
+@@ -76,7 +76,7 @@ _asn1_find_left (asn1_node_const node)
+   return node->left;
+ }
+ 
+-
++#if 0 /* GRUB SKIPPED IMPORTING */
+ int
+ _asn1_create_static_structure (asn1_node_const pointer,
+ 			       char *output_file_name, char *vector_name)
+@@ -155,7 +155,7 @@ _asn1_create_static_structure (asn1_node_const pointer,
+ 
+   return ASN1_SUCCESS;
+ }
+-
++#endif
+ 
+ /**
+  * asn1_array2tree:
+@@ -721,7 +721,7 @@ asn1_create_element (asn1_node_const definitions, const char *source_name,
+   return res;
+ }
+ 
+-
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /**
+  * asn1_print_structure:
+  * @out: pointer to the output file (e.g. stdout).
+@@ -1062,7 +1062,7 @@ asn1_print_structure (FILE * out, asn1_node_const structure, const char *name,
+ 	}
+     }
+ }
+-
++#endif
+ 
+ 
+ /**
+@@ -1158,6 +1158,7 @@ asn1_find_structure_from_oid (asn1_node_const definitions,
+   return NULL;			/* ASN1_ELEMENT_NOT_FOUND; */
+ }
+ 
++#if 0 /* GRUB SKIPPED IMPORTING */
+ /**
+  * asn1_copy_node:
+  * @dst: Destination asn1 node.
+@@ -1207,6 +1208,7 @@ asn1_copy_node (asn1_node dst, const char *dst_name,
+ 
+   return result;
+ }
++#endif
+ 
+ /**
+  * asn1_dup_node:
+diff --git a/grub-core/lib/libtasn1-grub/libtasn1.h b/grub-core/lib/libtasn1-grub/libtasn1.h
+index 51cc7879f..058ab27b0 100644
+--- a/grub-core/lib/libtasn1-grub/libtasn1.h
++++ b/grub-core/lib/libtasn1-grub/libtasn1.h
+@@ -318,6 +318,8 @@ extern "C"
+ /*  Functions definitions          */
+ /***********************************/
+ 
++/* These functions are not used in grub and should not be referenced. */
++# if 0 /* GRUB SKIPPED IMPORTING */
+   extern ASN1_API int
+     asn1_parser2tree (const char *file,
+ 		      asn1_node * definitions, char *error_desc);
+@@ -326,14 +328,17 @@ extern "C"
+     asn1_parser2array (const char *inputFileName,
+ 		       const char *outputFileName,
+ 		       const char *vectorName, char *error_desc);
++# endif
+ 
+   extern ASN1_API int
+     asn1_array2tree (const asn1_static_node * array,
+ 		     asn1_node * definitions, char *errorDescription);
+ 
++# if 0 /* GRUB SKIPPED IMPORTING */
+   extern ASN1_API void
+     asn1_print_structure (FILE * out, asn1_node_const structure,
+ 			  const char *name, int mode);
++# endif
+ 
+   extern ASN1_API int
+     asn1_create_element (asn1_node_const definitions,
+@@ -347,9 +352,11 @@ extern "C"
+   extern ASN1_API int
+     asn1_delete_element (asn1_node structure, const char *element_name);
+ 
++# if 0 /* GRUB SKIPPED IMPORTING */
+   extern ASN1_API int
+     asn1_write_value (asn1_node node_root, const char *name,
+ 		      const void *ivalue, int len);
++# endif
+ 
+   extern ASN1_API int
+     asn1_read_value (asn1_node_const root, const char *name,
+@@ -366,9 +373,11 @@ extern "C"
+     asn1_number_of_elements (asn1_node_const element, const char *name,
+ 			     int *num);
+ 
++# if 0 /* GRUB SKIPPED IMPORTING */
+   extern ASN1_API int
+     asn1_der_coding (asn1_node_const element, const char *name,
+ 		     void *ider, int *len, char *ErrorDescription);
++# endif
+ 
+   extern ASN1_API int
+     asn1_der_decoding2 (asn1_node * element, const void *ider,
+@@ -379,6 +388,7 @@ extern "C"
+     asn1_der_decoding (asn1_node * element, const void *ider,
+ 		       int ider_len, char *errorDescription);
+ 
++# if 0 /* GRUB SKIPPED IMPORTING */
+ /* Do not use. Use asn1_der_decoding() instead. */
+   extern ASN1_API int
+     asn1_der_decoding_element (asn1_node * structure,
+@@ -386,6 +396,7 @@ extern "C"
+ 			       const void *ider, int len,
+ 			       char *errorDescription)
+     _ASN1_GCC_ATTR_DEPRECATED;
++# endif
+ 
+   extern ASN1_API int
+     asn1_der_decoding_startEnd (asn1_node element,
+@@ -411,12 +422,16 @@ extern "C"
+ 							    const char
+ 							    *oidValue);
+ 
++# if 0 /* GRUB SKIPPED IMPORTING */
+     __LIBTASN1_PURE__
+     extern ASN1_API const char *asn1_check_version (const char *req_version);
++# endif
+ 
+   __LIBTASN1_PURE__ extern ASN1_API const char *asn1_strerror (int error);
+ 
++# if 0 /* GRUB SKIPPED IMPORTING */
+   extern ASN1_API void asn1_perror (int error);
++# endif
+ 
+ # define ASN1_MAX_TAG_SIZE 4
+ # define ASN1_MAX_LENGTH_SIZE 9
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0002-libtasn1-replace-strcat-with-strcpy-in-_asn1_str_cat.patch b/grub-core/lib/libtasn1-patches/0002-libtasn1-replace-strcat-with-strcpy-in-_asn1_str_cat.patch
new file mode 100644
index 0000000..908016d
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0002-libtasn1-replace-strcat-with-strcpy-in-_asn1_str_cat.patch
@@ -0,0 +1,33 @@
+From 93453558fbe34634096770933b3dc40c9199dfb4 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Tue, 20 Aug 2024 16:14:51 +0800
+Subject: [PATCH 02/13] libtasn1: replace strcat() with strcpy() in
+ _asn1_str_cat()
+
+strcat() is not available in GRUB. This commit replaces strcat() with
+strcpy() in _asn1_str_cat() as the preparation to replace other strcat()
+with the bounds-checking _asn1_str_cat().
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/libtasn1-grub/lib/gstr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/lib/libtasn1-grub/lib/gstr.c b/grub-core/lib/libtasn1-grub/lib/gstr.c
+index eef419554..a9c16f5d3 100644
+--- a/grub-core/lib/libtasn1-grub/lib/gstr.c
++++ b/grub-core/lib/libtasn1-grub/lib/gstr.c
+@@ -36,7 +36,7 @@ _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src)
+ 
+   if (dest_tot_size - dest_size > str_size)
+     {
+-      strcat (dest, src);
++      strcpy (dest + dest_size, src);
+     }
+   else
+     {
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0003-libtasn1-replace-strcat-with-_asn1_str_cat.patch b/grub-core/lib/libtasn1-patches/0003-libtasn1-replace-strcat-with-_asn1_str_cat.patch
new file mode 100644
index 0000000..d92ae15
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0003-libtasn1-replace-strcat-with-_asn1_str_cat.patch
@@ -0,0 +1,71 @@
+From b5efa707619fde1921a3cbd83f4ee95a7d995fa0 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Tue, 20 Aug 2024 16:26:45 +0800
+Subject: [PATCH 03/13] libtasn1: replace strcat() with _asn1_str_cat()
+
+strcat() is not available in GRUB. This commit replaces strcat() and
+_asn1_strcat() with the bounds-checking _asn1_str_cat().
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/libtasn1-grub/lib/decoding.c | 8 ++++----
+ grub-core/lib/libtasn1-grub/lib/element.c  | 2 +-
+ grub-core/lib/libtasn1-grub/lib/int.h      | 1 -
+ 3 files changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/lib/libtasn1-grub/lib/decoding.c b/grub-core/lib/libtasn1-grub/lib/decoding.c
+index bf9cb13ac..51859fe36 100644
+--- a/grub-core/lib/libtasn1-grub/lib/decoding.c
++++ b/grub-core/lib/libtasn1-grub/lib/decoding.c
+@@ -2016,8 +2016,8 @@ asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element,
+ 	  (p2->type & CONST_ASSIGN))
+ 	{
+ 	  strcpy (name, definitions->name);
+-	  strcat (name, ".");
+-	  strcat (name, p2->name);
++	  _asn1_str_cat (name, sizeof (name), ".");
++	  _asn1_str_cat (name, sizeof (name), p2->name);
+ 
+ 	  len = sizeof (value);
+ 	  result = asn1_read_value (definitions, name, value, &len);
+@@ -2034,8 +2034,8 @@ asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element,
+ 	      if (p2)
+ 		{
+ 		  strcpy (name, definitions->name);
+-		  strcat (name, ".");
+-		  strcat (name, p2->name);
++		  _asn1_str_cat (name, sizeof (name), ".");
++		  _asn1_str_cat (name, sizeof (name), p2->name);
+ 
+ 		  result = asn1_create_element (definitions, name, &aux);
+ 		  if (result == ASN1_SUCCESS)
+diff --git a/grub-core/lib/libtasn1-grub/lib/element.c b/grub-core/lib/libtasn1-grub/lib/element.c
+index bc4c3c8d7..8694fecb9 100644
+--- a/grub-core/lib/libtasn1-grub/lib/element.c
++++ b/grub-core/lib/libtasn1-grub/lib/element.c
+@@ -688,7 +688,7 @@ asn1_write_value (asn1_node node_root, const char *name,
+                 return ASN1_MEM_ERROR; \
+         } else { \
+                 /* this strcat is checked */ \
+-                if (ptr) _asn1_strcat (ptr, data); \
++                if (ptr) _asn1_str_cat ((char *)ptr, ptr_size, (const char *)data); \
+         }
+ 
+ /**
+diff --git a/grub-core/lib/libtasn1-grub/lib/int.h b/grub-core/lib/libtasn1-grub/lib/int.h
+index d94d51c8c..cadd80df6 100644
+--- a/grub-core/lib/libtasn1-grub/lib/int.h
++++ b/grub-core/lib/libtasn1-grub/lib/int.h
+@@ -115,7 +115,6 @@ extern const tag_and_class_st _asn1_tags[];
+ # define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b)
+ # define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b)
+ # define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b)
+-# define _asn1_strcat(a,b) strcat((char *)a, (const char *)b)
+ 
+ # if SIZEOF_UNSIGNED_LONG_INT == 8
+ #  define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b)
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0004-libtasn1-adjust-the-header-paths-in-libtasn1.h.patch b/grub-core/lib/libtasn1-patches/0004-libtasn1-adjust-the-header-paths-in-libtasn1.h.patch
new file mode 100644
index 0000000..a5d5be4
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0004-libtasn1-adjust-the-header-paths-in-libtasn1.h.patch
@@ -0,0 +1,39 @@
+From 24036474fab426917507fcadc85a83fa0b1cef3b Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Tue, 25 Jun 2024 16:30:40 +0800
+Subject: [PATCH 04/13] libtasn1: adjust the header paths in libtasn1.h
+
+Since libtasn1.h is the header to be included by users, including the
+standard POSIX headers in libtasn1.h would force the user to add the
+CFLAGS/CPPFLAGS for the POSIX headers.
+
+This commit adjusts the header paths to use the grub headers instead of
+the standard POSIX headers, so that users only need to include
+libtasn1.h to use libtasn1 functions.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/libtasn1-grub/libtasn1.h | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/grub-core/lib/libtasn1-grub/libtasn1.h b/grub-core/lib/libtasn1-grub/libtasn1.h
+index 058ab27b0..7d64b6ab7 100644
+--- a/grub-core/lib/libtasn1-grub/libtasn1.h
++++ b/grub-core/lib/libtasn1-grub/libtasn1.h
+@@ -54,9 +54,8 @@
+ #  define __LIBTASN1_PURE__
+ # endif
+ 
+-# include <sys/types.h>
+-# include <time.h>
+-# include <stdio.h>		/* for FILE* */
++# include <grub/types.h>
++# include <grub/time.h>
+ 
+ # ifdef __cplusplus
+ extern "C"
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0005-libtasn1-Use-grub_divmod64-for-division.patch b/grub-core/lib/libtasn1-patches/0005-libtasn1-Use-grub_divmod64-for-division.patch
new file mode 100644
index 0000000..201df10
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0005-libtasn1-Use-grub_divmod64-for-division.patch
@@ -0,0 +1,31 @@
+From 5ee39f0bb8b0b713f766c0fc83439d83ac2c0bf2 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Tue, 25 Jun 2024 16:32:50 +0800
+Subject: [PATCH 05/13] libtasn1: Use grub_divmod64() for division
+
+Replace a 64-bit division with a call to grub_divmod64(), preventing
+creation of __udivdi3() calls on 32-bit platforms.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/libtasn1-grub/lib/parser_aux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/lib/libtasn1-grub/lib/parser_aux.c b/grub-core/lib/libtasn1-grub/lib/parser_aux.c
+index c05bd2339..e4e4c0556 100644
+--- a/grub-core/lib/libtasn1-grub/lib/parser_aux.c
++++ b/grub-core/lib/libtasn1-grub/lib/parser_aux.c
+@@ -632,7 +632,7 @@ _asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE])
+   count = 0;
+   do
+     {
+-      d = val / 10;
++      d = grub_divmod64(val, 10, NULL);
+       r = val - d * 10;
+       temp[start + count] = '0' + (char) r;
+       count++;
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0006-libtasn1-fix-the-potential-buffer-overrun.patch b/grub-core/lib/libtasn1-patches/0006-libtasn1-fix-the-potential-buffer-overrun.patch
new file mode 100644
index 0000000..f9f45ae
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0006-libtasn1-fix-the-potential-buffer-overrun.patch
@@ -0,0 +1,36 @@
+From f629f58b01b3e88052be5e50f51a667181203e05 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Mon, 8 Apr 2024 14:57:21 +0800
+Subject: [PATCH 06/13] libtasn1: fix the potential buffer overrun
+
+In _asn1_tag_der(), the first while loop for the long form may end up
+with a 'k' value with 'ASN1_MAX_TAG_SIZE' and cause the buffer overrun
+in the second while loop. This commit tweaks the conditional check to
+avoid producing a too large 'k'.
+
+This is a quick fix and may differ from the official upstream fix.
+
+libtasn1 issue: https://gitlab.com/gnutls/libtasn1/-/issues/49
+
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/lib/libtasn1-grub/lib/coding.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/grub-core/lib/libtasn1-grub/lib/coding.c b/grub-core/lib/libtasn1-grub/lib/coding.c
+index 5d03bca9d..0458829a5 100644
+--- a/grub-core/lib/libtasn1-grub/lib/coding.c
++++ b/grub-core/lib/libtasn1-grub/lib/coding.c
+@@ -143,7 +143,7 @@ _asn1_tag_der (unsigned char class, unsigned int tag_value,
+ 	  temp[k++] = tag_value & 0x7F;
+ 	  tag_value >>= 7;
+ 
+-	  if (k > ASN1_MAX_TAG_SIZE - 1)
++	  if (k >= ASN1_MAX_TAG_SIZE - 1)
+ 	    break;		/* will not encode larger tags */
+ 	}
+       *ans_len = k + 1;
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0007-asn1_test-include-asn1_test.h-only.patch b/grub-core/lib/libtasn1-patches/0007-asn1_test-include-asn1_test.h-only.patch
new file mode 100644
index 0000000..29b9313
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0007-asn1_test-include-asn1_test.h-only.patch
@@ -0,0 +1,164 @@
+From 9cc63a71d6772947127d4d77e135d5fda68ccb8d Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Fri, 16 Aug 2024 14:10:21 +0800
+Subject: [PATCH 07/13] asn1_test: include asn1_test.h only
+
+This commit removes all the headers and only uses asn1_test.h.
+To avoid including int.h from grub-core/lib/libtasn1-grub/lib/,
+CONST_DOWN is defined in reproducers.c.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/tests/asn1/tests/CVE-2018-1000654.c   | 4 +---
+ grub-core/tests/asn1/tests/Test_overflow.c      | 7 +------
+ grub-core/tests/asn1/tests/Test_simple.c        | 6 +-----
+ grub-core/tests/asn1/tests/Test_strings.c       | 6 +-----
+ grub-core/tests/asn1/tests/object-id-decoding.c | 6 +-----
+ grub-core/tests/asn1/tests/object-id-encoding.c | 6 +-----
+ grub-core/tests/asn1/tests/octet-string.c       | 6 +-----
+ grub-core/tests/asn1/tests/reproducers.c        | 8 ++------
+ 8 files changed, 9 insertions(+), 40 deletions(-)
+
+diff --git a/grub-core/tests/asn1/tests/CVE-2018-1000654.c b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+index 0c22b7012..98c2a8b8c 100644
+--- a/grub-core/tests/asn1/tests/CVE-2018-1000654.c
++++ b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+@@ -22,9 +22,7 @@
+ /* Description: reproducer for CVE-2018-1000654			*/
+ /****************************************************************/
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
++#include "asn1_test.h"
+ #include "CVE-2018-1000654-1_asn1_tab.h"
+ #include "CVE-2018-1000654-2_asn1_tab.h"
+ 
+diff --git a/grub-core/tests/asn1/tests/Test_overflow.c b/grub-core/tests/asn1/tests/Test_overflow.c
+index c61dea4bb..73e9d8c68 100644
+--- a/grub-core/tests/asn1/tests/Test_overflow.c
++++ b/grub-core/tests/asn1/tests/Test_overflow.c
+@@ -20,12 +20,7 @@
+ 
+ /* Written by Simon Josefsson */
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-#include <limits.h>
+-
+-#include "libtasn1.h"
++#include "asn1_test.h"
+ 
+ int
+ main (int argc, char **argv)
+diff --git a/grub-core/tests/asn1/tests/Test_simple.c b/grub-core/tests/asn1/tests/Test_simple.c
+index 6cd07e069..3aa8ce21b 100644
+--- a/grub-core/tests/asn1/tests/Test_simple.c
++++ b/grub-core/tests/asn1/tests/Test_simple.c
+@@ -20,11 +20,7 @@
+  *
+  */
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-
+-#include "libtasn1.h"
++#include "asn1_test.h"
+ 
+ struct tv
+ {
+diff --git a/grub-core/tests/asn1/tests/Test_strings.c b/grub-core/tests/asn1/tests/Test_strings.c
+index 27f7215e1..c49229af9 100644
+--- a/grub-core/tests/asn1/tests/Test_strings.c
++++ b/grub-core/tests/asn1/tests/Test_strings.c
+@@ -20,11 +20,7 @@
+  *
+  */
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-
+-#include "libtasn1.h"
++#include "asn1_test.h"
+ 
+ struct tv
+ {
+diff --git a/grub-core/tests/asn1/tests/object-id-decoding.c b/grub-core/tests/asn1/tests/object-id-decoding.c
+index 06a6c52a2..0a77db752 100644
+--- a/grub-core/tests/asn1/tests/object-id-decoding.c
++++ b/grub-core/tests/asn1/tests/object-id-decoding.c
+@@ -18,11 +18,7 @@
+  *
+  */
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-
+-#include "libtasn1.h"
++#include "asn1_test.h"
+ 
+ struct tv
+ {
+diff --git a/grub-core/tests/asn1/tests/object-id-encoding.c b/grub-core/tests/asn1/tests/object-id-encoding.c
+index 1a3396986..e32835830 100644
+--- a/grub-core/tests/asn1/tests/object-id-encoding.c
++++ b/grub-core/tests/asn1/tests/object-id-encoding.c
+@@ -18,11 +18,7 @@
+  *
+  */
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-
+-#include "libtasn1.h"
++#include "asn1_test.h"
+ 
+ struct tv
+ {
+diff --git a/grub-core/tests/asn1/tests/octet-string.c b/grub-core/tests/asn1/tests/octet-string.c
+index 69eb18a62..8e803af41 100644
+--- a/grub-core/tests/asn1/tests/octet-string.c
++++ b/grub-core/tests/asn1/tests/octet-string.c
+@@ -20,11 +20,7 @@
+  *
+  */
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-
+-#include "libtasn1.h"
++#include "asn1_test.h"
+ 
+ struct tv
+ {
+diff --git a/grub-core/tests/asn1/tests/reproducers.c b/grub-core/tests/asn1/tests/reproducers.c
+index a09d8b021..ce24e0991 100644
+--- a/grub-core/tests/asn1/tests/reproducers.c
++++ b/grub-core/tests/asn1/tests/reproducers.c
+@@ -22,13 +22,9 @@
+ /* Description: run reproducers for several fixed issues        */
+ /****************************************************************/
+ 
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
++#include "asn1_test.h"
+ 
+-#include <libtasn1.h>
+-
+-#include <int.h>
++#define CONST_DOWN        (1U<<29)
+ 
+ /* produces endless loop (fixed by d4b624b2):
+  * The following translates into a single node with all pointers
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0008-asn1_test-rename-the-main-functions-to-the-test-name.patch b/grub-core/lib/libtasn1-patches/0008-asn1_test-rename-the-main-functions-to-the-test-name.patch
new file mode 100644
index 0000000..bd34b47
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0008-asn1_test-rename-the-main-functions-to-the-test-name.patch
@@ -0,0 +1,129 @@
+From c0f39b9eae745a36c44fc0dfa106675405ea154f Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Fri, 16 Aug 2024 14:18:44 +0800
+Subject: [PATCH 08/13] asn1_test: rename the main functions to the test names
+
+This commit changes the main functions in the testcases to the test
+names so that the real 'main' test function can invokes them.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/tests/asn1/tests/CVE-2018-1000654.c   | 2 +-
+ grub-core/tests/asn1/tests/Test_overflow.c      | 2 +-
+ grub-core/tests/asn1/tests/Test_simple.c        | 2 +-
+ grub-core/tests/asn1/tests/Test_strings.c       | 2 +-
+ grub-core/tests/asn1/tests/object-id-decoding.c | 2 +-
+ grub-core/tests/asn1/tests/object-id-encoding.c | 2 +-
+ grub-core/tests/asn1/tests/octet-string.c       | 2 +-
+ grub-core/tests/asn1/tests/reproducers.c        | 2 +-
+ 8 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/tests/asn1/tests/CVE-2018-1000654.c b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+index 98c2a8b8c..a935ab541 100644
+--- a/grub-core/tests/asn1/tests/CVE-2018-1000654.c
++++ b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+@@ -27,7 +27,7 @@
+ #include "CVE-2018-1000654-2_asn1_tab.h"
+ 
+ int
+-main (int argc, char *argv[])
++test_CVE_2018_1000654 (void)
+ {
+   int result, verbose = 0;
+   asn1_node definitions = NULL;
+diff --git a/grub-core/tests/asn1/tests/Test_overflow.c b/grub-core/tests/asn1/tests/Test_overflow.c
+index 73e9d8c68..bc28d0826 100644
+--- a/grub-core/tests/asn1/tests/Test_overflow.c
++++ b/grub-core/tests/asn1/tests/Test_overflow.c
+@@ -23,7 +23,7 @@
+ #include "asn1_test.h"
+ 
+ int
+-main (int argc, char **argv)
++test_overflow (void)
+ {
+   /* Test that values larger than long are rejected.  This has worked
+      fine with all versions of libtasn1. */
+diff --git a/grub-core/tests/asn1/tests/Test_simple.c b/grub-core/tests/asn1/tests/Test_simple.c
+index 3aa8ce21b..12993bfba 100644
+--- a/grub-core/tests/asn1/tests/Test_simple.c
++++ b/grub-core/tests/asn1/tests/Test_simple.c
+@@ -73,7 +73,7 @@ static const struct tv tv[] = {
+ };
+ 
+ int
+-main (int argc, char *argv[])
++test_simple (void)
+ {
+   int result;
+   unsigned char der[100];
+diff --git a/grub-core/tests/asn1/tests/Test_strings.c b/grub-core/tests/asn1/tests/Test_strings.c
+index c49229af9..2538f2558 100644
+--- a/grub-core/tests/asn1/tests/Test_strings.c
++++ b/grub-core/tests/asn1/tests/Test_strings.c
+@@ -70,7 +70,7 @@ static const struct tv ber[] = {
+ };
+ 
+ int
+-main (int argc, char *argv[])
++test_strings (void)
+ {
+   int ret;
+   unsigned char tl[ASN1_MAX_TL_SIZE];
+diff --git a/grub-core/tests/asn1/tests/object-id-decoding.c b/grub-core/tests/asn1/tests/object-id-decoding.c
+index 0a77db752..fdbb8ea21 100644
+--- a/grub-core/tests/asn1/tests/object-id-decoding.c
++++ b/grub-core/tests/asn1/tests/object-id-decoding.c
+@@ -70,7 +70,7 @@ static const struct tv tv[] = {
+ };
+ 
+ int
+-main (int argc, char *argv[])
++test_object_id_decoding (void)
+ {
+   char str[128];
+   int ret, ret_len;
+diff --git a/grub-core/tests/asn1/tests/object-id-encoding.c b/grub-core/tests/asn1/tests/object-id-encoding.c
+index e32835830..a497015e3 100644
+--- a/grub-core/tests/asn1/tests/object-id-encoding.c
++++ b/grub-core/tests/asn1/tests/object-id-encoding.c
+@@ -80,7 +80,7 @@ static const struct tv tv[] = {
+ };
+ 
+ int
+-main (int argc, char *argv[])
++test_object_id_encoding (void)
+ {
+   unsigned char der[128];
+   int ret, der_len, i, j;
+diff --git a/grub-core/tests/asn1/tests/octet-string.c b/grub-core/tests/asn1/tests/octet-string.c
+index 8e803af41..8c49c6e0c 100644
+--- a/grub-core/tests/asn1/tests/octet-string.c
++++ b/grub-core/tests/asn1/tests/octet-string.c
+@@ -108,7 +108,7 @@ static const struct tv tv[] = {
+ };
+ 
+ int
+-main (int argc, char *argv[])
++test_octet_string (void)
+ {
+   unsigned char str[100];
+   unsigned char der[100];
+diff --git a/grub-core/tests/asn1/tests/reproducers.c b/grub-core/tests/asn1/tests/reproducers.c
+index ce24e0991..e843b74b9 100644
+--- a/grub-core/tests/asn1/tests/reproducers.c
++++ b/grub-core/tests/asn1/tests/reproducers.c
+@@ -49,7 +49,7 @@ const asn1_static_node tab[] = {
+ };
+ 
+ int
+-main (int argc, char *argv[])
++test_reproducers (void)
+ {
+   int result, verbose = 0;
+   asn1_node definitions = NULL;
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0009-asn1_test-return-either-0-or-1-to-reflect-the-result.patch b/grub-core/lib/libtasn1-patches/0009-asn1_test-return-either-0-or-1-to-reflect-the-result.patch
new file mode 100644
index 0000000..b76942d
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0009-asn1_test-return-either-0-or-1-to-reflect-the-result.patch
@@ -0,0 +1,78 @@
+From 103ec39de5277e2683099017959415e107b885a5 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Fri, 16 Aug 2024 15:32:39 +0800
+Subject: [PATCH 09/13] asn1_test: return either 0 or 1 to reflect the results
+
+Some testcases use exit() to end the test. Since all the asn1 testcases
+are invoked as functions, this commit replaces exit() with return to
+reflect the test results, so that the main test function can check the
+results.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/tests/asn1/tests/CVE-2018-1000654.c | 6 +++---
+ grub-core/tests/asn1/tests/reproducers.c      | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/grub-core/tests/asn1/tests/CVE-2018-1000654.c b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+index a935ab541..2085b3cd3 100644
+--- a/grub-core/tests/asn1/tests/CVE-2018-1000654.c
++++ b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+@@ -45,7 +45,7 @@ test_CVE_2018_1000654 (void)
+     {
+       asn1_perror (result);
+       printf ("ErrorDescription = %s\n\n", errorDescription);
+-      exit (1);
++      return 1;
+     }
+ 
+   asn1_delete_structure (&definitions);
+@@ -59,12 +59,12 @@ test_CVE_2018_1000654 (void)
+     {
+       asn1_perror (result);
+       printf ("ErrorDescription = %s\n\n", errorDescription);
+-      exit (1);
++      return 1;
+     }
+ 
+   asn1_delete_structure (&definitions);
+ 
+   if (verbose)
+     printf ("Success\n");
+-  exit (0);
++  return 0;
+ }
+diff --git a/grub-core/tests/asn1/tests/reproducers.c b/grub-core/tests/asn1/tests/reproducers.c
+index e843b74b9..54a243d51 100644
+--- a/grub-core/tests/asn1/tests/reproducers.c
++++ b/grub-core/tests/asn1/tests/reproducers.c
+@@ -63,7 +63,7 @@ test_reproducers (void)
+     {
+       asn1_perror (result);
+       printf ("ErrorDescription = %s\n\n", errorDescription);
+-      exit (EXIT_FAILURE);
++      return 1;
+     }
+ 
+   asn1_delete_structure (&definitions);
+@@ -74,7 +74,7 @@ test_reproducers (void)
+     {
+       asn1_perror (result);
+       printf ("ErrorDescription = %s\n\n", errorDescription);
+-      exit (EXIT_FAILURE);
++      return 1;
+     }
+ 
+   asn1_delete_structure (&definitions);
+@@ -82,5 +82,5 @@ test_reproducers (void)
+   if (verbose)
+     printf ("Success\n");
+ 
+-  exit (EXIT_SUCCESS);
++  return 0;
+ }
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch b/grub-core/lib/libtasn1-patches/0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch
new file mode 100644
index 0000000..2bd8ffb
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch
@@ -0,0 +1,173 @@
+From 759bc707a924f89b0d32ba7be2f54e100f1d57b7 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Fri, 16 Aug 2024 14:26:38 +0800
+Subject: [PATCH 10/13] asn1_test: remove 'verbose' and the unnecessary
+ printf()
+
+This commit removes the 'verbose' variables and the unnecessary printf()
+to simplify the output.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/tests/asn1/tests/CVE-2018-1000654.c | 11 +----
+ grub-core/tests/asn1/tests/Test_overflow.c    | 40 +++----------------
+ grub-core/tests/asn1/tests/reproducers.c      |  8 +---
+ 3 files changed, 7 insertions(+), 52 deletions(-)
+
+diff --git a/grub-core/tests/asn1/tests/CVE-2018-1000654.c b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+index 2085b3cd3..81448cde8 100644
+--- a/grub-core/tests/asn1/tests/CVE-2018-1000654.c
++++ b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+@@ -29,15 +29,10 @@
+ int
+ test_CVE_2018_1000654 (void)
+ {
+-  int result, verbose = 0;
++  int result;
+   asn1_node definitions = NULL;
+   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+ 
+-  if (argc > 1)
+-    verbose = 1;
+-
+-  printf ("Test 1\n");
+-
+   result =
+     asn1_array2tree (CVE_2018_1000654_1_asn1_tab, &definitions,
+ 		     errorDescription);
+@@ -50,8 +45,6 @@ test_CVE_2018_1000654 (void)
+ 
+   asn1_delete_structure (&definitions);
+ 
+-  printf ("Test 2\n");
+-
+   result =
+     asn1_array2tree (CVE_2018_1000654_2_asn1_tab, &definitions,
+ 		     errorDescription);
+@@ -64,7 +57,5 @@ test_CVE_2018_1000654 (void)
+ 
+   asn1_delete_structure (&definitions);
+ 
+-  if (verbose)
+-    printf ("Success\n");
+   return 0;
+ }
+diff --git a/grub-core/tests/asn1/tests/Test_overflow.c b/grub-core/tests/asn1/tests/Test_overflow.c
+index bc28d0826..9f9578a1f 100644
+--- a/grub-core/tests/asn1/tests/Test_overflow.c
++++ b/grub-core/tests/asn1/tests/Test_overflow.c
+@@ -27,11 +27,6 @@ test_overflow (void)
+ {
+   /* Test that values larger than long are rejected.  This has worked
+      fine with all versions of libtasn1. */
+-  int verbose = 0;
+-
+-  if (argc > 1)
+-    verbose = 1;
+-
+   {
+     unsigned char der[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
+     long l;
+@@ -39,12 +34,7 @@ test_overflow (void)
+ 
+     l = asn1_get_length_der (der, sizeof der, &len);
+ 
+-    if (l == -2L)
+-      {
+-	if (verbose)
+-	  puts ("OK: asn1_get_length_der bignum");
+-      }
+-    else
++    if (l != -2L)
+       {
+ 	printf ("ERROR: asn1_get_length_der bignum (l %ld len %d)\n", l, len);
+ 	return 1;
+@@ -65,12 +55,7 @@ test_overflow (void)
+ 
+       l = asn1_get_length_der (der, der_len, &len);
+ 
+-      if (l == -2L)
+-	{
+-	  if (verbose)
+-	    puts ("OK: asn1_get_length_der intnum");
+-	}
+-      else
++      if (l != -2L)
+ 	{
+ 	  printf ("ERROR: asn1_get_length_der intnum (l %ld len %d)\n", l,
+ 		  len);
+@@ -92,12 +77,7 @@ test_overflow (void)
+     der_len = sizeof (der);
+     l = asn1_get_length_der (der, der_len, &len);
+ 
+-    if (l == -4L)
+-      {
+-	if (verbose)
+-	  puts ("OK: asn1_get_length_der overflow-small");
+-      }
+-    else
++    if (l != -4L)
+       {
+ 	printf ("ERROR: asn1_get_length_der overflow-small (l %ld len %d)\n",
+ 		l, len);
+@@ -119,12 +99,7 @@ test_overflow (void)
+     der_len = sizeof (der);
+     l = asn1_get_length_der (der, der_len, &len);
+ 
+-    if (l == -4L)
+-      {
+-	if (verbose)
+-	  puts ("OK: asn1_get_length_der overflow-large1");
+-      }
+-    else
++    if (l != -4L)
+       {
+ 	printf ("ERROR: asn1_get_length_der overflow-large1 (l %ld len %d)\n",
+ 		l, len);
+@@ -146,12 +121,7 @@ test_overflow (void)
+     der_len = sizeof (der);
+     l = asn1_get_length_der (der, der_len, &len);
+ 
+-    if (l == -2L)
+-      {
+-	if (verbose)
+-	  puts ("OK: asn1_get_length_der overflow-large2");
+-      }
+-    else
++    if (l != -2L)
+       {
+ 	printf ("ERROR: asn1_get_length_der overflow-large2 (l %ld len %d)\n",
+ 		l, len);
+diff --git a/grub-core/tests/asn1/tests/reproducers.c b/grub-core/tests/asn1/tests/reproducers.c
+index 54a243d51..fa3cea762 100644
+--- a/grub-core/tests/asn1/tests/reproducers.c
++++ b/grub-core/tests/asn1/tests/reproducers.c
+@@ -51,13 +51,10 @@ const asn1_static_node tab[] = {
+ int
+ test_reproducers (void)
+ {
+-  int result, verbose = 0;
++  int result;
+   asn1_node definitions = NULL;
+   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+ 
+-  if (argc > 1)
+-    verbose = 1;
+-
+   result = asn1_array2tree (endless_asn1_tab, &definitions, errorDescription);
+   if (result != ASN1_SUCCESS)
+     {
+@@ -79,8 +76,5 @@ test_reproducers (void)
+ 
+   asn1_delete_structure (&definitions);
+ 
+-  if (verbose)
+-    printf ("Success\n");
+-
+   return 0;
+ }
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0011-asn1_test-print-the-error-messages-with-grub_printf.patch b/grub-core/lib/libtasn1-patches/0011-asn1_test-print-the-error-messages-with-grub_printf.patch
new file mode 100644
index 0000000..aadd362
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0011-asn1_test-print-the-error-messages-with-grub_printf.patch
@@ -0,0 +1,485 @@
+From af5f0a651de09e44e78177b988857acd3208c4b6 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Fri, 16 Aug 2024 15:00:42 +0800
+Subject: [PATCH 11/13] asn1_test: print the error messages with grub_printf()
+
+This commit replaces printf() and fprintf() with grub_printf() to print
+the error messages for the testcases. Besides, asn1_strerror() is used
+to convert the result code to strings instead of asn1_perror().
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/tests/asn1/tests/CVE-2018-1000654.c |  8 +--
+ grub-core/tests/asn1/tests/Test_overflow.c    | 14 ++---
+ grub-core/tests/asn1/tests/Test_simple.c      | 21 ++++----
+ grub-core/tests/asn1/tests/Test_strings.c     | 21 +++-----
+ .../tests/asn1/tests/object-id-decoding.c     | 16 +++---
+ .../tests/asn1/tests/object-id-encoding.c     | 26 ++++-----
+ grub-core/tests/asn1/tests/octet-string.c     | 54 ++++++++-----------
+ grub-core/tests/asn1/tests/reproducers.c      |  6 +--
+ 8 files changed, 67 insertions(+), 99 deletions(-)
+
+diff --git a/grub-core/tests/asn1/tests/CVE-2018-1000654.c b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+index 81448cde8..b78667900 100644
+--- a/grub-core/tests/asn1/tests/CVE-2018-1000654.c
++++ b/grub-core/tests/asn1/tests/CVE-2018-1000654.c
+@@ -38,8 +38,8 @@ test_CVE_2018_1000654 (void)
+ 		     errorDescription);
+   if (result != ASN1_RECURSION)
+     {
+-      asn1_perror (result);
+-      printf ("ErrorDescription = %s\n\n", errorDescription);
++      grub_printf ("Error: %s\nErrorDescription = %s\n\n",
++		   asn1_strerror (result), errorDescription);
+       return 1;
+     }
+ 
+@@ -50,8 +50,8 @@ test_CVE_2018_1000654 (void)
+ 		     errorDescription);
+   if (result != ASN1_RECURSION)
+     {
+-      asn1_perror (result);
+-      printf ("ErrorDescription = %s\n\n", errorDescription);
++      grub_printf ("Error: %s\nErrorDescription = %s\n\n",
++		   asn1_strerror (result), errorDescription);
+       return 1;
+     }
+ 
+diff --git a/grub-core/tests/asn1/tests/Test_overflow.c b/grub-core/tests/asn1/tests/Test_overflow.c
+index 9f9578a1f..ffac8507a 100644
+--- a/grub-core/tests/asn1/tests/Test_overflow.c
++++ b/grub-core/tests/asn1/tests/Test_overflow.c
+@@ -36,7 +36,7 @@ test_overflow (void)
+ 
+     if (l != -2L)
+       {
+-	printf ("ERROR: asn1_get_length_der bignum (l %ld len %d)\n", l, len);
++	grub_printf ("ERROR: asn1_get_length_der bignum (l %ld len %d)\n", l, len);
+ 	return 1;
+       }
+   }
+@@ -57,8 +57,7 @@ test_overflow (void)
+ 
+       if (l != -2L)
+ 	{
+-	  printf ("ERROR: asn1_get_length_der intnum (l %ld len %d)\n", l,
+-		  len);
++	  grub_printf ("ERROR: asn1_get_length_der intnum (l %ld len %d)\n", l, len);
+ 	  return 1;
+ 	}
+     }
+@@ -79,8 +78,7 @@ test_overflow (void)
+ 
+     if (l != -4L)
+       {
+-	printf ("ERROR: asn1_get_length_der overflow-small (l %ld len %d)\n",
+-		l, len);
++	grub_printf ("ERROR: asn1_get_length_der overflow-small (l %ld len %d)\n", l, len);
+ 	return 1;
+       }
+   }
+@@ -101,8 +99,7 @@ test_overflow (void)
+ 
+     if (l != -4L)
+       {
+-	printf ("ERROR: asn1_get_length_der overflow-large1 (l %ld len %d)\n",
+-		l, len);
++	grub_printf ("ERROR: asn1_get_length_der overflow-large1 (l %ld len %d)\n", l, len);
+ 	return 1;
+       }
+   }
+@@ -123,8 +120,7 @@ test_overflow (void)
+ 
+     if (l != -2L)
+       {
+-	printf ("ERROR: asn1_get_length_der overflow-large2 (l %ld len %d)\n",
+-		l, len);
++	grub_printf ("ERROR: asn1_get_length_der overflow-large2 (l %ld len %d)\n", l, len);
+ 	return 1;
+       }
+   }
+diff --git a/grub-core/tests/asn1/tests/Test_simple.c b/grub-core/tests/asn1/tests/Test_simple.c
+index 12993bfba..dc70db191 100644
+--- a/grub-core/tests/asn1/tests/Test_simple.c
++++ b/grub-core/tests/asn1/tests/Test_simple.c
+@@ -94,7 +94,7 @@ test_simple (void)
+     result = asn1_encode_simple_der (etype, my_str, my_str_len, tl, &tl_len);
+     if (result != ASN1_VALUE_NOT_VALID)
+       {
+-	fprintf (stderr, "asn1_encode_simple_der out of range etype\n");
++	grub_printf ("asn1_encode_simple_der out of range etype\n");
+ 	return 1;
+       }
+   }
+@@ -105,7 +105,7 @@ test_simple (void)
+   result = asn1_get_bit_der (der, 0, &ret_len, str, str_size, &bit_len);
+   if (result != ASN1_GENERIC_ERROR)
+     {
+-      fprintf (stderr, "asn1_get_bit_der zero\n");
++      grub_printf ("asn1_get_bit_der zero\n");
+       return 1;
+     }
+ 
+@@ -129,7 +129,7 @@ test_simple (void)
+ 
+       if (der_len != tv[i].derlen || memcmp (der, tv[i].der, der_len) != 0)
+ 	{
+-	  fprintf (stderr, "asn1_bit_der iter %lu\n", (unsigned long) i);
++	  grub_printf ("asn1_bit_der iter %lu\n", (unsigned long) i);
+ 	  return 1;
+ 	}
+ 
+@@ -140,8 +140,7 @@ test_simple (void)
+       if (result != ASN1_SUCCESS || ret_len != tv[i].derlen
+ 	  || bit_len != tv[i].bitlen)
+ 	{
+-	  fprintf (stderr, "asn1_get_bit_der iter %lu, err: %d\n",
+-		   (unsigned long) i, result);
++	  grub_printf ("asn1_get_bit_der iter %lu, err: %d\n", (unsigned long) i, result);
+ 	  return 1;
+ 	}
+     }
+@@ -163,7 +162,7 @@ test_simple (void)
+   if (result != ASN1_SUCCESS || ret_len != 5
+       || bit_len != 18 || memcmp (str, "\x6e\x5d\xc0", 3) != 0)
+     {
+-      fprintf (stderr, "asn1_get_bit_der example\n");
++      grub_printf ("asn1_get_bit_der example\n");
+       return 1;
+     }
+ 
+@@ -171,7 +170,7 @@ test_simple (void)
+   asn1_bit_der (str, bit_len, der, &der_len);
+   if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+     {
+-      fprintf (stderr, "asn1_bit_der example roundtrip\n");
++      grub_printf ("asn1_bit_der example roundtrip\n");
+       return 1;
+     }
+ 
+@@ -184,7 +183,7 @@ test_simple (void)
+   if (result != ASN1_SUCCESS || ret_len != 5
+       || bit_len != 18 || memcmp (str, "\x6e\x5d\xe0", 3) != 0)
+     {
+-      fprintf (stderr, "asn1_get_bit_der example padded\n");
++      grub_printf ("asn1_get_bit_der example padded\n");
+       return 1;
+     }
+ 
+@@ -192,7 +191,7 @@ test_simple (void)
+   asn1_bit_der (str, bit_len, der, &der_len);
+   if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+     {
+-      fprintf (stderr, "asn1_bit_der example roundtrip\n");
++      grub_printf ("asn1_bit_der example roundtrip\n");
+       return 1;
+     }
+ 
+@@ -206,7 +205,7 @@ test_simple (void)
+   if (result != ASN1_SUCCESS || ret_len != 6
+       || bit_len != 18 || memcmp (str, "\x6e\x5d\xc0", 3) != 0)
+     {
+-      fprintf (stderr, "asn1_get_bit_der example long form\n");
++      grub_printf ("asn1_get_bit_der example long form\n");
+       return 1;
+     }
+ 
+@@ -214,7 +213,7 @@ test_simple (void)
+   asn1_bit_der (str, bit_len, der, &der_len);
+   if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+     {
+-      fprintf (stderr, "asn1_bit_der example roundtrip\n");
++      grub_printf ("asn1_bit_der example roundtrip\n");
+       return 1;
+     }
+ 
+diff --git a/grub-core/tests/asn1/tests/Test_strings.c b/grub-core/tests/asn1/tests/Test_strings.c
+index 2538f2558..65c30937f 100644
+--- a/grub-core/tests/asn1/tests/Test_strings.c
++++ b/grub-core/tests/asn1/tests/Test_strings.c
+@@ -89,17 +89,14 @@ test_strings (void)
+ 				    tl, &tl_len);
+       if (ret != ASN1_SUCCESS)
+ 	{
+-	  fprintf (stderr, "Encoding error in %u: %s\n", i,
+-		   asn1_strerror (ret));
++	  grub_printf ("Encoding error in %u: %s\n", i, asn1_strerror (ret));
+ 	  return 1;
+ 	}
+       der_len = tl_len + tv[i].str_len;
+ 
+       if (der_len != tv[i].der_len || memcmp (tl, tv[i].der, tl_len) != 0)
+ 	{
+-	  fprintf (stderr,
+-		   "DER encoding differs in %u! (size: %u, expected: %u)\n",
+-		   i, der_len, tv[i].der_len);
++	  grub_printf ("DER encoding differs in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].der_len);
+ 	  return 1;
+ 	}
+ 
+@@ -109,16 +106,13 @@ test_strings (void)
+ 				&str_len);
+       if (ret != ASN1_SUCCESS)
+ 	{
+-	  fprintf (stderr, "Decoding error in %u: %s\n", i,
+-		   asn1_strerror (ret));
++	  grub_printf ("Decoding error in %u: %s\n", i, asn1_strerror (ret));
+ 	  return 1;
+ 	}
+ 
+       if (str_len != tv[i].str_len || memcmp (str, tv[i].str, str_len) != 0)
+ 	{
+-	  fprintf (stderr,
+-		   "DER decoded data differ in %u! (size: %u, expected: %u)\n",
+-		   i, der_len, tv[i].str_len);
++	  grub_printf ("DER decoded data differ in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].str_len);
+ 	  return 1;
+ 	}
+     }
+@@ -132,16 +126,13 @@ test_strings (void)
+ 				&str_len, NULL);
+       if (ret != ASN1_SUCCESS)
+ 	{
+-	  fprintf (stderr, "BER decoding error in %u: %s\n", i,
+-		   asn1_strerror (ret));
++	  grub_printf ("BER decoding error in %u: %s\n", i, asn1_strerror (ret));
+ 	  return 1;
+ 	}
+ 
+       if (str_len != ber[i].str_len || memcmp (b, ber[i].str, str_len) != 0)
+ 	{
+-	  fprintf (stderr,
+-		   "BER decoded data differ in %u! (size: %u, expected: %u)\n",
+-		   i, str_len, ber[i].str_len);
++	  grub_printf ("BER decoded data differ in %u! (size: %u, expected: %u)\n", i, str_len, ber[i].str_len);
+ 	  return 1;
+ 	}
+       free (b);
+diff --git a/grub-core/tests/asn1/tests/object-id-decoding.c b/grub-core/tests/asn1/tests/object-id-decoding.c
+index fdbb8ea21..c087b46e3 100644
+--- a/grub-core/tests/asn1/tests/object-id-decoding.c
++++ b/grub-core/tests/asn1/tests/object-id-decoding.c
+@@ -85,10 +85,8 @@ test_object_id_decoding (void)
+ 				sizeof (str));
+       if (ret != tv[i].expected_error)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: asn1_get_object_id_der iter %lu: got '%s' expected %d\n",
+-		   __LINE__, (unsigned long) i, asn1_strerror (ret),
+-		   tv[i].expected_error);
++	  grub_printf ("%d: asn1_get_object_id_der iter %lu: got '%s' expected %d\n",
++		       __LINE__, (unsigned long) i, asn1_strerror (ret), tv[i].expected_error);
+ 	  return 1;
+ 	}
+ 
+@@ -97,17 +95,15 @@ test_object_id_decoding (void)
+ 
+       if (ret_len != tv[i].der_len - 1)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: iter %lu: error in DER, length returned is %d, had %d\n",
+-		   __LINE__, (unsigned long) i, ret_len, tv[i].der_len - 1);
++	  grub_printf ("%d: iter %lu: error in DER, length returned is %d, had %d\n",
++		       __LINE__, (unsigned long) i, ret_len, tv[i].der_len - 1);
+ 	  return 1;
+ 	}
+ 
+       if (strcmp (tv[i].oid, str) != 0)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: strcmp iter %lu: got invalid OID: %s, expected: %s\n",
+-		   __LINE__, (unsigned long) i, str, tv[i].oid);
++	  grub_printf ("%d: strcmp iter %lu: got invalid OID: %s, expected: %s\n",
++		       __LINE__, (unsigned long) i, str, tv[i].oid);
+ 	  return 1;
+ 	}
+ 
+diff --git a/grub-core/tests/asn1/tests/object-id-encoding.c b/grub-core/tests/asn1/tests/object-id-encoding.c
+index a497015e3..e3da092cc 100644
+--- a/grub-core/tests/asn1/tests/object-id-encoding.c
++++ b/grub-core/tests/asn1/tests/object-id-encoding.c
+@@ -93,33 +93,29 @@ test_object_id_encoding (void)
+ 	{
+ 	  if (ret == tv[i].expected_error)
+ 	    continue;
+-	  fprintf (stderr,
+-		   "%d: iter %lu, encoding of OID failed: %s\n",
+-		   __LINE__, (unsigned long) i, asn1_strerror (ret));
++	  grub_printf ("%d: iter %lu, encoding of OID failed: %s\n",
++		       __LINE__, (unsigned long) i, asn1_strerror (ret));
+ 	  return 1;
+ 	}
+       else if (ret != tv[i].expected_error)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: iter %lu, encoding of OID %s succeeded when expecting failure\n",
+-		   __LINE__, (unsigned long) i, tv[i].oid);
++	  grub_printf ("%d: iter %lu, encoding of OID %s succeeded when expecting failure\n",
++		       __LINE__, (unsigned long) i, tv[i].oid);
+ 	  return 1;
+ 	}
+ 
+       if (der_len != tv[i].der_len || memcmp (der, tv[i].der, der_len) != 0)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: iter %lu, re-encoding of OID %s resulted to different string (%d vs %d bytes)\n",
+-		   __LINE__, (unsigned long) i, tv[i].oid, der_len,
+-		   tv[i].der_len);
+-	  fprintf (stderr, "\nGot:\t\t");
++	  grub_printf ("%d: iter %lu, re-encoding of OID %s resulted to different string (%d vs %d bytes)\n",
++		   __LINE__, (unsigned long) i, tv[i].oid, der_len, tv[i].der_len);
++	  grub_printf ("\nGot:\t\t");
+ 	  for (j = 0; j < der_len; j++)
+-	    fprintf (stderr, "%.2x", der[j]);
++	    grub_printf ("%.2x", der[j]);
+ 
+-	  fprintf (stderr, "\nExpected:\t");
++	  grub_printf ("\nExpected:\t");
+ 	  for (j = 0; j < tv[i].der_len; j++)
+-	    fprintf (stderr, "%.2x", tv[i].der[j]);
+-	  fprintf (stderr, "\n");
++	    grub_printf ("%.2x", tv[i].der[j]);
++	  grub_printf ("\n");
+ 
+ 	  return 1;
+ 	}
+diff --git a/grub-core/tests/asn1/tests/octet-string.c b/grub-core/tests/asn1/tests/octet-string.c
+index 8c49c6e0c..d3a35dff8 100644
+--- a/grub-core/tests/asn1/tests/octet-string.c
++++ b/grub-core/tests/asn1/tests/octet-string.c
+@@ -131,9 +131,8 @@ test_octet_string (void)
+ 				sizeof (str), &str_size);
+ 	  if (ret != tv[i].expected_error)
+ 	    {
+-	      fprintf (stderr,
+-		       "%d: asn1_get_octet_der: %s: got %d expected %d\n",
+-		       __LINE__, tv[i].name, ret, tv[i].expected_error);
++	      grub_printf ("%d: asn1_get_octet_der: %s: got %d expected %d\n",
++			   __LINE__, tv[i].name, ret, tv[i].expected_error);
+ 	      return 1;
+ 	    }
+ 	  if (tv[i].expected_error)
+@@ -141,27 +140,25 @@ test_octet_string (void)
+ 
+ 	  if (ret_len != tv[i].der_len - 1)
+ 	    {
+-	      fprintf (stderr,
+-		       "%d: error in DER, length returned is %d, had %d\n",
+-		       __LINE__, ret_len, tv[i].der_len - 1);
++	      grub_printf ("%d: error in DER, length returned is %d, had %d\n",
++			   __LINE__, ret_len, tv[i].der_len - 1);
+ 	      return 1;
+ 	    }
+ 
+ 	  if (str_size != tv[i].len
+ 	      || memcmp (tv[i].string, str, tv[i].len) != 0)
+ 	    {
+-	      fprintf (stderr,
+-		       "%d: memcmp: %s: got invalid decoding\n",
+-		       __LINE__, tv[i].name);
++	      grub_printf ("%d: memcmp: %s: got invalid decoding\n",
++			   __LINE__, tv[i].name);
+ 
+-	      fprintf (stderr, "\nGot:\t\t");
++	      grub_printf ("\nGot:\t\t");
+ 	      for (j = 0; j < str_size; j++)
+-		fprintf (stderr, "%.2x", str[j]);
++		grub_printf ("%.2x", str[j]);
+ 
+-	      fprintf (stderr, "\nExpected:\t");
++	      grub_printf ("\nExpected:\t");
+ 	      for (j = 0; j < tv[i].len; j++)
+-		fprintf (stderr, "%.2x", tv[i].string[j]);
+-	      fprintf (stderr, "\n");
++		grub_printf ("%.2x", tv[i].string[j]);
++	      grub_printf ("\n");
+ 	      return 1;
+ 	    }
+ 
+@@ -172,8 +169,7 @@ test_octet_string (void)
+ 	  if (der_len != tv[i].der_len - 1
+ 	      || memcmp (tv[i].der_str + 1, der, tv[i].der_len - 1) != 0)
+ 	    {
+-	      fprintf (stderr,
+-		       "encoding: %s: got invalid encoding\n", tv[i].name);
++	      grub_printf ("encoding: %s: got invalid encoding\n", tv[i].name);
+ 	      return 1;
+ 	    }
+ 	}
+@@ -185,10 +181,9 @@ test_octet_string (void)
+ 				(unsigned int *) &der_len);
+       if (ret != tv[i].expected_error)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: asn1_decode_simple_ber: %s: got %s expected %s\n",
+-		   __LINE__, tv[i].name, asn1_strerror (ret),
+-		   asn1_strerror (tv[i].expected_error));
++	  grub_printf ("%d: asn1_decode_simple_ber: %s: got %s expected %s\n",
++		       __LINE__, tv[i].name, asn1_strerror (ret),
++		       asn1_strerror (tv[i].expected_error));
+ 	  return 1;
+ 	}
+       if (tv[i].expected_error)
+@@ -196,25 +191,22 @@ test_octet_string (void)
+ 
+       if (der_len != tv[i].der_len)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: error: %s: DER, length returned is %d, had %d\n",
+-		   __LINE__, tv[i].name, der_len, tv[i].der_len);
++	  grub_printf ("%d: error: %s: DER, length returned is %d, had %d\n",
++		       __LINE__, tv[i].name, der_len, tv[i].der_len);
+ 	  return 1;
+ 	}
+ 
+       if (str_size != tv[i].len || memcmp (tv[i].string, tmp, tv[i].len) != 0)
+ 	{
+-	  fprintf (stderr,
+-		   "%d: memcmp: %s: got invalid decoding\n",
+-		   __LINE__, tv[i].name);
+-	  fprintf (stderr, "\nGot:\t\t");
++	  grub_printf ("%d: memcmp: %s: got invalid decoding\n", __LINE__, tv[i].name);
++	  grub_printf ("\nGot:\t\t");
+ 	  for (j = 0; j < str_size; j++)
+-	    fprintf (stderr, "%.2x", tmp[j]);
++	    grub_printf ("%.2x", tmp[j]);
+ 
+-	  fprintf (stderr, "\nExpected:\t");
++	  grub_printf ("\nExpected:\t");
+ 	  for (j = 0; j < tv[i].len; j++)
+-	    fprintf (stderr, "%.2x", tv[i].string[j]);
+-	  fprintf (stderr, "\n");
++	    grub_printf ("%.2x", tv[i].string[j]);
++	  grub_printf ("\n");
+ 	  return 1;
+ 	}
+       free (tmp);
+diff --git a/grub-core/tests/asn1/tests/reproducers.c b/grub-core/tests/asn1/tests/reproducers.c
+index fa3cea762..0e3c9fd65 100644
+--- a/grub-core/tests/asn1/tests/reproducers.c
++++ b/grub-core/tests/asn1/tests/reproducers.c
+@@ -58,8 +58,7 @@ test_reproducers (void)
+   result = asn1_array2tree (endless_asn1_tab, &definitions, errorDescription);
+   if (result != ASN1_SUCCESS)
+     {
+-      asn1_perror (result);
+-      printf ("ErrorDescription = %s\n\n", errorDescription);
++      grub_printf ("Error: %s\nErrorDescription = %s\n\n", asn1_strerror (result), errorDescription);
+       return 1;
+     }
+ 
+@@ -69,8 +68,7 @@ test_reproducers (void)
+   result = asn1_array2tree (tab, &definitions, errorDescription);
+   if (result != ASN1_SUCCESS)
+     {
+-      asn1_perror (result);
+-      printf ("ErrorDescription = %s\n\n", errorDescription);
++      grub_printf ("Error: %s\nErrorDescription = %s\n\n", asn1_strerror (result), errorDescription);
+       return 1;
+     }
+ 
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0012-asn1_test-use-the-grub-specific-functions-and-types.patch b/grub-core/lib/libtasn1-patches/0012-asn1_test-use-the-grub-specific-functions-and-types.patch
new file mode 100644
index 0000000..ba27157
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0012-asn1_test-use-the-grub-specific-functions-and-types.patch
@@ -0,0 +1,263 @@
+From 392da24a8a4b2ab94a93e9e0f74db027a3a9374d Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Fri, 16 Aug 2024 15:46:59 +0800
+Subject: [PATCH 12/13] asn1_test: use the grub-specific functions and types
+
+This commit converts functions and types to the grub-specific ones:
+
+LONG_MAX -> GRUB_LONG_MAX
+INT_MAX -> GRUB_INT_MAX
+UINT_MAX -> GRUB_UINT_MAX
+size_t -> grub_size_t
+memcmp() -> grub_memcmp()
+memcpy() -> grub_memcpy()
+free() -> grub_free()
+strcmp() -> grub_strcmp()
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/tests/asn1/tests/Test_overflow.c    |  4 ++--
+ grub-core/tests/asn1/tests/Test_simple.c      | 22 +++++++++----------
+ grub-core/tests/asn1/tests/Test_strings.c     |  8 +++----
+ .../tests/asn1/tests/object-id-decoding.c     |  4 ++--
+ .../tests/asn1/tests/object-id-encoding.c     |  2 +-
+ grub-core/tests/asn1/tests/octet-string.c     | 10 ++++-----
+ 6 files changed, 25 insertions(+), 25 deletions(-)
+
+diff --git a/grub-core/tests/asn1/tests/Test_overflow.c b/grub-core/tests/asn1/tests/Test_overflow.c
+index ffac8507a..65843abf6 100644
+--- a/grub-core/tests/asn1/tests/Test_overflow.c
++++ b/grub-core/tests/asn1/tests/Test_overflow.c
+@@ -43,9 +43,9 @@ test_overflow (void)
+ 
+   /* Test that values larger than int but smaller than long are
+      rejected.  This limitation was introduced with libtasn1 2.12. */
+-  if (LONG_MAX > INT_MAX)
++  if (GRUB_LONG_MAX > GRUB_INT_MAX)
+     {
+-      unsigned long num = ((long) UINT_MAX) << 2;
++      unsigned long num = ((long) GRUB_UINT_MAX) << 2;
+       unsigned char der[20];
+       int der_len;
+       long l;
+diff --git a/grub-core/tests/asn1/tests/Test_simple.c b/grub-core/tests/asn1/tests/Test_simple.c
+index dc70db191..19613cae8 100644
+--- a/grub-core/tests/asn1/tests/Test_simple.c
++++ b/grub-core/tests/asn1/tests/Test_simple.c
+@@ -81,7 +81,7 @@ test_simple (void)
+   int der_len = sizeof (der);
+   int str_size = sizeof (str);
+   int ret_len, bit_len;
+-  size_t i;
++  grub_size_t i;
+ 
+   {
+     unsigned int etype = 38;
+@@ -127,7 +127,7 @@ test_simple (void)
+       }
+ #endif
+ 
+-      if (der_len != tv[i].derlen || memcmp (der, tv[i].der, der_len) != 0)
++      if (der_len != tv[i].derlen || grub_memcmp (der, tv[i].der, der_len) != 0)
+ 	{
+ 	  grub_printf ("asn1_bit_der iter %lu\n", (unsigned long) i);
+ 	  return 1;
+@@ -155,12 +155,12 @@ test_simple (void)
+ 
+   /* 03 04 06 6e 5d c0  DER encoding */
+ 
+-  memcpy (der, "\x04\x06\x6e\x5d\xc0", 5);
++  grub_memcpy (der, "\x04\x06\x6e\x5d\xc0", 5);
+   der_len = 5;
+ 
+   result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len);
+   if (result != ASN1_SUCCESS || ret_len != 5
+-      || bit_len != 18 || memcmp (str, "\x6e\x5d\xc0", 3) != 0)
++      || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xc0", 3) != 0)
+     {
+       grub_printf ("asn1_get_bit_der example\n");
+       return 1;
+@@ -168,7 +168,7 @@ test_simple (void)
+ 
+   der_len = sizeof (der);
+   asn1_bit_der (str, bit_len, der, &der_len);
+-  if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
++  if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+     {
+       grub_printf ("asn1_bit_der example roundtrip\n");
+       return 1;
+@@ -176,12 +176,12 @@ test_simple (void)
+ 
+   /* 03 04 06 6e 5d e0 padded with "100000" */
+ 
+-  memcpy (der, "\x04\x06\x6e\x5d\xe0", 5);
++  grub_memcpy (der, "\x04\x06\x6e\x5d\xe0", 5);
+   der_len = 5;
+ 
+   result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len);
+   if (result != ASN1_SUCCESS || ret_len != 5
+-      || bit_len != 18 || memcmp (str, "\x6e\x5d\xe0", 3) != 0)
++      || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xe0", 3) != 0)
+     {
+       grub_printf ("asn1_get_bit_der example padded\n");
+       return 1;
+@@ -189,7 +189,7 @@ test_simple (void)
+ 
+   der_len = sizeof (der);
+   asn1_bit_der (str, bit_len, der, &der_len);
+-  if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
++  if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+     {
+       grub_printf ("asn1_bit_der example roundtrip\n");
+       return 1;
+@@ -197,13 +197,13 @@ test_simple (void)
+ 
+   /* 03 81 04 06 6e 5d c0 long form of length octets */
+ 
+-  memcpy (der, "\x81\x04\x06\x6e\x5d\xc0", 6);
++  grub_memcpy (der, "\x81\x04\x06\x6e\x5d\xc0", 6);
+   der_len = 6;
+ 
+   result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len);
+ 
+   if (result != ASN1_SUCCESS || ret_len != 6
+-      || bit_len != 18 || memcmp (str, "\x6e\x5d\xc0", 3) != 0)
++      || bit_len != 18 || grub_memcmp (str, "\x6e\x5d\xc0", 3) != 0)
+     {
+       grub_printf ("asn1_get_bit_der example long form\n");
+       return 1;
+@@ -211,7 +211,7 @@ test_simple (void)
+ 
+   der_len = sizeof (der);
+   asn1_bit_der (str, bit_len, der, &der_len);
+-  if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
++  if (der_len != 5 || grub_memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+     {
+       grub_printf ("asn1_bit_der example roundtrip\n");
+       return 1;
+diff --git a/grub-core/tests/asn1/tests/Test_strings.c b/grub-core/tests/asn1/tests/Test_strings.c
+index 65c30937f..c7c1afa1b 100644
+--- a/grub-core/tests/asn1/tests/Test_strings.c
++++ b/grub-core/tests/asn1/tests/Test_strings.c
+@@ -94,7 +94,7 @@ test_strings (void)
+ 	}
+       der_len = tl_len + tv[i].str_len;
+ 
+-      if (der_len != tv[i].der_len || memcmp (tl, tv[i].der, tl_len) != 0)
++      if (der_len != tv[i].der_len || grub_memcmp (tl, tv[i].der, tl_len) != 0)
+ 	{
+ 	  grub_printf ("DER encoding differs in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].der_len);
+ 	  return 1;
+@@ -110,7 +110,7 @@ test_strings (void)
+ 	  return 1;
+ 	}
+ 
+-      if (str_len != tv[i].str_len || memcmp (str, tv[i].str, str_len) != 0)
++      if (str_len != tv[i].str_len || grub_memcmp (str, tv[i].str, str_len) != 0)
+ 	{
+ 	  grub_printf ("DER decoded data differ in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].str_len);
+ 	  return 1;
+@@ -130,12 +130,12 @@ test_strings (void)
+ 	  return 1;
+ 	}
+ 
+-      if (str_len != ber[i].str_len || memcmp (b, ber[i].str, str_len) != 0)
++      if (str_len != ber[i].str_len || grub_memcmp (b, ber[i].str, str_len) != 0)
+ 	{
+ 	  grub_printf ("BER decoded data differ in %u! (size: %u, expected: %u)\n", i, str_len, ber[i].str_len);
+ 	  return 1;
+ 	}
+-      free (b);
++      grub_free (b);
+     }
+ 
+ 
+diff --git a/grub-core/tests/asn1/tests/object-id-decoding.c b/grub-core/tests/asn1/tests/object-id-decoding.c
+index c087b46e3..91af8cde5 100644
+--- a/grub-core/tests/asn1/tests/object-id-decoding.c
++++ b/grub-core/tests/asn1/tests/object-id-decoding.c
+@@ -74,7 +74,7 @@ test_object_id_decoding (void)
+ {
+   char str[128];
+   int ret, ret_len;
+-  size_t i;
++  grub_size_t i;
+ 
+   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+     {
+@@ -100,7 +100,7 @@ test_object_id_decoding (void)
+ 	  return 1;
+ 	}
+ 
+-      if (strcmp (tv[i].oid, str) != 0)
++      if (grub_strcmp (tv[i].oid, str) != 0)
+ 	{
+ 	  grub_printf ("%d: strcmp iter %lu: got invalid OID: %s, expected: %s\n",
+ 		       __LINE__, (unsigned long) i, str, tv[i].oid);
+diff --git a/grub-core/tests/asn1/tests/object-id-encoding.c b/grub-core/tests/asn1/tests/object-id-encoding.c
+index e3da092cc..f8f98ff17 100644
+--- a/grub-core/tests/asn1/tests/object-id-encoding.c
++++ b/grub-core/tests/asn1/tests/object-id-encoding.c
+@@ -104,7 +104,7 @@ test_object_id_encoding (void)
+ 	  return 1;
+ 	}
+ 
+-      if (der_len != tv[i].der_len || memcmp (der, tv[i].der, der_len) != 0)
++      if (der_len != tv[i].der_len || grub_memcmp (der, tv[i].der, der_len) != 0)
+ 	{
+ 	  grub_printf ("%d: iter %lu, re-encoding of OID %s resulted to different string (%d vs %d bytes)\n",
+ 		   __LINE__, (unsigned long) i, tv[i].oid, der_len, tv[i].der_len);
+diff --git a/grub-core/tests/asn1/tests/octet-string.c b/grub-core/tests/asn1/tests/octet-string.c
+index d3a35dff8..dcf0fb808 100644
+--- a/grub-core/tests/asn1/tests/octet-string.c
++++ b/grub-core/tests/asn1/tests/octet-string.c
+@@ -116,7 +116,7 @@ test_octet_string (void)
+   int str_size = sizeof (str);
+   unsigned char *tmp = NULL;
+   int ret, ret_len, j;
+-  size_t i;
++  grub_size_t i;
+ 
+   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+     {
+@@ -146,7 +146,7 @@ test_octet_string (void)
+ 	    }
+ 
+ 	  if (str_size != tv[i].len
+-	      || memcmp (tv[i].string, str, tv[i].len) != 0)
++	      || grub_memcmp (tv[i].string, str, tv[i].len) != 0)
+ 	    {
+ 	      grub_printf ("%d: memcmp: %s: got invalid decoding\n",
+ 			   __LINE__, tv[i].name);
+@@ -167,7 +167,7 @@ test_octet_string (void)
+ 	  asn1_octet_der (str, str_size, der, &der_len);
+ 
+ 	  if (der_len != tv[i].der_len - 1
+-	      || memcmp (tv[i].der_str + 1, der, tv[i].der_len - 1) != 0)
++	      || grub_memcmp (tv[i].der_str + 1, der, tv[i].der_len - 1) != 0)
+ 	    {
+ 	      grub_printf ("encoding: %s: got invalid encoding\n", tv[i].name);
+ 	      return 1;
+@@ -196,7 +196,7 @@ test_octet_string (void)
+ 	  return 1;
+ 	}
+ 
+-      if (str_size != tv[i].len || memcmp (tv[i].string, tmp, tv[i].len) != 0)
++      if (str_size != tv[i].len || grub_memcmp (tv[i].string, tmp, tv[i].len) != 0)
+ 	{
+ 	  grub_printf ("%d: memcmp: %s: got invalid decoding\n", __LINE__, tv[i].name);
+ 	  grub_printf ("\nGot:\t\t");
+@@ -209,7 +209,7 @@ test_octet_string (void)
+ 	  grub_printf ("\n");
+ 	  return 1;
+ 	}
+-      free (tmp);
++      grub_free (tmp);
+       tmp = NULL;
+ 
+     }
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1-patches/0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch b/grub-core/lib/libtasn1-patches/0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch
new file mode 100644
index 0000000..a81a350
--- /dev/null
+++ b/grub-core/lib/libtasn1-patches/0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch
@@ -0,0 +1,48 @@
+From 6d308d9053447dcc003a9ca740c47c00932d3569 Mon Sep 17 00:00:00 2001
+From: Gary Lin <glin@suse.com>
+Date: Mon, 7 Oct 2024 11:33:19 +0800
+Subject: [PATCH 13/13] asn1_test: enable the testcase only when GRUB_LONG_MAX
+ is larger than GRUB_INT_MAX
+
+There is a testcase to test the values larger than 'int' but smaller
+than 'long'. However, for some architectures, 'long' and 'int' are the
+same, and the compiler may issue a warning like this:
+
+grub-core/tests/asn1/tests/Test_overflow.c:48:50: error: left shift of negative value [-Werror=shift-negative-value]
+       unsigned long num = ((long) GRUB_UINT_MAX) << 2;
+                                                  ^~
+
+To avoid unnecessary error the testcase is enabled only when
+GRUB_LONG_MAX is larger than GRUB_INT_MAX.
+
+Signed-off-by: Daniel Axtens <dja@axtens.net>
+Signed-off-by: Gary Lin <glin@suse.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/tests/asn1/tests/Test_overflow.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/tests/asn1/tests/Test_overflow.c b/grub-core/tests/asn1/tests/Test_overflow.c
+index 65843abf6..fdeff5634 100644
+--- a/grub-core/tests/asn1/tests/Test_overflow.c
++++ b/grub-core/tests/asn1/tests/Test_overflow.c
+@@ -43,7 +43,7 @@ test_overflow (void)
+ 
+   /* Test that values larger than int but smaller than long are
+      rejected.  This limitation was introduced with libtasn1 2.12. */
+-  if (GRUB_LONG_MAX > GRUB_INT_MAX)
++#if (GRUB_LONG_MAX > GRUB_INT_MAX)
+     {
+       unsigned long num = ((long) GRUB_UINT_MAX) << 2;
+       unsigned char der[20];
+@@ -61,6 +61,7 @@ test_overflow (void)
+ 	  return 1;
+ 	}
+     }
++#endif
+ 
+   /* Test that values larger than would fit in the input string are
+      rejected.  This problem was fixed in libtasn1 2.12. */
+-- 
+2.43.0
+
diff --git a/grub-core/lib/libtasn1/COPYING b/grub-core/lib/libtasn1/COPYING
new file mode 100644
index 0000000..e8b3628
--- /dev/null
+++ b/grub-core/lib/libtasn1/COPYING
@@ -0,0 +1,16 @@
+LICENSING
+=========
+
+The libtasn1 library is released under the GNU Lesser General Public
+License (LGPL) version 2.1 or later; see [COPYING.LESSER](doc/COPYING.LESSER)
+for the license terms.
+
+The GNU LGPL applies to the main libtasn1 library, while the
+included applications library are under the GNU GPL version 3.
+The libtasn1 library is located in the lib directory, while the applications
+in src/.
+
+The documentation in doc/ is under the GNU FDL license 1.3.
+
+For any copyright year range specified as YYYY-ZZZZ in this package
+note that the range specifies every single year in that closed interval.
diff --git a/grub-core/lib/libtasn1/README.md b/grub-core/lib/libtasn1/README.md
new file mode 100644
index 0000000..b0305b9
--- /dev/null
+++ b/grub-core/lib/libtasn1/README.md
@@ -0,0 +1,98 @@
+# Libtasn1 README -- Introduction information
+
+This is GNU Libtasn1, a small ASN.1 library.
+
+The C library (libtasn1.*) is licensed under the GNU Lesser General
+Public License version 2.1 or later.  See the file COPYING.LIB.
+
+The command line tool, self tests, examples, and other auxilliary
+files, are licensed under the GNU General Public License version 3.0
+or later.  See the file COPYING.
+
+## Building the library
+
+We require several tools to build the software, including:
+
+* [Make](https://www.gnu.org/software/make/)
+* [Automake](https://www.gnu.org/software/automake/) (use 1.11.3 or later)
+* [Autoconf](https://www.gnu.org/software/autoconf/)
+* [Libtool](https://www.gnu.org/software/libtool/)
+* [Texinfo](https://www.gnu.org/software/texinfo/)
+* [help2man](http://www.gnu.org/software/help2man/)
+* [Tar](https://www.gnu.org/software/tar/)
+* [Gzip](https://www.gnu.org/software/gzip/)
+* [bison](https://www.gnu.org/software/bison/)
+* [Texlive & epsf](https://www.tug.org/texlive/) (for PDF manual)
+* [GTK-DOC](https://www.gtk.org/gtk-doc/) (for API manual)
+* [Git](https://git-scm.com/)
+* [libabigail](https://pagure.io/libabigail/) (for abi comparison in make dist)
+* [Valgrind](https://valgrind.org/) (optional)
+
+The required software is typically distributed with your operating
+system, and the instructions for installing them differ.  Here are
+some hints:
+
+Debian/Ubuntu:
+```
+sudo apt-get install make git autoconf automake libtool bison
+sudo apt-get install texinfo help2man gtk-doc-tools valgrind abigail-tools
+```
+
+PDF manual - Debian <= stretch:
+```
+sudo apt-get install texlive-generic-recommended texlive texlive-extra-utils
+```
+
+PDF manual - Debian >= buster:
+```
+sudo apt-get install texlive-plain-generic texlive texlive-extra-utils
+```
+
+The next step is to run autoreconf, ./configure, etc:
+
+```
+$ ./bootstrap
+```
+
+Then build the project normally:
+
+```
+$ ./configure
+$ make check
+```
+
+Happy hacking!
+
+
+## Manual
+
+The manual is in the `doc/` directory of the release.
+
+You can also browse the manual online at:
+
+ - https://www.gnu.org/software/libtasn1/manual/
+ - https://gnutls.gitlab.io/libtasn1/manual/
+ - https://gnutls.gitlab.io/libtasn1/manual/libtasn1.html
+ - https://gnutls.gitlab.io/libtasn1/manual/libtasn1.pdf
+ - https://gnutls.gitlab.io/libtasn1/reference/
+ - https://gnutls.gitlab.io/libtasn1/reference/libtasn1.pdf
+
+
+## Code coverage report
+
+The coverage report is at:
+
+ - https://gnutls.gitlab.io/libtasn1/coverage
+
+
+## Issue trackers
+
+ - [Main issue tracker](https://gitlab.com/gnutls/libtasn1/issues)
+ - [oss-fuzz found issues](https://bugs.chromium.org/p/oss-fuzz/issues/list?q=libtasn1&can=2)
+
+
+## Homepage
+
+The project homepage at the gnu site is at:
+
+https://www.gnu.org/software/libtasn1/
diff --git a/grub-core/lib/libtasn1/lib/coding.c b/grub-core/lib/libtasn1/lib/coding.c
new file mode 100644
index 0000000..ea5bc37
--- /dev/null
+++ b/grub-core/lib/libtasn1/lib/coding.c
@@ -0,0 +1,1425 @@
+/*
+ * Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+
+/*****************************************************/
+/* File: coding.c                                    */
+/* Description: Functions to create a DER coding of  */
+/*   an ASN1 type.                                   */
+/*****************************************************/
+
+#include <int.h>
+#include "parser_aux.h"
+#include <gstr.h>
+#include "element.h"
+#include "minmax.h"
+#include <structure.h>
+
+#define MAX_TAG_LEN 16
+
+/******************************************************/
+/* Function : _asn1_error_description_value_not_found */
+/* Description: creates the ErrorDescription string   */
+/* for the ASN1_VALUE_NOT_FOUND error.                */
+/* Parameters:                                        */
+/*   node: node of the tree where the value is NULL.  */
+/*   ErrorDescription: string returned.               */
+/* Return:                                            */
+/******************************************************/
+static void
+_asn1_error_description_value_not_found (asn1_node node,
+					 char *ErrorDescription)
+{
+
+  if (ErrorDescription == NULL)
+    return;
+
+  Estrcpy (ErrorDescription, ":: value of element '");
+  _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription),
+			   ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40);
+  Estrcat (ErrorDescription, "' not found");
+
+}
+
+/**
+ * asn1_length_der:
+ * @len: value to convert.
+ * @der: buffer to hold the returned encoding (may be %NULL).
+ * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]).
+ *
+ * Creates the DER encoding of the provided length value.
+ * The @der buffer must have enough room for the output. The maximum
+ * length this function will encode is %ASN1_MAX_LENGTH_SIZE.
+ *
+ * To know the size of the DER encoding use a %NULL value for @der.
+ **/
+void
+asn1_length_der (unsigned long int len, unsigned char *der, int *der_len)
+{
+  int k;
+  unsigned char temp[ASN1_MAX_LENGTH_SIZE];
+#if SIZEOF_UNSIGNED_LONG_INT > 8
+  len &= 0xFFFFFFFFFFFFFFFF;
+#endif
+
+  if (len < 128)
+    {
+      /* short form */
+      if (der != NULL)
+	der[0] = (unsigned char) len;
+      *der_len = 1;
+    }
+  else
+    {
+      /* Long form */
+      k = 0;
+      while (len)
+	{
+	  temp[k++] = len & 0xFF;
+	  len = len >> 8;
+	}
+      *der_len = k + 1;
+      if (der != NULL)
+	{
+	  der[0] = ((unsigned char) k & 0x7F) + 128;
+	  while (k--)
+	    der[*der_len - 1 - k] = temp[k];
+	}
+    }
+}
+
+/******************************************************/
+/* Function : _asn1_tag_der                           */
+/* Description: creates the DER coding for the CLASS  */
+/* and TAG parameters.                                */
+/* It is limited by the ASN1_MAX_TAG_SIZE variable    */
+/* Parameters:                                        */
+/*   class: value to convert.                         */
+/*   tag_value: value to convert.                     */
+/*   ans: string returned.                            */
+/*   ans_len: number of meaningful bytes of ANS       */
+/*            (ans[0]..ans[ans_len-1]).               */
+/* Return:                                            */
+/******************************************************/
+static void
+_asn1_tag_der (unsigned char class, unsigned int tag_value,
+	       unsigned char ans[ASN1_MAX_TAG_SIZE], int *ans_len)
+{
+  int k;
+  unsigned char temp[ASN1_MAX_TAG_SIZE];
+
+  if (tag_value < 31)
+    {
+      /* short form */
+      ans[0] = (class & 0xE0) + ((unsigned char) (tag_value & 0x1F));
+      *ans_len = 1;
+    }
+  else
+    {
+      /* Long form */
+      ans[0] = (class & 0xE0) + 31;
+      k = 0;
+      while (tag_value != 0)
+	{
+	  temp[k++] = tag_value & 0x7F;
+	  tag_value >>= 7;
+
+	  if (k > ASN1_MAX_TAG_SIZE - 1)
+	    break;		/* will not encode larger tags */
+	}
+      *ans_len = k + 1;
+      while (k--)
+	ans[*ans_len - 1 - k] = temp[k] + 128;
+      ans[*ans_len - 1] -= 128;
+    }
+}
+
+/**
+ * asn1_octet_der:
+ * @str: the input data.
+ * @str_len: STR length (str[0]..str[*str_len-1]).
+ * @der: encoded string returned.
+ * @der_len: number of meaningful bytes of DER (der[0]..der[der_len-1]).
+ *
+ * Creates a length-value DER encoding for the input data.
+ * The DER encoding of the input data will be placed in the @der variable.
+ *
+ * Note that the OCTET STRING tag is not included in the output.
+ *
+ * This function does not return any value because it is expected
+ * that @der_len will contain enough bytes to store the string
+ * plus the DER encoding. The DER encoding size can be obtained using
+ * asn1_length_der().
+ **/
+void
+asn1_octet_der (const unsigned char *str, int str_len,
+		unsigned char *der, int *der_len)
+{
+  int len_len;
+
+  if (der == NULL || str_len < 0)
+    return;
+
+  asn1_length_der (str_len, der, &len_len);
+  memcpy (der + len_len, str, str_len);
+  *der_len = str_len + len_len;
+}
+
+
+/**
+ * asn1_encode_simple_der:
+ * @etype: The type of the string to be encoded (ASN1_ETYPE_)
+ * @str: the string data.
+ * @str_len: the string length
+ * @tl: the encoded tag and length
+ * @tl_len: the bytes of the @tl field
+ *
+ * Creates the DER encoding for various simple ASN.1 types like strings etc.
+ * It stores the tag and length in @tl, which should have space for at least
+ * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl.
+ *
+ * The complete DER encoding should consist of the value in @tl appended
+ * with the provided @str.
+ *
+ * Returns: %ASN1_SUCCESS if successful or an error value.
+ **/
+int
+asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
+			unsigned int str_len, unsigned char *tl,
+			unsigned int *tl_len)
+{
+  int tag_len, len_len;
+  unsigned tlen;
+  unsigned char der_tag[ASN1_MAX_TAG_SIZE];
+  unsigned char der_length[ASN1_MAX_LENGTH_SIZE];
+  unsigned char *p;
+
+  if (str == NULL)
+    return ASN1_VALUE_NOT_VALID;
+
+  if (ETYPE_OK (etype) == 0)
+    return ASN1_VALUE_NOT_VALID;
+
+  /* doesn't handle constructed classes */
+  if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
+    return ASN1_VALUE_NOT_VALID;
+
+  _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len);
+
+  asn1_length_der (str_len, der_length, &len_len);
+
+  if (tag_len <= 0 || len_len <= 0)
+    return ASN1_VALUE_NOT_VALID;
+
+  tlen = tag_len + len_len;
+
+  if (*tl_len < tlen)
+    return ASN1_MEM_ERROR;
+
+  p = tl;
+  memcpy (p, der_tag, tag_len);
+  p += tag_len;
+  memcpy (p, der_length, len_len);
+
+  *tl_len = tlen;
+
+  return ASN1_SUCCESS;
+}
+
+/******************************************************/
+/* Function : _asn1_time_der                          */
+/* Description: creates the DER coding for a TIME     */
+/* type (length included).                            */
+/* Parameters:                                        */
+/*   str: TIME null-terminated string.                */
+/*   der: string returned.                            */
+/*   der_len: number of meaningful bytes of DER       */
+/*            (der[0]..der[ans_len-1]). Initially it  */
+/*            if must store the lenght of DER.        */
+/* Return:                                            */
+/*   ASN1_MEM_ERROR when DER isn't big enough         */
+/*   ASN1_SUCCESS otherwise                           */
+/******************************************************/
+static int
+_asn1_time_der (unsigned char *str, int str_len, unsigned char *der,
+		int *der_len)
+{
+  int len_len;
+  int max_len;
+
+  max_len = *der_len;
+
+  asn1_length_der (str_len, (max_len > 0) ? der : NULL, &len_len);
+
+  if ((len_len + str_len) <= max_len)
+    memcpy (der + len_len, str, str_len);
+  *der_len = len_len + str_len;
+
+  if ((*der_len) > max_len)
+    return ASN1_MEM_ERROR;
+
+  return ASN1_SUCCESS;
+}
+
+
+/*
+void
+_asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
+{
+  int len_len,str_len;
+  char temp[20];
+
+  if(str==NULL) return;
+  str_len=asn1_get_length_der(der,*der_len,&len_len);
+  if (str_len<0) return;
+  memcpy(temp,der+len_len,str_len);
+  *der_len=str_len+len_len;
+  switch(str_len)
+  {
+  case 11:
+    temp[10]=0;
+    strcat(temp,"00+0000");
+    break;
+  case 13:
+    temp[12]=0;
+    strcat(temp,"+0000");
+    break;
+  case 15:
+    temp[15]=0;
+    memmove(temp+12,temp+10,6);
+    temp[10]=temp[11]='0';
+    break;
+  case 17:
+    temp[17]=0;
+    break;
+  default:
+    return;
+  }
+  strcpy(str,temp);
+}
+*/
+
+static void
+encode_val (uint64_t val, unsigned char *der, int max_len, int *der_len)
+{
+  int first, k;
+  unsigned char bit7;
+
+  first = 0;
+  for (k = sizeof (val); k >= 0; k--)
+    {
+      bit7 = (val >> (k * 7)) & 0x7F;
+      if (bit7 || first || !k)
+	{
+	  if (k)
+	    bit7 |= 0x80;
+	  if (max_len > (*der_len))
+	    der[*der_len] = bit7;
+	  (*der_len)++;
+	  first = 1;
+	}
+    }
+}
+
+/******************************************************/
+/* Function : _asn1_object_id_der                     */
+/* Description: creates the DER coding for an         */
+/* OBJECT IDENTIFIER  type (length included).         */
+/* Parameters:                                        */
+/*   str: OBJECT IDENTIFIER null-terminated string.   */
+/*   der: string returned.                            */
+/*   der_len: number of meaningful bytes of DER       */
+/*            (der[0]..der[ans_len-1]). Initially it  */
+/*            must store the length of DER.           */
+/* Return:                                            */
+/*   ASN1_MEM_ERROR when DER isn't big enough         */
+/*   ASN1_SUCCESS if succesful                        */
+/*   or an error value.                               */
+/******************************************************/
+static int
+_asn1_object_id_der (const char *str, unsigned char *der, int *der_len)
+{
+  int len_len, counter, max_len;
+  char *temp, *n_end, *n_start;
+  uint64_t val, val1 = 0;
+  int str_len = _asn1_strlen (str);
+
+  max_len = *der_len;
+  *der_len = 0;
+
+  if (der == NULL && max_len > 0)
+    return ASN1_VALUE_NOT_VALID;
+
+  temp = malloc (str_len + 2);
+  if (temp == NULL)
+    return ASN1_MEM_ALLOC_ERROR;
+
+  memcpy (temp, str, str_len);
+  temp[str_len] = '.';
+  temp[str_len + 1] = 0;
+
+  counter = 0;
+  n_start = temp;
+  while ((n_end = strchr (n_start, '.')))
+    {
+      *n_end = 0;
+      val = _asn1_strtou64 (n_start, NULL, 10);
+      counter++;
+
+      if (counter == 1)
+	{
+	  val1 = val;
+	}
+      else if (counter == 2)
+	{
+	  uint64_t val0;
+
+	  if (val1 > 2)
+	    {
+	      free (temp);
+	      return ASN1_VALUE_NOT_VALID;
+	    }
+	  else if ((val1 == 0 || val1 == 1) && val > 39)
+	    {
+	      free (temp);
+	      return ASN1_VALUE_NOT_VALID;
+	    }
+
+	  val0 = 40 * val1 + val;
+	  encode_val (val0, der, max_len, der_len);
+	}
+      else
+	{
+	  encode_val (val, der, max_len, der_len);
+	}
+      n_start = n_end + 1;
+    }
+
+  asn1_length_der (*der_len, NULL, &len_len);
+  if (max_len >= (*der_len + len_len))
+    {
+      memmove (der + len_len, der, *der_len);
+      asn1_length_der (*der_len, der, &len_len);
+    }
+  *der_len += len_len;
+
+  free (temp);
+
+  if (max_len < (*der_len))
+    return ASN1_MEM_ERROR;
+
+  return ASN1_SUCCESS;
+}
+
+/**
+ * asn1_object_id_der:
+ * @str: An object identifier in numeric, dot format.
+ * @der: buffer to hold the returned encoding (may be %NULL).
+ * @der_len: initially the size of @der; will hold the final size.
+ * @flags: must be zero
+ *
+ * Creates the DER encoding of the provided object identifier.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding was OK, %ASN1_VALUE_NOT_VALID
+ *   if @str is not a valid OID, %ASN1_MEM_ERROR if the @der
+ *   vector isn't big enough and in this case @der_len will contain the
+ *   length needed.
+ **/
+int
+asn1_object_id_der (const char *str, unsigned char *der, int *der_len,
+		    unsigned flags)
+{
+  unsigned char tag_der[MAX_TAG_LEN];
+  int tag_len = 0, r;
+  int max_len = *der_len;
+
+  *der_len = 0;
+
+  _asn1_tag_der (ETYPE_CLASS (ASN1_ETYPE_OBJECT_ID),
+		 ETYPE_TAG (ASN1_ETYPE_OBJECT_ID), tag_der, &tag_len);
+
+  if (max_len > tag_len)
+    {
+      memcpy (der, tag_der, tag_len);
+    }
+  max_len -= tag_len;
+  der += tag_len;
+
+  r = _asn1_object_id_der (str, der, &max_len);
+  if (r == ASN1_MEM_ERROR || r == ASN1_SUCCESS)
+    {
+      *der_len = max_len + tag_len;
+    }
+
+  return r;
+}
+
+static const unsigned char bit_mask[] =
+  { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
+
+/**
+ * asn1_bit_der:
+ * @str: BIT string.
+ * @bit_len: number of meaningful bits in STR.
+ * @der: string returned.
+ * @der_len: number of meaningful bytes of DER
+ *   (der[0]..der[ans_len-1]).
+ *
+ * Creates a length-value DER encoding for the input data
+ * as it would have been for a BIT STRING.
+ * The DER encoded data will be copied in @der.
+ *
+ * Note that the BIT STRING tag is not included in the output.
+ *
+ * This function does not return any value because it is expected
+ * that @der_len will contain enough bytes to store the string
+ * plus the DER encoding. The DER encoding size can be obtained using
+ * asn1_length_der().
+ **/
+void
+asn1_bit_der (const unsigned char *str, int bit_len,
+	      unsigned char *der, int *der_len)
+{
+  int len_len, len_byte, len_pad;
+
+  if (der == NULL)
+    return;
+
+  len_byte = bit_len >> 3;
+  len_pad = 8 - (bit_len & 7);
+  if (len_pad == 8)
+    len_pad = 0;
+  else
+    len_byte++;
+  asn1_length_der (len_byte + 1, der, &len_len);
+  der[len_len] = len_pad;
+
+  if (str)
+    memcpy (der + len_len + 1, str, len_byte);
+  der[len_len + len_byte] &= bit_mask[len_pad];
+  *der_len = len_byte + len_len + 1;
+}
+
+
+/******************************************************/
+/* Function : _asn1_complete_explicit_tag             */
+/* Description: add the length coding to the EXPLICIT */
+/* tags.                                              */
+/* Parameters:                                        */
+/*   node: pointer to the tree element.               */
+/*   der: string with the DER coding of the whole tree*/
+/*   counter: number of meaningful bytes of DER       */
+/*            (der[0]..der[*counter-1]).              */
+/*   max_len: size of der vector                      */
+/* Return:                                            */
+/*   ASN1_MEM_ERROR if der vector isn't big enough,   */
+/*   otherwise ASN1_SUCCESS.                          */
+/******************************************************/
+static int
+_asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
+			     int *counter, int *max_len)
+{
+  asn1_node p;
+  int is_tag_implicit, len2, len3;
+  unsigned char temp[SIZEOF_UNSIGNED_INT];
+
+  if (der == NULL && *max_len > 0)
+    return ASN1_VALUE_NOT_VALID;
+
+  is_tag_implicit = 0;
+
+  if (node->type & CONST_TAG)
+    {
+      p = node->down;
+      if (p == NULL)
+	return ASN1_DER_ERROR;
+      /* When there are nested tags we must complete them reverse to
+         the order they were created. This is because completing a tag
+         modifies all data within it, including the incomplete tags
+         which store buffer positions -- simon@josefsson.org 2002-09-06
+       */
+      while (p->right)
+	p = p->right;
+      while (p && p != node->down->left)
+	{
+	  if (type_field (p->type) == ASN1_ETYPE_TAG)
+	    {
+	      if (p->type & CONST_EXPLICIT)
+		{
+		  len2 = strtol (p->name, NULL, 10);
+		  _asn1_set_name (p, NULL);
+
+		  asn1_length_der (*counter - len2, temp, &len3);
+		  if (len3 <= (*max_len))
+		    {
+		      memmove (der + len2 + len3, der + len2,
+			       *counter - len2);
+		      memcpy (der + len2, temp, len3);
+		    }
+		  *max_len -= len3;
+		  *counter += len3;
+		  is_tag_implicit = 0;
+		}
+	      else
+		{		/* CONST_IMPLICIT */
+		  if (!is_tag_implicit)
+		    {
+		      is_tag_implicit = 1;
+		    }
+		}
+	    }
+	  p = p->left;
+	}
+    }
+
+  if (*max_len < 0)
+    return ASN1_MEM_ERROR;
+
+  return ASN1_SUCCESS;
+}
+
+const tag_and_class_st _asn1_tags[] = {
+  [ASN1_ETYPE_GENERALSTRING] =
+    {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"},
+  [ASN1_ETYPE_NUMERIC_STRING] =
+    {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"},
+  [ASN1_ETYPE_IA5_STRING] =
+    {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"},
+  [ASN1_ETYPE_TELETEX_STRING] =
+    {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"},
+  [ASN1_ETYPE_PRINTABLE_STRING] =
+    {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"},
+  [ASN1_ETYPE_UNIVERSAL_STRING] =
+    {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"},
+  [ASN1_ETYPE_BMP_STRING] =
+    {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"},
+  [ASN1_ETYPE_UTF8_STRING] =
+    {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"},
+  [ASN1_ETYPE_VISIBLE_STRING] =
+    {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"},
+  [ASN1_ETYPE_OCTET_STRING] =
+    {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"},
+  [ASN1_ETYPE_BIT_STRING] =
+    {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"},
+  [ASN1_ETYPE_OBJECT_ID] =
+    {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"},
+  [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"},
+  [ASN1_ETYPE_BOOLEAN] =
+    {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"},
+  [ASN1_ETYPE_INTEGER] =
+    {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"},
+  [ASN1_ETYPE_ENUMERATED] =
+    {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"},
+  [ASN1_ETYPE_SEQUENCE] =
+    {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+     "type:SEQUENCE"},
+  [ASN1_ETYPE_SEQUENCE_OF] =
+    {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+     "type:SEQ_OF"},
+  [ASN1_ETYPE_SET] =
+    {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"},
+  [ASN1_ETYPE_SET_OF] =
+    {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+     "type:SET_OF"},
+  [ASN1_ETYPE_GENERALIZED_TIME] =
+    {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"},
+  [ASN1_ETYPE_UTC_TIME] =
+    {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"},
+};
+
+unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]);
+
+/******************************************************/
+/* Function : _asn1_insert_tag_der                    */
+/* Description: creates the DER coding of tags of one */
+/* NODE.                                              */
+/* Parameters:                                        */
+/*   node: pointer to the tree element.               */
+/*   der: string returned                             */
+/*   counter: number of meaningful bytes of DER       */
+/*            (counter[0]..der[*counter-1]).          */
+/*   max_len: size of der vector                      */
+/* Return:                                            */
+/*   ASN1_GENERIC_ERROR if the type is unknown,       */
+/*   ASN1_MEM_ERROR if der vector isn't big enough,   */
+/*   otherwise ASN1_SUCCESS.                          */
+/******************************************************/
+static int
+_asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter,
+		      int *max_len)
+{
+  asn1_node p;
+  int tag_len, is_tag_implicit;
+  unsigned char class, class_implicit =
+    0, temp[MAX (SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)];
+  unsigned long tag_implicit = 0;
+  unsigned char tag_der[MAX_TAG_LEN];
+
+  is_tag_implicit = 0;
+
+  if (node->type & CONST_TAG)
+    {
+      p = node->down;
+      while (p)
+	{
+	  if (type_field (p->type) == ASN1_ETYPE_TAG)
+	    {
+	      if (p->type & CONST_APPLICATION)
+		class = ASN1_CLASS_APPLICATION;
+	      else if (p->type & CONST_UNIVERSAL)
+		class = ASN1_CLASS_UNIVERSAL;
+	      else if (p->type & CONST_PRIVATE)
+		class = ASN1_CLASS_PRIVATE;
+	      else
+		class = ASN1_CLASS_CONTEXT_SPECIFIC;
+
+	      if (p->type & CONST_EXPLICIT)
+		{
+		  if (is_tag_implicit)
+		    _asn1_tag_der (class_implicit, tag_implicit, tag_der,
+				   &tag_len);
+		  else
+		    _asn1_tag_der (class | ASN1_CLASS_STRUCTURED,
+				   _asn1_strtoul (p->value, NULL, 10),
+				   tag_der, &tag_len);
+
+		  *max_len -= tag_len;
+		  if (der && *max_len >= 0)
+		    memcpy (der + *counter, tag_der, tag_len);
+		  *counter += tag_len;
+
+		  _asn1_ltostr (*counter, (char *) temp);
+		  _asn1_set_name (p, (const char *) temp);
+
+		  is_tag_implicit = 0;
+		}
+	      else
+		{		/* CONST_IMPLICIT */
+		  if (!is_tag_implicit)
+		    {
+		      if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) ||
+			  (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF)
+			  || (type_field (node->type) == ASN1_ETYPE_SET)
+			  || (type_field (node->type) == ASN1_ETYPE_SET_OF))
+			class |= ASN1_CLASS_STRUCTURED;
+		      class_implicit = class;
+		      tag_implicit = _asn1_strtoul (p->value, NULL, 10);
+		      is_tag_implicit = 1;
+		    }
+		}
+	    }
+	  p = p->right;
+	}
+    }
+
+  if (is_tag_implicit)
+    {
+      _asn1_tag_der (class_implicit, tag_implicit, tag_der, &tag_len);
+    }
+  else
+    {
+      unsigned type = type_field (node->type);
+      switch (type)
+	{
+	CASE_HANDLED_ETYPES:
+	  _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag,
+			 tag_der, &tag_len);
+	  break;
+	case ASN1_ETYPE_TAG:
+	case ASN1_ETYPE_CHOICE:
+	case ASN1_ETYPE_ANY:
+	  tag_len = 0;
+	  break;
+	default:
+	  return ASN1_GENERIC_ERROR;
+	}
+    }
+
+  *max_len -= tag_len;
+  if (der && *max_len >= 0)
+    memcpy (der + *counter, tag_der, tag_len);
+  *counter += tag_len;
+
+  if (*max_len < 0)
+    return ASN1_MEM_ERROR;
+
+  return ASN1_SUCCESS;
+}
+
+/******************************************************/
+/* Function : _asn1_ordering_set                      */
+/* Description: puts the elements of a SET type in    */
+/* the correct order according to DER rules.          */
+/* Parameters:                                        */
+/*   der: string with the DER coding.                 */
+/*   node: pointer to the SET element.                */
+/* Return:                                            */
+/*    ASN1_SUCCESS if successful                      */
+/*    or an error value.                              */
+/******************************************************/
+static int
+_asn1_ordering_set (unsigned char *der, int der_len, asn1_node node)
+{
+  struct vet
+  {
+    int end;
+    unsigned long value;
+    struct vet *next, *prev;
+  };
+
+  int counter, len, len2;
+  struct vet *first, *last, *p_vet, *p2_vet;
+  asn1_node p;
+  unsigned char class, *temp;
+  unsigned long tag, t;
+  int err;
+
+  counter = 0;
+
+  if (type_field (node->type) != ASN1_ETYPE_SET)
+    return ASN1_VALUE_NOT_VALID;
+
+  p = node->down;
+  while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) ||
+	       (type_field (p->type) == ASN1_ETYPE_SIZE)))
+    p = p->right;
+
+  if ((p == NULL) || (p->right == NULL))
+    return ASN1_SUCCESS;
+
+  first = last = NULL;
+  while (p)
+    {
+      p_vet = malloc (sizeof (struct vet));
+      if (p_vet == NULL)
+	{
+	  err = ASN1_MEM_ALLOC_ERROR;
+	  goto error;
+	}
+
+      p_vet->next = NULL;
+      p_vet->prev = last;
+      if (first == NULL)
+	first = p_vet;
+      else
+	last->next = p_vet;
+      last = p_vet;
+
+      /* tag value calculation */
+      err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2,
+			      &tag);
+      if (err != ASN1_SUCCESS)
+	goto error;
+
+      t = ((unsigned int) class) << 24;
+      p_vet->value = t | tag;
+      counter += len2;
+
+      /* extraction and length */
+      len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
+      if (len2 < 0)
+	{
+	  err = ASN1_DER_ERROR;
+	  goto error;
+	}
+      counter += len + len2;
+
+      p_vet->end = counter;
+      p = p->right;
+    }
+
+  p_vet = first;
+
+  while (p_vet)
+    {
+      p2_vet = p_vet->next;
+      counter = 0;
+      while (p2_vet)
+	{
+	  if (p_vet->value > p2_vet->value)
+	    {
+	      /* change position */
+	      temp = malloc (p_vet->end - counter);
+	      if (temp == NULL)
+		{
+		  err = ASN1_MEM_ALLOC_ERROR;
+		  goto error;
+		}
+
+	      memcpy (temp, der + counter, p_vet->end - counter);
+	      memcpy (der + counter, der + p_vet->end,
+		      p2_vet->end - p_vet->end);
+	      memcpy (der + counter + p2_vet->end - p_vet->end, temp,
+		      p_vet->end - counter);
+	      free (temp);
+
+	      tag = p_vet->value;
+	      p_vet->value = p2_vet->value;
+	      p2_vet->value = tag;
+
+	      p_vet->end = counter + (p2_vet->end - p_vet->end);
+	    }
+	  counter = p_vet->end;
+
+	  p2_vet = p2_vet->next;
+	  p_vet = p_vet->next;
+	}
+
+      if (p_vet != first)
+	p_vet->prev->next = NULL;
+      else
+	first = NULL;
+      free (p_vet);
+      p_vet = first;
+    }
+  return ASN1_SUCCESS;
+
+error:
+  while (first != NULL)
+    {
+      p_vet = first;
+      first = first->next;
+      free (p_vet);
+    }
+  return err;
+}
+
+struct vet
+{
+  unsigned char *ptr;
+  int size;
+};
+
+static int
+setof_compar (const void *_e1, const void *_e2)
+{
+  unsigned length;
+  const struct vet *e1 = _e1, *e2 = _e2;
+  int rval;
+
+  /* The encodings of the component values of a set-of value shall
+   * appear in ascending order, the encodings being compared
+   * as octet strings with the shorter components being
+   * padded at their trailing end with 0-octets.
+   * The padding octets are for comparison purposes and
+   * do not appear in the encodings.
+   */
+  length = MIN (e1->size, e2->size);
+
+  rval = memcmp (e1->ptr, e2->ptr, length);
+  if (rval == 0 && e1->size != e2->size)
+    {
+      if (e1->size > e2->size)
+	rval = 1;
+      else if (e2->size > e1->size)
+	rval = -1;
+    }
+
+  return rval;
+}
+
+/******************************************************/
+/* Function : _asn1_ordering_set_of                   */
+/* Description: puts the elements of a SET OF type in */
+/* the correct order according to DER rules.          */
+/* Parameters:                                        */
+/*   der: string with the DER coding.                 */
+/*   node: pointer to the SET OF element.             */
+/* Return:                                            */
+/*    ASN1_SUCCESS if successful                      */
+/*    or an error value.                              */
+/******************************************************/
+static int
+_asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node)
+{
+  int counter, len, len2;
+  struct vet *list = NULL, *tlist;
+  unsigned list_size = 0;
+  struct vet *p_vet;
+  asn1_node p;
+  unsigned char class;
+  unsigned i;
+  unsigned char *out = NULL;
+  int err;
+
+  counter = 0;
+
+  if (type_field (node->type) != ASN1_ETYPE_SET_OF)
+    return ASN1_VALUE_NOT_VALID;
+
+  p = node->down;
+  while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) ||
+	       (type_field (p->type) == ASN1_ETYPE_SIZE)))
+    p = p->right;
+  if (p == NULL)
+    return ASN1_VALUE_NOT_VALID;
+  p = p->right;
+
+  if ((p == NULL) || (p->right == NULL))
+    return ASN1_SUCCESS;
+
+  while (p)
+    {
+      list_size++;
+      tlist = realloc (list, list_size * sizeof (struct vet));
+      if (tlist == NULL)
+	{
+	  err = ASN1_MEM_ALLOC_ERROR;
+	  goto error;
+	}
+      list = tlist;
+      p_vet = &list[list_size - 1];
+
+      p_vet->ptr = der + counter;
+      p_vet->size = 0;
+
+      /* extraction of tag and length */
+      if (der_len - counter > 0)
+	{
+	  err = asn1_get_tag_der (der + counter, der_len - counter, &class,
+				  &len, NULL);
+	  if (err != ASN1_SUCCESS)
+	    goto error;
+	  counter += len;
+	  p_vet->size += len;
+
+	  len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
+	  if (len2 < 0)
+	    {
+	      err = ASN1_DER_ERROR;
+	      goto error;
+	    }
+	  counter += len + len2;
+	  p_vet->size += len + len2;
+
+	}
+      else
+	{
+	  err = ASN1_DER_ERROR;
+	  goto error;
+	}
+      p = p->right;
+    }
+
+  if (counter > der_len)
+    {
+      err = ASN1_DER_ERROR;
+      goto error;
+    }
+
+  qsort (list, list_size, sizeof (struct vet), setof_compar);
+
+  out = malloc (der_len);
+  if (out == NULL)
+    {
+      err = ASN1_MEM_ERROR;
+      goto error;
+    }
+
+  /* the sum of p_vet->size == der_len */
+  counter = 0;
+  for (i = 0; i < list_size; i++)
+    {
+      p_vet = &list[i];
+      memcpy (out + counter, p_vet->ptr, p_vet->size);
+      counter += p_vet->size;
+    }
+  memcpy (der, out, der_len);
+  free (out);
+
+  err = ASN1_SUCCESS;
+
+error:
+  free (list);
+  return err;
+}
+
+/**
+ * asn1_der_coding:
+ * @element: pointer to an ASN1 element
+ * @name: the name of the structure you want to encode (it must be
+ *   inside *POINTER).
+ * @ider: vector that will contain the DER encoding. DER must be a
+ *   pointer to memory cells already allocated.
+ * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy
+ *   holds the sizeof of der vector.
+ * @ErrorDescription: return the error description or an empty
+ *   string if success.
+ *
+ * Creates the DER encoding for the NAME structure (inside *POINTER
+ * structure).
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if @name is not a valid element, %ASN1_VALUE_NOT_FOUND if there
+ *   is an element without a value, %ASN1_MEM_ERROR if the @ider
+ *   vector isn't big enough and in this case @len will contain the
+ *   length needed.
+ **/
+int
+asn1_der_coding (asn1_node_const element, const char *name, void *ider,
+		 int *len, char *ErrorDescription)
+{
+  asn1_node node, p, p2;
+  unsigned char temp[MAX (LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)];
+  int counter, counter_old, len2, len3, move, max_len, max_len_old;
+  int err;
+  unsigned char *der = ider;
+  unsigned char dummy;
+
+  if (ErrorDescription)
+    ErrorDescription[0] = 0;
+
+  node = asn1_find_node (element, name);
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  /* Node is now a locally allocated variable.
+   * That is because in some point we modify the
+   * structure, and I don't know why! --nmav
+   */
+  node = _asn1_copy_structure3 (node);
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  max_len = *len;
+
+  if (der == NULL && max_len > 0)
+    {
+      err = ASN1_VALUE_NOT_VALID;
+      goto error;
+    }
+
+  counter = 0;
+  move = DOWN;
+  p = node;
+
+  while (1)
+    {
+
+      counter_old = counter;
+      max_len_old = max_len;
+      if (move != UP)
+	{
+	  p->start = counter;
+	  err = _asn1_insert_tag_der (p, der, &counter, &max_len);
+	  if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+	    goto error;
+	}
+      switch (type_field (p->type))
+	{
+	case ASN1_ETYPE_NULL:
+	  max_len--;
+	  if (der != NULL && max_len >= 0)
+	    der[counter] = 0;
+	  counter++;
+	  move = RIGHT;
+	  break;
+	case ASN1_ETYPE_BOOLEAN:
+	  if ((p->type & CONST_DEFAULT) && (p->value == NULL))
+	    {
+	      counter = counter_old;
+	      max_len = max_len_old;
+	    }
+	  else
+	    {
+	      if (p->value == NULL)
+		{
+		  _asn1_error_description_value_not_found (p,
+							   ErrorDescription);
+		  err = ASN1_VALUE_NOT_FOUND;
+		  goto error;
+		}
+	      max_len -= 2;
+	      if (der != NULL && max_len >= 0)
+		{
+		  der[counter++] = 1;
+		  if (p->value[0] == 'F')
+		    der[counter++] = 0;
+		  else
+		    der[counter++] = 0xFF;
+		}
+	      else
+		counter += 2;
+	    }
+	  move = RIGHT;
+	  break;
+	case ASN1_ETYPE_INTEGER:
+	case ASN1_ETYPE_ENUMERATED:
+	  if ((p->type & CONST_DEFAULT) && (p->value == NULL))
+	    {
+	      counter = counter_old;
+	      max_len = max_len_old;
+	    }
+	  else
+	    {
+	      if (p->value == NULL)
+		{
+		  _asn1_error_description_value_not_found (p,
+							   ErrorDescription);
+		  err = ASN1_VALUE_NOT_FOUND;
+		  goto error;
+		}
+	      len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+	      if (len2 < 0)
+		{
+		  err = ASN1_DER_ERROR;
+		  goto error;
+		}
+	      max_len -= len2 + len3;
+	      if (der != NULL && max_len >= 0)
+		memcpy (der + counter, p->value, len3 + len2);
+	      counter += len3 + len2;
+	    }
+	  move = RIGHT;
+	  break;
+	case ASN1_ETYPE_OBJECT_ID:
+	  if ((p->type & CONST_DEFAULT) && (p->value == NULL))
+	    {
+	      counter = counter_old;
+	      max_len = max_len_old;
+	    }
+	  else
+	    {
+	      if (p->value == NULL)
+		{
+		  _asn1_error_description_value_not_found (p,
+							   ErrorDescription);
+		  err = ASN1_VALUE_NOT_FOUND;
+		  goto error;
+		}
+	      len2 = max_len;
+	      err =
+		_asn1_object_id_der ((char *) p->value,
+				     der ? der + counter : &dummy, &len2);
+	      if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+		goto error;
+
+	      max_len -= len2;
+	      counter += len2;
+	    }
+	  move = RIGHT;
+	  break;
+	case ASN1_ETYPE_GENERALIZED_TIME:
+	case ASN1_ETYPE_UTC_TIME:
+	  if (p->value == NULL)
+	    {
+	      _asn1_error_description_value_not_found (p, ErrorDescription);
+	      err = ASN1_VALUE_NOT_FOUND;
+	      goto error;
+	    }
+	  len2 = max_len;
+	  err =
+	    _asn1_time_der (p->value, p->value_len,
+			    der ? der + counter : &dummy, &len2);
+	  if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+	    goto error;
+
+	  max_len -= len2;
+	  counter += len2;
+	  move = RIGHT;
+	  break;
+	case ASN1_ETYPE_OCTET_STRING:
+	case ASN1_ETYPE_GENERALSTRING:
+	case ASN1_ETYPE_NUMERIC_STRING:
+	case ASN1_ETYPE_IA5_STRING:
+	case ASN1_ETYPE_TELETEX_STRING:
+	case ASN1_ETYPE_PRINTABLE_STRING:
+	case ASN1_ETYPE_UNIVERSAL_STRING:
+	case ASN1_ETYPE_BMP_STRING:
+	case ASN1_ETYPE_UTF8_STRING:
+	case ASN1_ETYPE_VISIBLE_STRING:
+	case ASN1_ETYPE_BIT_STRING:
+	  if (p->value == NULL)
+	    {
+	      _asn1_error_description_value_not_found (p, ErrorDescription);
+	      err = ASN1_VALUE_NOT_FOUND;
+	      goto error;
+	    }
+	  len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+	  if (len2 < 0)
+	    {
+	      err = ASN1_DER_ERROR;
+	      goto error;
+	    }
+	  max_len -= len2 + len3;
+	  if (der != NULL && max_len >= 0)
+	    memcpy (der + counter, p->value, len3 + len2);
+	  counter += len3 + len2;
+	  move = RIGHT;
+	  break;
+	case ASN1_ETYPE_SEQUENCE:
+	case ASN1_ETYPE_SET:
+	  if (move != UP)
+	    {
+	      p->tmp_ival = counter;
+	      if (p->down == NULL)
+		{
+		  move = UP;
+		  continue;
+		}
+	      else
+		{
+		  p2 = p->down;
+		  while (p2 && (type_field (p2->type) == ASN1_ETYPE_TAG))
+		    p2 = p2->right;
+		  if (p2)
+		    {
+		      p = p2;
+		      move = RIGHT;
+		      continue;
+		    }
+		  move = UP;
+		  continue;
+		}
+	    }
+	  else
+	    {			/* move==UP */
+	      len2 = p->tmp_ival;
+	      p->tmp_ival = 0;
+	      if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0))
+		{
+		  err =
+		    _asn1_ordering_set (der ? der + len2 : &dummy,
+					counter - len2, p);
+		  if (err != ASN1_SUCCESS)
+		    goto error;
+		}
+	      asn1_length_der (counter - len2, temp, &len3);
+	      max_len -= len3;
+	      if (der != NULL && max_len >= 0)
+		{
+		  memmove (der + len2 + len3, der + len2, counter - len2);
+		  memcpy (der + len2, temp, len3);
+		}
+	      counter += len3;
+	      move = RIGHT;
+	    }
+	  break;
+	case ASN1_ETYPE_SEQUENCE_OF:
+	case ASN1_ETYPE_SET_OF:
+	  if (move != UP)
+	    {
+	      p->tmp_ival = counter;
+	      p = p->down;
+	      while ((type_field (p->type) == ASN1_ETYPE_TAG)
+		     || (type_field (p->type) == ASN1_ETYPE_SIZE))
+		p = p->right;
+	      if (p->right)
+		{
+		  p = p->right;
+		  move = RIGHT;
+		  continue;
+		}
+	      else
+		p = _asn1_find_up (p);
+	      move = UP;
+	    }
+	  if (move == UP)
+	    {
+	      len2 = p->tmp_ival;
+	      p->tmp_ival = 0;
+	      if ((type_field (p->type) == ASN1_ETYPE_SET_OF)
+		  && (counter - len2 > 0) && (max_len >= 0))
+		{
+		  err =
+		    _asn1_ordering_set_of (der ? der + len2 : &dummy,
+					   counter - len2, p);
+		  if (err != ASN1_SUCCESS)
+		    goto error;
+		}
+	      asn1_length_der (counter - len2, temp, &len3);
+	      max_len -= len3;
+	      if (der != NULL && max_len >= 0)
+		{
+		  memmove (der + len2 + len3, der + len2, counter - len2);
+		  memcpy (der + len2, temp, len3);
+		}
+	      counter += len3;
+	      move = RIGHT;
+	    }
+	  break;
+	case ASN1_ETYPE_ANY:
+	  if (p->value == NULL)
+	    {
+	      _asn1_error_description_value_not_found (p, ErrorDescription);
+	      err = ASN1_VALUE_NOT_FOUND;
+	      goto error;
+	    }
+	  len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+	  if (len2 < 0)
+	    {
+	      err = ASN1_DER_ERROR;
+	      goto error;
+	    }
+	  max_len -= len2;
+	  if (der != NULL && max_len >= 0)
+	    memcpy (der + counter, p->value + len3, len2);
+	  counter += len2;
+	  move = RIGHT;
+	  break;
+	default:
+	  move = (move == UP) ? RIGHT : DOWN;
+	  break;
+	}
+
+      if ((move != DOWN) && (counter != counter_old))
+	{
+	  p->end = counter - 1;
+	  err = _asn1_complete_explicit_tag (p, der, &counter, &max_len);
+	  if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+	    goto error;
+	}
+
+      if (p == node && move != DOWN)
+	break;
+
+      if (move == DOWN)
+	{
+	  if (p->down)
+	    p = p->down;
+	  else
+	    move = RIGHT;
+	}
+      if (move == RIGHT)
+	{
+	  if (p->right)
+	    p = p->right;
+	  else
+	    move = UP;
+	}
+      if (move == UP)
+	p = _asn1_find_up (p);
+    }
+
+  *len = counter;
+
+  if (max_len < 0)
+    {
+      err = ASN1_MEM_ERROR;
+      goto error;
+    }
+
+  err = ASN1_SUCCESS;
+
+error:
+  asn1_delete_structure (&node);
+  return err;
+}
diff --git a/grub-core/lib/libtasn1/lib/decoding.c b/grub-core/lib/libtasn1/lib/decoding.c
new file mode 100644
index 0000000..b9245c4
--- /dev/null
+++ b/grub-core/lib/libtasn1/lib/decoding.c
@@ -0,0 +1,2501 @@
+/*
+ * Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+
+/*****************************************************/
+/* File: decoding.c                                  */
+/* Description: Functions to manage DER decoding     */
+/*****************************************************/
+
+#include <int.h>
+#include <parser_aux.h>
+#include <gstr.h>
+#include <structure.h>
+#include <element.h>
+#include <limits.h>
+#include <intprops.h>
+#include "c-ctype.h"
+
+#ifdef DEBUG
+# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
+#else
+# define warn()
+#endif
+
+#define IS_ERR(len, flags) (len < -1 || ((flags & ASN1_DECODE_FLAG_STRICT_DER) && len < 0))
+
+#define HAVE_TWO(x) (x>=2?1:0)
+
+/* Decoding flags (dflags) used in several decoding functions.
+ *  DECODE_FLAG_HAVE_TAG: The provided buffer includes a tag
+ *  DECODE_FLAG_CONSTRUCTED: The provided buffer is of indefinite encoding (useful
+ *                           when no tags are present).
+ *  DECODE_FLAG_LEVEL1: Internal flag to indicate a level of recursion for BER strings.
+ *  DECODE_FLAG_LEVEL2: Internal flag to indicate two levels of recursion for BER strings.
+ *  DECODE_FLAG_LEVEL3: Internal flag to indicate three levels of recursion for BER strings.
+ *                      This is the maximum levels of recursion possible to prevent stack
+ *                      exhaustion.
+ */
+
+#define DECODE_FLAG_HAVE_TAG 1
+#define DECODE_FLAG_CONSTRUCTED (1<<1)
+#define DECODE_FLAG_LEVEL1 (1<<2)
+#define DECODE_FLAG_LEVEL2 (1<<3)
+#define DECODE_FLAG_LEVEL3 (1<<4)
+
+#define DECR_LEN(l, s) do { \
+	  l -= s; \
+	  if (l < 0) { \
+	    warn(); \
+	    result = ASN1_DER_ERROR; \
+	    goto cleanup; \
+	  } \
+	} while (0)
+
+static int
+_asn1_get_indefinite_length_string (const unsigned char *der, int der_len,
+				    int *len);
+
+static int
+_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
+			 unsigned int _der_len, unsigned char **str,
+			 unsigned int *str_len, unsigned int *ber_len,
+			 unsigned dflags);
+
+static int
+_asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
+			 unsigned int _der_len, const unsigned char **str,
+			 unsigned int *str_len, unsigned dflags);
+
+static void
+_asn1_error_description_tag_error (asn1_node node, char *ErrorDescription)
+{
+
+  Estrcpy (ErrorDescription, ":: tag error near element '");
+  _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription),
+			   ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40);
+  Estrcat (ErrorDescription, "'");
+
+}
+
+/**
+ * asn1_get_length_der:
+ * @der: DER data to decode.
+ * @der_len: Length of DER data to decode.
+ * @len: Output variable containing the length of the DER length field.
+ *
+ * Extract a length field from DER data.
+ *
+ * Returns: Return the decoded length value, or -1 on indefinite
+ *   length, or -2 when the value was too big to fit in a int, or -4
+ *   when the decoded length value plus @len would exceed @der_len.
+ **/
+long
+asn1_get_length_der (const unsigned char *der, int der_len, int *len)
+{
+  unsigned int ans;
+  int k, punt, sum;
+
+  *len = 0;
+  if (der_len <= 0)
+    return 0;
+
+  if (!(der[0] & 128))
+    {
+      /* short form */
+      *len = 1;
+      ans = der[0];
+    }
+  else
+    {
+      /* Long form */
+      k = der[0] & 0x7F;
+      punt = 1;
+      if (k)
+	{			/* definite length method */
+	  ans = 0;
+	  while (punt <= k && punt < der_len)
+	    {
+	      if (INT_MULTIPLY_OVERFLOW (ans, 256))
+		return -2;
+	      ans *= 256;
+
+	      if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt])))
+		return -2;
+	      ans += der[punt];
+	      punt++;
+	    }
+	}
+      else
+	{			/* indefinite length method */
+	  *len = punt;
+	  return -1;
+	}
+
+      *len = punt;
+    }
+
+  sum = ans;
+  if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len)))
+    return -2;
+  sum += *len;
+
+  if (sum > der_len)
+    return -4;
+
+  return ans;
+}
+
+/**
+ * asn1_get_tag_der:
+ * @der: DER data to decode.
+ * @der_len: Length of DER data to decode.
+ * @cls: Output variable containing decoded class.
+ * @len: Output variable containing the length of the DER TAG data.
+ * @tag: Output variable containing the decoded tag (may be %NULL).
+ *
+ * Decode the class and TAG from DER code.
+ *
+ * Returns: Returns %ASN1_SUCCESS on success, or an error.
+ **/
+int
+asn1_get_tag_der (const unsigned char *der, int der_len,
+		  unsigned char *cls, int *len, unsigned long *tag)
+{
+  unsigned int ris;
+  int punt;
+
+  if (der == NULL || der_len < 2 || len == NULL)
+    return ASN1_DER_ERROR;
+
+  *cls = der[0] & 0xE0;
+  if ((der[0] & 0x1F) != 0x1F)
+    {
+      /* short form */
+      *len = 1;
+      ris = der[0] & 0x1F;
+    }
+  else
+    {
+      /* Long form */
+      punt = 1;
+      ris = 0;
+      while (punt < der_len && der[punt] & 128)
+	{
+
+	  if (INT_MULTIPLY_OVERFLOW (ris, 128))
+	    return ASN1_DER_ERROR;
+	  ris *= 128;
+
+	  if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
+	    return ASN1_DER_ERROR;
+	  ris += (der[punt] & 0x7F);
+	  punt++;
+	}
+
+      if (punt >= der_len)
+	return ASN1_DER_ERROR;
+
+      if (INT_MULTIPLY_OVERFLOW (ris, 128))
+	return ASN1_DER_ERROR;
+      ris *= 128;
+
+      if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
+	return ASN1_DER_ERROR;
+      ris += (der[punt] & 0x7F);
+      punt++;
+
+      *len = punt;
+    }
+
+  if (tag)
+    *tag = ris;
+  return ASN1_SUCCESS;
+}
+
+/**
+ * asn1_get_length_ber:
+ * @ber: BER data to decode.
+ * @ber_len: Length of BER data to decode.
+ * @len: Output variable containing the length of the BER length field.
+ *
+ * Extract a length field from BER data.  The difference to
+ * asn1_get_length_der() is that this function will return a length
+ * even if the value has indefinite encoding.
+ *
+ * Returns: Return the decoded length value, or negative value when
+ *   the value was too big.
+ *
+ * Since: 2.0
+ **/
+long
+asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len)
+{
+  int ret;
+  long err;
+
+  ret = asn1_get_length_der (ber, ber_len, len);
+
+  if (ret == -1 && ber_len > 1)
+    {				/* indefinite length method */
+      err = _asn1_get_indefinite_length_string (ber + 1, ber_len - 1, &ret);
+      if (err != ASN1_SUCCESS)
+	return -3;
+    }
+
+  return ret;
+}
+
+/**
+ * asn1_get_octet_der:
+ * @der: DER data to decode containing the OCTET SEQUENCE.
+ * @der_len: The length of the @der data to decode.
+ * @ret_len: Output variable containing the encoded length of the DER data.
+ * @str: Pre-allocated output buffer to put decoded OCTET SEQUENCE in.
+ * @str_size: Length of pre-allocated output buffer.
+ * @str_len: Output variable containing the length of the contents of the OCTET SEQUENCE.
+ *
+ * Extract an OCTET SEQUENCE from DER data. Note that this function
+ * expects the DER data past the tag field, i.e., the length and
+ * content octets.
+ *
+ * Returns: Returns %ASN1_SUCCESS on success, or an error.
+ **/
+int
+asn1_get_octet_der (const unsigned char *der, int der_len,
+		    int *ret_len, unsigned char *str, int str_size,
+		    int *str_len)
+{
+  int len_len = 0;
+
+  if (der_len <= 0)
+    return ASN1_GENERIC_ERROR;
+
+  *str_len = asn1_get_length_der (der, der_len, &len_len);
+
+  if (*str_len < 0)
+    return ASN1_DER_ERROR;
+
+  *ret_len = *str_len + len_len;
+  if (str_size >= *str_len)
+    {
+      if (*str_len > 0 && str != NULL)
+	memcpy (str, der + len_len, *str_len);
+    }
+  else
+    {
+      return ASN1_MEM_ERROR;
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+/*-
+ * _asn1_get_time_der:
+ * @type: %ASN1_ETYPE_GENERALIZED_TIME or %ASN1_ETYPE_UTC_TIME
+ * @der: DER data to decode containing the time
+ * @der_len: Length of DER data to decode.
+ * @ret_len: Output variable containing the length of the DER data.
+ * @str: Pre-allocated output buffer to put the textual time in.
+ * @str_size: Length of pre-allocated output buffer.
+ * @flags: Zero or %ASN1_DECODE_FLAG_STRICT_DER
+ *
+ * Performs basic checks in the DER encoded time object and returns its textual form.
+ * The textual form will be in the YYYYMMDD000000Z format for GeneralizedTime
+ * and YYMMDD000000Z for UTCTime.
+ *
+ * Returns: %ASN1_SUCCESS on success, or an error.
+ -*/
+static int
+_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len,
+		    int *ret_len, char *str, int str_size, unsigned flags)
+{
+  int len_len, str_len;
+  unsigned i;
+  unsigned sign_count = 0;
+  unsigned dot_count = 0;
+  const unsigned char *p;
+
+  if (der_len <= 0 || str == NULL)
+    return ASN1_DER_ERROR;
+
+  str_len = asn1_get_length_der (der, der_len, &len_len);
+  if (str_len <= 0 || str_size < str_len)
+    return ASN1_DER_ERROR;
+
+  /* perform some sanity checks on the data */
+  if (str_len < 8)
+    {
+      warn ();
+      return ASN1_TIME_ENCODING_ERROR;
+    }
+
+  if ((flags & ASN1_DECODE_FLAG_STRICT_DER)
+      && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME))
+    {
+      p = &der[len_len];
+      for (i = 0; i < (unsigned) (str_len - 1); i++)
+	{
+	  if (c_isdigit (p[i]) == 0)
+	    {
+	      if (type == ASN1_ETYPE_GENERALIZED_TIME)
+		{
+		  /* tolerate lax encodings */
+		  if (p[i] == '.' && dot_count == 0)
+		    {
+		      dot_count++;
+		      continue;
+		    }
+
+		  /* This is not really valid DER, but there are
+		   * structures using that */
+		  if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) &&
+		      (p[i] == '+' || p[i] == '-') && sign_count == 0)
+		    {
+		      sign_count++;
+		      continue;
+		    }
+		}
+
+	      warn ();
+	      return ASN1_TIME_ENCODING_ERROR;
+	    }
+	}
+
+      if (sign_count == 0 && p[str_len - 1] != 'Z')
+	{
+	  warn ();
+	  return ASN1_TIME_ENCODING_ERROR;
+	}
+    }
+  memcpy (str, der + len_len, str_len);
+  str[str_len] = 0;
+  *ret_len = str_len + len_len;
+
+  return ASN1_SUCCESS;
+}
+
+/**
+ * asn1_get_object_id_der:
+ * @der: DER data to decode containing the OBJECT IDENTIFIER
+ * @der_len: Length of DER data to decode.
+ * @ret_len: Output variable containing the length of the DER data.
+ * @str: Pre-allocated output buffer to put the textual object id in.
+ * @str_size: Length of pre-allocated output buffer.
+ *
+ * Converts a DER encoded object identifier to its textual form. This
+ * function expects the DER object identifier without the tag.
+ *
+ * Returns: %ASN1_SUCCESS on success, or an error.
+ **/
+int
+asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len,
+			char *str, int str_size)
+{
+  int len_len, len, k;
+  int leading, parsed;
+  char temp[LTOSTR_MAX_SIZE];
+  uint64_t val, val1, val0;
+
+  *ret_len = 0;
+  if (str && str_size > 0)
+    str[0] = 0;			/* no oid */
+
+  if (str == NULL || der_len <= 0)
+    return ASN1_GENERIC_ERROR;
+
+  len = asn1_get_length_der (der, der_len, &len_len);
+
+  if (len <= 0 || len + len_len > der_len)
+    return ASN1_DER_ERROR;
+
+  /* leading octet can never be 0x80 */
+  if (der[len_len] == 0x80)
+    return ASN1_DER_ERROR;
+
+  val0 = 0;
+
+  for (k = 0; k < len; k++)
+    {
+      if (INT_LEFT_SHIFT_OVERFLOW (val0, 7))
+	return ASN1_DER_ERROR;
+
+      val0 <<= 7;
+      val0 |= der[len_len + k] & 0x7F;
+      if (!(der[len_len + k] & 0x80))
+	break;
+    }
+  parsed = ++k;
+
+  /* val0 = (X*40) + Y, X={0,1,2}, Y<=39 when X={0,1} */
+  /* X = val, Y = val1 */
+
+  /* check if X == 0  */
+  val = 0;
+  val1 = val0;
+  if (val1 > 39)
+    {
+      val = 1;
+      val1 = val0 - 40;
+      if (val1 > 39)
+	{
+	  val = 2;
+	  val1 = val0 - 80;
+	}
+    }
+
+  _asn1_str_cpy (str, str_size, _asn1_ltostr (val, temp));
+  _asn1_str_cat (str, str_size, ".");
+  _asn1_str_cat (str, str_size, _asn1_ltostr (val1, temp));
+
+  val = 0;
+  leading = 1;
+  for (k = parsed; k < len; k++)
+    {
+      /* X.690 mandates that the leading byte must never be 0x80
+       */
+      if (leading != 0 && der[len_len + k] == 0x80)
+	return ASN1_DER_ERROR;
+      leading = 0;
+
+      /* check for wrap around */
+      if (INT_LEFT_SHIFT_OVERFLOW (val, 7))
+	return ASN1_DER_ERROR;
+
+      val = val << 7;
+      val |= der[len_len + k] & 0x7F;
+
+      if (!(der[len_len + k] & 0x80))
+	{
+	  _asn1_str_cat (str, str_size, ".");
+	  _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
+	  val = 0;
+	  leading = 1;
+	}
+    }
+
+  if (INT_ADD_OVERFLOW (len, len_len))
+    return ASN1_DER_ERROR;
+
+  *ret_len = len + len_len;
+
+  return ASN1_SUCCESS;
+}
+
+/**
+ * asn1_get_bit_der:
+ * @der: DER data to decode containing the BIT SEQUENCE.
+ * @der_len: Length of DER data to decode.
+ * @ret_len: Output variable containing the length of the DER data.
+ * @str: Pre-allocated output buffer to put decoded BIT SEQUENCE in.
+ * @str_size: Length of pre-allocated output buffer.
+ * @bit_len: Output variable containing the size of the BIT SEQUENCE.
+ *
+ * Extract a BIT SEQUENCE from DER data.
+ *
+ * Returns: %ASN1_SUCCESS on success, or an error.
+ **/
+int
+asn1_get_bit_der (const unsigned char *der, int der_len,
+		  int *ret_len, unsigned char *str, int str_size,
+		  int *bit_len)
+{
+  int len_len = 0, len_byte;
+
+  if (der_len <= 0)
+    return ASN1_GENERIC_ERROR;
+
+  len_byte = asn1_get_length_der (der, der_len, &len_len) - 1;
+  if (len_byte < 0)
+    return ASN1_DER_ERROR;
+
+  *ret_len = len_byte + len_len + 1;
+  *bit_len = len_byte * 8 - der[len_len];
+
+  if (*bit_len < 0)
+    return ASN1_DER_ERROR;
+
+  if (str_size >= len_byte)
+    {
+      if (len_byte > 0 && str)
+	memcpy (str, der + len_len + 1, len_byte);
+    }
+  else
+    {
+      return ASN1_MEM_ERROR;
+    }
+
+  return ASN1_SUCCESS;
+}
+
+/* tag_len: the total tag length (explicit+inner)
+ * inner_tag_len: the inner_tag length
+ */
+static int
+_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
+		       int *tag_len, int *inner_tag_len, unsigned flags)
+{
+  asn1_node p;
+  int counter, len2, len3, is_tag_implicit;
+  int result;
+  unsigned long tag, tag_implicit = 0;
+  unsigned char class, class2, class_implicit = 0;
+
+  if (der_len <= 0)
+    return ASN1_GENERIC_ERROR;
+
+  counter = is_tag_implicit = 0;
+
+  if (node->type & CONST_TAG)
+    {
+      p = node->down;
+      while (p)
+	{
+	  if (type_field (p->type) == ASN1_ETYPE_TAG)
+	    {
+	      if (p->type & CONST_APPLICATION)
+		class2 = ASN1_CLASS_APPLICATION;
+	      else if (p->type & CONST_UNIVERSAL)
+		class2 = ASN1_CLASS_UNIVERSAL;
+	      else if (p->type & CONST_PRIVATE)
+		class2 = ASN1_CLASS_PRIVATE;
+	      else
+		class2 = ASN1_CLASS_CONTEXT_SPECIFIC;
+
+	      if (p->type & CONST_EXPLICIT)
+		{
+		  if (asn1_get_tag_der
+		      (der + counter, der_len, &class, &len2,
+		       &tag) != ASN1_SUCCESS)
+		    return ASN1_DER_ERROR;
+
+		  DECR_LEN (der_len, len2);
+		  counter += len2;
+
+		  if (flags & ASN1_DECODE_FLAG_STRICT_DER)
+		    len3 =
+		      asn1_get_length_der (der + counter, der_len, &len2);
+		  else
+		    len3 =
+		      asn1_get_length_ber (der + counter, der_len, &len2);
+		  if (len3 < 0)
+		    return ASN1_DER_ERROR;
+
+		  DECR_LEN (der_len, len2);
+		  counter += len2;
+
+		  if (!is_tag_implicit)
+		    {
+		      if ((class != (class2 | ASN1_CLASS_STRUCTURED)) ||
+			  (tag != strtoul ((char *) p->value, NULL, 10)))
+			return ASN1_TAG_ERROR;
+		    }
+		  else
+		    {		/* ASN1_TAG_IMPLICIT */
+		      if ((class != class_implicit) || (tag != tag_implicit))
+			return ASN1_TAG_ERROR;
+		    }
+		  is_tag_implicit = 0;
+		}
+	      else
+		{		/* ASN1_TAG_IMPLICIT */
+		  if (!is_tag_implicit)
+		    {
+		      if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) ||
+			  (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF)
+			  || (type_field (node->type) == ASN1_ETYPE_SET)
+			  || (type_field (node->type) == ASN1_ETYPE_SET_OF))
+			class2 |= ASN1_CLASS_STRUCTURED;
+		      class_implicit = class2;
+		      tag_implicit = strtoul ((char *) p->value, NULL, 10);
+		      is_tag_implicit = 1;
+		    }
+		}
+	    }
+	  p = p->right;
+	}
+    }
+
+  if (is_tag_implicit)
+    {
+      if (asn1_get_tag_der
+	  (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS)
+	return ASN1_DER_ERROR;
+
+      DECR_LEN (der_len, len2);
+
+      if ((class != class_implicit) || (tag != tag_implicit))
+	{
+	  if (type_field (node->type) == ASN1_ETYPE_OCTET_STRING)
+	    {
+	      class_implicit |= ASN1_CLASS_STRUCTURED;
+	      if ((class != class_implicit) || (tag != tag_implicit))
+		return ASN1_TAG_ERROR;
+	    }
+	  else
+	    return ASN1_TAG_ERROR;
+	}
+    }
+  else
+    {
+      unsigned type = type_field (node->type);
+      if (type == ASN1_ETYPE_TAG)
+	{
+	  *tag_len = 0;
+	  if (inner_tag_len)
+	    *inner_tag_len = 0;
+	  return ASN1_SUCCESS;
+	}
+
+      if (asn1_get_tag_der
+	  (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS)
+	return ASN1_DER_ERROR;
+
+      DECR_LEN (der_len, len2);
+
+      switch (type)
+	{
+	case ASN1_ETYPE_NULL:
+	case ASN1_ETYPE_BOOLEAN:
+	case ASN1_ETYPE_INTEGER:
+	case ASN1_ETYPE_ENUMERATED:
+	case ASN1_ETYPE_OBJECT_ID:
+	case ASN1_ETYPE_GENERALSTRING:
+	case ASN1_ETYPE_NUMERIC_STRING:
+	case ASN1_ETYPE_IA5_STRING:
+	case ASN1_ETYPE_TELETEX_STRING:
+	case ASN1_ETYPE_PRINTABLE_STRING:
+	case ASN1_ETYPE_UNIVERSAL_STRING:
+	case ASN1_ETYPE_BMP_STRING:
+	case ASN1_ETYPE_UTF8_STRING:
+	case ASN1_ETYPE_VISIBLE_STRING:
+	case ASN1_ETYPE_BIT_STRING:
+	case ASN1_ETYPE_SEQUENCE:
+	case ASN1_ETYPE_SEQUENCE_OF:
+	case ASN1_ETYPE_SET:
+	case ASN1_ETYPE_SET_OF:
+	case ASN1_ETYPE_GENERALIZED_TIME:
+	case ASN1_ETYPE_UTC_TIME:
+	  if ((class != _asn1_tags[type].class)
+	      || (tag != _asn1_tags[type].tag))
+	    return ASN1_DER_ERROR;
+	  break;
+
+	case ASN1_ETYPE_OCTET_STRING:
+	  /* OCTET STRING is handled differently to allow
+	   * BER encodings (structured class). */
+	  if (((class != ASN1_CLASS_UNIVERSAL)
+	       && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED)))
+	      || (tag != ASN1_TAG_OCTET_STRING))
+	    return ASN1_DER_ERROR;
+	  break;
+	case ASN1_ETYPE_ANY:
+	  counter -= len2;
+	  break;
+	case ASN1_ETYPE_CHOICE:
+	  counter -= len2;
+	  break;
+	default:
+	  return ASN1_DER_ERROR;
+	  break;
+	}
+    }
+
+  counter += len2;
+  *tag_len = counter;
+  if (inner_tag_len)
+    *inner_tag_len = len2;
+  return ASN1_SUCCESS;
+
+cleanup:
+  return result;
+}
+
+static int
+extract_tag_der_recursive (asn1_node node, const unsigned char *der,
+			   int der_len, int *ret_len, int *inner_len,
+			   unsigned flags)
+{
+  asn1_node p;
+  int ris = ASN1_DER_ERROR;
+
+  if (type_field (node->type) == ASN1_ETYPE_CHOICE)
+    {
+      p = node->down;
+      while (p)
+	{
+	  ris =
+	    _asn1_extract_tag_der (p, der, der_len, ret_len, inner_len,
+				   flags);
+	  if (ris == ASN1_SUCCESS)
+	    break;
+	  p = p->right;
+	}
+
+      *ret_len = 0;
+      return ris;
+    }
+  else
+    return _asn1_extract_tag_der (node, der, der_len, ret_len, inner_len,
+				  flags);
+}
+
+static int
+_asn1_delete_not_used (asn1_node node)
+{
+  asn1_node p, p2;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node;
+  while (p)
+    {
+      if (p->type & CONST_NOT_USED)
+	{
+	  p2 = NULL;
+	  if (p != node)
+	    {
+	      p2 = _asn1_find_left (p);
+	      if (!p2)
+		p2 = _asn1_find_up (p);
+	    }
+	  asn1_delete_structure (&p);
+	  p = p2;
+	}
+
+      if (!p)
+	break;			/* reach node */
+
+      if (p->down)
+	{
+	  p = p->down;
+	}
+      else
+	{
+	  if (p == node)
+	    p = NULL;
+	  else if (p->right)
+	    p = p->right;
+	  else
+	    {
+	      while (1)
+		{
+		  p = _asn1_find_up (p);
+		  if (p == node)
+		    {
+		      p = NULL;
+		      break;
+		    }
+		  if (p->right)
+		    {
+		      p = p->right;
+		      break;
+		    }
+		}
+	    }
+	}
+    }
+  return ASN1_SUCCESS;
+}
+
+static int
+_asn1_get_indefinite_length_string (const unsigned char *der,
+				    int der_len, int *len)
+{
+  int len2, len3, counter, indefinite;
+  int result;
+  unsigned long tag;
+  unsigned char class;
+
+  counter = indefinite = 0;
+
+  while (1)
+    {
+      if (HAVE_TWO (der_len) && (der[counter] == 0)
+	  && (der[counter + 1] == 0))
+	{
+	  counter += 2;
+	  DECR_LEN (der_len, 2);
+
+	  indefinite--;
+	  if (indefinite <= 0)
+	    break;
+	  else
+	    continue;
+	}
+
+      if (asn1_get_tag_der
+	  (der + counter, der_len, &class, &len2, &tag) != ASN1_SUCCESS)
+	return ASN1_DER_ERROR;
+
+      DECR_LEN (der_len, len2);
+      counter += len2;
+
+      len2 = asn1_get_length_der (der + counter, der_len, &len3);
+      if (len2 < -1)
+	return ASN1_DER_ERROR;
+
+      if (len2 == -1)
+	{
+	  indefinite++;
+	  counter += 1;
+	  DECR_LEN (der_len, 1);
+	}
+      else
+	{
+	  counter += len2 + len3;
+	  DECR_LEN (der_len, len2 + len3);
+	}
+    }
+
+  *len = counter;
+  return ASN1_SUCCESS;
+
+cleanup:
+  return result;
+}
+
+static void
+delete_unneeded_choice_fields (asn1_node p)
+{
+  asn1_node p2;
+
+  while (p->right)
+    {
+      p2 = p->right;
+      asn1_delete_structure (&p2);
+    }
+}
+
+
+/**
+ * asn1_der_decoding2
+ * @element: pointer to an ASN1 structure.
+ * @ider: vector that contains the DER encoding.
+ * @max_ider_len: pointer to an integer giving the information about the
+ *   maximal number of bytes occupied by *@ider. The real size of the DER
+ *   encoding is returned through this pointer.
+ * @flags: flags controlling the behaviour of the function.
+ * @errorDescription: null-terminated string contains details when an
+ *   error occurred.
+ *
+ * Fill the structure *@element with values of a DER encoding string. The
+ * structure must just be created with function asn1_create_element().
+ *
+ * If %ASN1_DECODE_FLAG_ALLOW_PADDING flag is set then the function will ignore
+ * padding after the decoded DER data. Upon a successful return the value of
+ * *@max_ider_len will be set to the number of bytes decoded.
+ *
+ * If %ASN1_DECODE_FLAG_STRICT_DER flag is set then the function will
+ * not decode any BER-encoded elements.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
+ *   %ASN1_DER_ERROR if the der encoding doesn't match the structure
+ *   name (*@ELEMENT deleted).
+ **/
+int
+asn1_der_decoding2 (asn1_node * element, const void *ider, int *max_ider_len,
+		    unsigned int flags, char *errorDescription)
+{
+  asn1_node node, p, p2, p3;
+  char temp[128];
+  int counter, len2, len3, len4, move, ris, tlen;
+  struct node_tail_cache_st tcache = { NULL, NULL };
+  unsigned char class;
+  unsigned long tag;
+  int tag_len;
+  int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len;
+  int inner_tag_len;
+  unsigned char *ptmp;
+  const unsigned char *ptag;
+  const unsigned char *der = ider;
+
+  node = *element;
+
+  if (errorDescription != NULL)
+    errorDescription[0] = 0;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  if (node->type & CONST_OPTION)
+    {
+      result = ASN1_GENERIC_ERROR;
+      warn ();
+      goto cleanup;
+    }
+
+  counter = 0;
+  move = DOWN;
+  p = node;
+  while (1)
+    {
+      tag_len = 0;
+      inner_tag_len = 0;
+      ris = ASN1_SUCCESS;
+      if (move != UP)
+	{
+	  if (p->type & CONST_SET)
+	    {
+	      p2 = _asn1_find_up (p);
+	      len2 = p2->tmp_ival;
+	      if (len2 == -1)
+		{
+		  if (HAVE_TWO (ider_len) && !der[counter]
+		      && !der[counter + 1])
+		    {
+		      p = p2;
+		      move = UP;
+		      counter += 2;
+		      DECR_LEN (ider_len, 2);
+		      continue;
+		    }
+		}
+	      else if (counter == len2)
+		{
+		  p = p2;
+		  move = UP;
+		  continue;
+		}
+	      else if (counter > len2)
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+	      p2 = p2->down;
+	      while (p2)
+		{
+		  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+		    {
+		      ris =
+			extract_tag_der_recursive (p2, der + counter,
+						   ider_len, &len2, NULL,
+						   flags);
+		      if (ris == ASN1_SUCCESS)
+			{
+			  p2->type &= ~CONST_NOT_USED;
+			  p = p2;
+			  break;
+			}
+		    }
+		  p2 = p2->right;
+		}
+	      if (p2 == NULL)
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+	    }
+
+	  /* the position in the DER structure this starts */
+	  p->start = counter;
+	  p->end = total_len - 1;
+
+	  if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+	    {
+	      p2 = _asn1_find_up (p);
+	      len2 = p2->tmp_ival;
+	      if (counter == len2)
+		{
+		  if (p->right)
+		    {
+		      p2 = p->right;
+		      move = RIGHT;
+		    }
+		  else
+		    move = UP;
+
+		  if (p->type & CONST_OPTION)
+		    asn1_delete_structure (&p);
+
+		  p = p2;
+		  continue;
+		}
+	    }
+
+	  if (type_field (p->type) == ASN1_ETYPE_CHOICE)
+	    {
+	      while (p->down)
+		{
+		  ris =
+		    extract_tag_der_recursive (p->down, der + counter,
+					       ider_len, &len2, NULL, flags);
+
+		  if (ris == ASN1_SUCCESS)
+		    {
+		      delete_unneeded_choice_fields (p->down);
+		      break;
+		    }
+		  else if (ris == ASN1_ERROR_TYPE_ANY)
+		    {
+		      result = ASN1_ERROR_TYPE_ANY;
+		      warn ();
+		      goto cleanup;
+		    }
+		  else
+		    {
+		      p2 = p->down;
+		      asn1_delete_structure (&p2);
+		    }
+		}
+
+	      if (p->down == NULL)
+		{
+		  if (!(p->type & CONST_OPTION))
+		    {
+		      result = ASN1_DER_ERROR;
+		      warn ();
+		      goto cleanup;
+		    }
+		}
+	      else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
+		p = p->down;
+
+	      p->start = counter;
+	    }
+
+	  if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+	    {
+	      p2 = _asn1_find_up (p);
+	      len2 = p2->tmp_ival;
+
+	      if ((len2 != -1) && (counter > len2))
+		ris = ASN1_TAG_ERROR;
+	    }
+
+	  if (ris == ASN1_SUCCESS)
+	    ris =
+	      extract_tag_der_recursive (p, der + counter, ider_len,
+					 &tag_len, &inner_tag_len, flags);
+
+	  if (ris != ASN1_SUCCESS)
+	    {
+	      if (p->type & CONST_OPTION)
+		{
+		  p->type |= CONST_NOT_USED;
+		  move = RIGHT;
+		}
+	      else if (p->type & CONST_DEFAULT)
+		{
+		  _asn1_set_value (p, NULL, 0);
+		  move = RIGHT;
+		}
+	      else
+		{
+		  if (errorDescription != NULL)
+		    _asn1_error_description_tag_error (p, errorDescription);
+
+		  result = ASN1_TAG_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+	    }
+	  else
+	    {
+	      DECR_LEN (ider_len, tag_len);
+	      counter += tag_len;
+	    }
+	}
+
+      if (ris == ASN1_SUCCESS)
+	{
+	  switch (type_field (p->type))
+	    {
+	    case ASN1_ETYPE_NULL:
+	      DECR_LEN (ider_len, 1);
+	      if (der[counter])
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+	      counter++;
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_BOOLEAN:
+	      DECR_LEN (ider_len, 2);
+
+	      if (der[counter++] != 1)
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+	      if (der[counter++] == 0)
+		_asn1_set_value (p, "F", 1);
+	      else
+		_asn1_set_value (p, "T", 1);
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_INTEGER:
+	    case ASN1_ETYPE_ENUMERATED:
+	      len2 = asn1_get_length_der (der + counter, ider_len, &len3);
+	      if (len2 < 0)
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+
+	      DECR_LEN (ider_len, len3 + len2);
+
+	      _asn1_set_value (p, der + counter, len3 + len2);
+	      counter += len3 + len2;
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_OBJECT_ID:
+	      result =
+		asn1_get_object_id_der (der + counter, ider_len, &len2,
+					temp, sizeof (temp));
+	      if (result != ASN1_SUCCESS)
+		{
+		  warn ();
+		  goto cleanup;
+		}
+
+	      DECR_LEN (ider_len, len2);
+
+	      tlen = strlen (temp);
+	      if (tlen > 0)
+		_asn1_set_value (p, temp, tlen + 1);
+
+	      counter += len2;
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_GENERALIZED_TIME:
+	    case ASN1_ETYPE_UTC_TIME:
+	      result =
+		_asn1_get_time_der (type_field (p->type), der + counter,
+				    ider_len, &len2, temp, sizeof (temp) - 1,
+				    flags);
+	      if (result != ASN1_SUCCESS)
+		{
+		  warn ();
+		  goto cleanup;
+		}
+
+	      DECR_LEN (ider_len, len2);
+
+	      tlen = strlen (temp);
+	      if (tlen > 0)
+		_asn1_set_value (p, temp, tlen);
+
+	      counter += len2;
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_OCTET_STRING:
+	      if (counter < inner_tag_len)
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+
+	      ptag = der + counter - inner_tag_len;
+	      if ((flags & ASN1_DECODE_FLAG_STRICT_DER)
+		  || !(ptag[0] & ASN1_CLASS_STRUCTURED))
+		{
+		  if (ptag[0] & ASN1_CLASS_STRUCTURED)
+		    {
+		      result = ASN1_DER_ERROR;
+		      warn ();
+		      goto cleanup;
+		    }
+
+		  len2 = asn1_get_length_der (der + counter, ider_len, &len3);
+		  if (len2 < 0)
+		    {
+		      result = ASN1_DER_ERROR;
+		      warn ();
+		      goto cleanup;
+		    }
+
+		  DECR_LEN (ider_len, len3 + len2);
+
+		  _asn1_set_value (p, der + counter, len3 + len2);
+		  counter += len3 + len2;
+		}
+	      else
+		{
+		  unsigned dflags = 0, vlen, ber_len;
+
+		  if (ptag[0] & ASN1_CLASS_STRUCTURED)
+		    dflags |= DECODE_FLAG_CONSTRUCTED;
+
+		  result =
+		    _asn1_decode_simple_ber (type_field (p->type),
+					     der + counter, ider_len, &ptmp,
+					     &vlen, &ber_len, dflags);
+		  if (result != ASN1_SUCCESS)
+		    {
+		      warn ();
+		      goto cleanup;
+		    }
+
+		  DECR_LEN (ider_len, ber_len);
+
+		  _asn1_set_value_lv (p, ptmp, vlen);
+
+		  counter += ber_len;
+		  free (ptmp);
+		}
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_GENERALSTRING:
+	    case ASN1_ETYPE_NUMERIC_STRING:
+	    case ASN1_ETYPE_IA5_STRING:
+	    case ASN1_ETYPE_TELETEX_STRING:
+	    case ASN1_ETYPE_PRINTABLE_STRING:
+	    case ASN1_ETYPE_UNIVERSAL_STRING:
+	    case ASN1_ETYPE_BMP_STRING:
+	    case ASN1_ETYPE_UTF8_STRING:
+	    case ASN1_ETYPE_VISIBLE_STRING:
+	    case ASN1_ETYPE_BIT_STRING:
+	      len2 = asn1_get_length_der (der + counter, ider_len, &len3);
+	      if (len2 < 0)
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+
+	      DECR_LEN (ider_len, len3 + len2);
+
+	      _asn1_set_value (p, der + counter, len3 + len2);
+	      counter += len3 + len2;
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_SEQUENCE:
+	    case ASN1_ETYPE_SET:
+	      if (move == UP)
+		{
+		  len2 = p->tmp_ival;
+		  p->tmp_ival = 0;
+		  if (len2 == -1)
+		    {		/* indefinite length method */
+		      DECR_LEN (ider_len, 2);
+		      if ((der[counter]) || der[counter + 1])
+			{
+			  result = ASN1_DER_ERROR;
+			  warn ();
+			  goto cleanup;
+			}
+		      counter += 2;
+		    }
+		  else
+		    {		/* definite length method */
+		      if (len2 != counter)
+			{
+			  result = ASN1_DER_ERROR;
+			  warn ();
+			  goto cleanup;
+			}
+		    }
+		  move = RIGHT;
+		}
+	      else
+		{		/* move==DOWN || move==RIGHT */
+		  len3 = asn1_get_length_der (der + counter, ider_len, &len2);
+		  if (IS_ERR (len3, flags))
+		    {
+		      result = ASN1_DER_ERROR;
+		      warn ();
+		      goto cleanup;
+		    }
+
+		  DECR_LEN (ider_len, len2);
+		  counter += len2;
+
+		  if (len3 > 0)
+		    {
+		      p->tmp_ival = counter + len3;
+		      move = DOWN;
+		    }
+		  else if (len3 == 0)
+		    {
+		      p2 = p->down;
+		      while (p2)
+			{
+			  if (type_field (p2->type) != ASN1_ETYPE_TAG)
+			    {
+			      p3 = p2->right;
+			      asn1_delete_structure (&p2);
+			      p2 = p3;
+			    }
+			  else
+			    p2 = p2->right;
+			}
+		      move = RIGHT;
+		    }
+		  else
+		    {		/* indefinite length method */
+		      p->tmp_ival = -1;
+		      move = DOWN;
+		    }
+		}
+	      break;
+	    case ASN1_ETYPE_SEQUENCE_OF:
+	    case ASN1_ETYPE_SET_OF:
+	      if (move == UP)
+		{
+		  len2 = p->tmp_ival;
+		  if (len2 == -1)
+		    {		/* indefinite length method */
+		      if (!HAVE_TWO (ider_len)
+			  || ((der[counter]) || der[counter + 1]))
+			{
+			  result = _asn1_append_sequence_set (p, &tcache);
+			  if (result != 0)
+			    {
+			      warn ();
+			      goto cleanup;
+			    }
+			  p = tcache.tail;
+			  move = RIGHT;
+			  continue;
+			}
+
+		      p->tmp_ival = 0;
+		      tcache.tail = NULL;	/* finished decoding this structure */
+		      tcache.head = NULL;
+		      DECR_LEN (ider_len, 2);
+		      counter += 2;
+		    }
+		  else
+		    {		/* definite length method */
+		      if (len2 > counter)
+			{
+			  result = _asn1_append_sequence_set (p, &tcache);
+			  if (result != 0)
+			    {
+			      warn ();
+			      goto cleanup;
+			    }
+			  p = tcache.tail;
+			  move = RIGHT;
+			  continue;
+			}
+
+		      p->tmp_ival = 0;
+		      tcache.tail = NULL;	/* finished decoding this structure */
+		      tcache.head = NULL;
+
+		      if (len2 != counter)
+			{
+			  result = ASN1_DER_ERROR;
+			  warn ();
+			  goto cleanup;
+			}
+		    }
+		}
+	      else
+		{		/* move==DOWN || move==RIGHT */
+		  len3 = asn1_get_length_der (der + counter, ider_len, &len2);
+		  if (IS_ERR (len3, flags))
+		    {
+		      result = ASN1_DER_ERROR;
+		      warn ();
+		      goto cleanup;
+		    }
+
+		  DECR_LEN (ider_len, len2);
+		  counter += len2;
+		  if (len3)
+		    {
+		      if (len3 > 0)
+			{	/* definite length method */
+			  p->tmp_ival = counter + len3;
+			}
+		      else
+			{	/* indefinite length method */
+			  p->tmp_ival = -1;
+			}
+
+		      p2 = p->down;
+		      if (p2 == NULL)
+			{
+			  result = ASN1_DER_ERROR;
+			  warn ();
+			  goto cleanup;
+			}
+
+		      while ((type_field (p2->type) == ASN1_ETYPE_TAG)
+			     || (type_field (p2->type) == ASN1_ETYPE_SIZE))
+			p2 = p2->right;
+		      if (p2->right == NULL)
+			{
+			  result = _asn1_append_sequence_set (p, &tcache);
+			  if (result != 0)
+			    {
+			      warn ();
+			      goto cleanup;
+			    }
+			}
+		      p = p2;
+		    }
+		}
+	      move = RIGHT;
+	      break;
+	    case ASN1_ETYPE_ANY:
+	      /* Check indefinite lenth method in an EXPLICIT TAG */
+
+	      if (!(flags & ASN1_DECODE_FLAG_STRICT_DER)
+		  && (p->type & CONST_TAG) && tag_len == 2
+		  && (der[counter - 1] == 0x80))
+		indefinite = 1;
+	      else
+		indefinite = 0;
+
+	      if (asn1_get_tag_der
+		  (der + counter, ider_len, &class, &len2,
+		   &tag) != ASN1_SUCCESS)
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+
+	      DECR_LEN (ider_len, len2);
+
+	      len4 =
+		asn1_get_length_der (der + counter + len2, ider_len, &len3);
+	      if (IS_ERR (len4, flags))
+		{
+		  result = ASN1_DER_ERROR;
+		  warn ();
+		  goto cleanup;
+		}
+	      if (len4 != -1)	/* definite */
+		{
+		  len2 += len4;
+
+		  DECR_LEN (ider_len, len4 + len3);
+		  _asn1_set_value_lv (p, der + counter, len2 + len3);
+		  counter += len2 + len3;
+		}
+	      else		/* == -1 */
+		{		/* indefinite length */
+		  ider_len += len2;	/* undo DECR_LEN */
+
+		  if (counter == 0)
+		    {
+		      result = ASN1_DER_ERROR;
+		      warn ();
+		      goto cleanup;
+		    }
+
+		  result =
+		    _asn1_get_indefinite_length_string (der + counter,
+							ider_len, &len2);
+		  if (result != ASN1_SUCCESS)
+		    {
+		      warn ();
+		      goto cleanup;
+		    }
+
+		  DECR_LEN (ider_len, len2);
+		  _asn1_set_value_lv (p, der + counter, len2);
+		  counter += len2;
+
+		}
+
+	      /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
+	         an indefinite length method. */
+	      if (indefinite)
+		{
+		  DECR_LEN (ider_len, 2);
+		  if (!der[counter] && !der[counter + 1])
+		    {
+		      counter += 2;
+		    }
+		  else
+		    {
+		      result = ASN1_DER_ERROR;
+		      warn ();
+		      goto cleanup;
+		    }
+		}
+
+	      move = RIGHT;
+	      break;
+	    default:
+	      move = (move == UP) ? RIGHT : DOWN;
+	      break;
+	    }
+	}
+
+      if (p)
+	{
+	  p->end = counter - 1;
+	}
+
+      if (p == node && move != DOWN)
+	break;
+
+      if (move == DOWN)
+	{
+	  if (p->down)
+	    p = p->down;
+	  else
+	    move = RIGHT;
+	}
+      if ((move == RIGHT) && !(p->type & CONST_SET))
+	{
+	  if (p->right)
+	    p = p->right;
+	  else
+	    move = UP;
+	}
+      if (move == UP)
+	p = _asn1_find_up (p);
+    }
+
+  _asn1_delete_not_used (*element);
+
+  if ((ider_len < 0) ||
+      (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0)))
+    {
+      warn ();
+      result = ASN1_DER_ERROR;
+      goto cleanup;
+    }
+
+  *max_ider_len = total_len - ider_len;
+
+  return ASN1_SUCCESS;
+
+cleanup:
+  asn1_delete_structure (element);
+  return result;
+}
+
+
+/**
+ * asn1_der_decoding:
+ * @element: pointer to an ASN1 structure.
+ * @ider: vector that contains the DER encoding.
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @errorDescription: null-terminated string contains details when an
+ *   error occurred.
+ *
+ * Fill the structure *@element with values of a DER encoding
+ * string. The structure must just be created with function
+ * asn1_create_element().
+ *
+ * Note that the *@element variable is provided as a pointer for
+ * historical reasons.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
+ *   %ASN1_DER_ERROR if the der encoding doesn't match the structure
+ *   name (*@ELEMENT deleted).
+ **/
+int
+asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
+		   char *errorDescription)
+{
+  return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription);
+}
+
+/**
+ * asn1_der_decoding_element:
+ * @structure: pointer to an ASN1 structure
+ * @elementName: name of the element to fill
+ * @ider: vector that contains the DER encoding of the whole structure.
+ * @len: number of bytes of *der: der[0]..der[len-1]
+ * @errorDescription: null-terminated string contains details when an
+ *   error occurred.
+ *
+ * Fill the element named @ELEMENTNAME with values of a DER encoding
+ * string.  The structure must just be created with function
+ * asn1_create_element().  The DER vector must contain the encoding
+ * string of the whole @STRUCTURE.  If an error occurs during the
+ * decoding procedure, the *@STRUCTURE is deleted and set equal to
+ * %NULL.
+ *
+ * This function is deprecated and may just be an alias to asn1_der_decoding
+ * in future versions. Use asn1_der_decoding() instead.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if ELEMENT is %NULL or @elementName == NULL, and
+ *   %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't
+ *   match the structure @structure (*ELEMENT deleted).
+ **/
+int
+asn1_der_decoding_element (asn1_node * structure, const char *elementName,
+			   const void *ider, int len, char *errorDescription)
+{
+  return asn1_der_decoding (structure, ider, len, errorDescription);
+}
+
+/**
+ * asn1_der_decoding_startEnd:
+ * @element: pointer to an ASN1 element
+ * @ider: vector that contains the DER encoding.
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]
+ * @name_element: an element of NAME structure.
+ * @start: the position of the first byte of NAME_ELEMENT decoding
+ *   (@ider[*start])
+ * @end: the position of the last byte of NAME_ELEMENT decoding
+ *  (@ider[*end])
+ *
+ * Find the start and end point of an element in a DER encoding
+ * string. I mean that if you have a der encoding and you have already
+ * used the function asn1_der_decoding() to fill a structure, it may
+ * happen that you want to find the piece of string concerning an
+ * element of the structure.
+ *
+ * One example is the sequence "tbsCertificate" inside an X509
+ * certificate.
+ *
+ * Note that since libtasn1 3.7 the @ider and @ider_len parameters
+ * can be omitted, if the element is already decoded using asn1_der_decoding().
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if ELEMENT is %asn1_node EMPTY or @name_element is not a valid
+ *   element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding
+ *   doesn't match the structure ELEMENT.
+ **/
+int
+asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len,
+			    const char *name_element, int *start, int *end)
+{
+  asn1_node node, node_to_find;
+  int result = ASN1_DER_ERROR;
+
+  node = element;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  node_to_find = asn1_find_node (node, name_element);
+
+  if (node_to_find == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  *start = node_to_find->start;
+  *end = node_to_find->end;
+
+  if (*start == 0 && *end == 0)
+    {
+      if (ider == NULL || ider_len == 0)
+	return ASN1_GENERIC_ERROR;
+
+      /* it seems asn1_der_decoding() wasn't called before. Do it now */
+      result = asn1_der_decoding (&node, ider, ider_len, NULL);
+      if (result != ASN1_SUCCESS)
+	{
+	  warn ();
+	  return result;
+	}
+
+      node_to_find = asn1_find_node (node, name_element);
+      if (node_to_find == NULL)
+	return ASN1_ELEMENT_NOT_FOUND;
+
+      *start = node_to_find->start;
+      *end = node_to_find->end;
+    }
+
+  if (*end < *start)
+    return ASN1_GENERIC_ERROR;
+
+  return ASN1_SUCCESS;
+}
+
+/**
+ * asn1_expand_any_defined_by:
+ * @definitions: ASN1 definitions
+ * @element: pointer to an ASN1 structure
+ *
+ * Expands every "ANY DEFINED BY" element of a structure created from
+ * a DER decoding process (asn1_der_decoding function). The element
+ * ANY must be defined by an OBJECT IDENTIFIER. The type used to
+ * expand the element ANY is the first one following the definition of
+ * the actual value of the OBJECT IDENTIFIER.
+ *
+ * Returns: %ASN1_SUCCESS if Substitution OK, %ASN1_ERROR_TYPE_ANY if
+ *   some "ANY DEFINED BY" element couldn't be expanded due to a
+ *   problem in OBJECT_ID -> TYPE association, or other error codes
+ *   depending on DER decoding.
+ **/
+int
+asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element)
+{
+  char name[2 * ASN1_MAX_NAME_SIZE + 2], value[ASN1_MAX_NAME_SIZE];
+  int retCode = ASN1_SUCCESS, result;
+  int len, len2, len3;
+  asn1_node_const p2;
+  asn1_node p, p3, aux = NULL;
+  char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+  const char *definitionsName;
+
+  if ((definitions == NULL) || (*element == NULL))
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  definitionsName = definitions->name;
+
+  p = *element;
+  while (p)
+    {
+
+      switch (type_field (p->type))
+	{
+	case ASN1_ETYPE_ANY:
+	  if ((p->type & CONST_DEFINED_BY) && (p->value))
+	    {
+	      /* search the "DEF_BY" element */
+	      p2 = p->down;
+	      while ((p2) && (type_field (p2->type) != ASN1_ETYPE_CONSTANT))
+		p2 = p2->right;
+
+	      if (!p2)
+		{
+		  retCode = ASN1_ERROR_TYPE_ANY;
+		  break;
+		}
+
+	      p3 = _asn1_find_up (p);
+
+	      if (!p3)
+		{
+		  retCode = ASN1_ERROR_TYPE_ANY;
+		  break;
+		}
+
+	      p3 = p3->down;
+	      while (p3)
+		{
+		  if (!(strcmp (p3->name, p2->name)))
+		    break;
+		  p3 = p3->right;
+		}
+
+	      if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) ||
+		  (p3->value == NULL))
+		{
+
+		  p3 = _asn1_find_up (p);
+		  p3 = _asn1_find_up (p3);
+
+		  if (!p3)
+		    {
+		      retCode = ASN1_ERROR_TYPE_ANY;
+		      break;
+		    }
+
+		  p3 = p3->down;
+
+		  while (p3)
+		    {
+		      if (!(strcmp (p3->name, p2->name)))
+			break;
+		      p3 = p3->right;
+		    }
+
+		  if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
+		      || (p3->value == NULL))
+		    {
+		      retCode = ASN1_ERROR_TYPE_ANY;
+		      break;
+		    }
+		}
+
+	      /* search the OBJECT_ID into definitions */
+	      p2 = definitions->down;
+	      while (p2)
+		{
+		  if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) &&
+		      (p2->type & CONST_ASSIGN))
+		    {
+		      snprintf (name, sizeof (name), "%s.%s", definitionsName,
+				p2->name);
+
+		      len = ASN1_MAX_NAME_SIZE;
+		      result =
+			asn1_read_value (definitions, name, value, &len);
+
+		      if ((result == ASN1_SUCCESS)
+			  && (!_asn1_strcmp (p3->value, value)))
+			{
+			  p2 = p2->right;	/* pointer to the structure to
+						   use for expansion */
+			  while ((p2) && (p2->type & CONST_ASSIGN))
+			    p2 = p2->right;
+
+			  if (p2)
+			    {
+			      snprintf (name, sizeof (name), "%s.%s",
+					definitionsName, p2->name);
+
+			      result =
+				asn1_create_element (definitions, name, &aux);
+			      if (result == ASN1_SUCCESS)
+				{
+				  _asn1_cpy_name (aux, p);
+				  len2 =
+				    asn1_get_length_der (p->value,
+							 p->value_len, &len3);
+				  if (len2 < 0)
+				    return ASN1_DER_ERROR;
+
+				  result =
+				    asn1_der_decoding (&aux, p->value + len3,
+						       len2,
+						       errorDescription);
+				  if (result == ASN1_SUCCESS)
+				    {
+
+				      _asn1_set_right (aux, p->right);
+				      _asn1_set_right (p, aux);
+
+				      result = asn1_delete_structure (&p);
+				      if (result == ASN1_SUCCESS)
+					{
+					  p = aux;
+					  aux = NULL;
+					  break;
+					}
+				      else
+					{	/* error with asn1_delete_structure */
+					  asn1_delete_structure (&aux);
+					  retCode = result;
+					  break;
+					}
+				    }
+				  else
+				    {	/* error with asn1_der_decoding */
+				      retCode = result;
+				      break;
+				    }
+				}
+			      else
+				{	/* error with asn1_create_element */
+				  retCode = result;
+				  break;
+				}
+			    }
+			  else
+			    {	/* error with the pointer to the structure to exapand */
+			      retCode = ASN1_ERROR_TYPE_ANY;
+			      break;
+			    }
+			}
+		    }
+		  p2 = p2->right;
+		}		/* end while */
+
+	      if (!p2)
+		{
+		  retCode = ASN1_ERROR_TYPE_ANY;
+		  break;
+		}
+
+	    }
+	  break;
+	default:
+	  break;
+	}
+
+
+      if (p->down)
+	{
+	  p = p->down;
+	}
+      else if (p == *element)
+	{
+	  p = NULL;
+	  break;
+	}
+      else if (p->right)
+	p = p->right;
+      else
+	{
+	  while (1)
+	    {
+	      p = _asn1_find_up (p);
+	      if (p == *element)
+		{
+		  p = NULL;
+		  break;
+		}
+	      if (p->right)
+		{
+		  p = p->right;
+		  break;
+		}
+	    }
+	}
+    }
+
+  return retCode;
+}
+
+/**
+ * asn1_expand_octet_string:
+ * @definitions: ASN1 definitions
+ * @element: pointer to an ASN1 structure
+ * @octetName: name of the OCTECT STRING field to expand.
+ * @objectName: name of the OBJECT IDENTIFIER field to use to define
+ *    the type for expansion.
+ *
+ * Expands an "OCTET STRING" element of a structure created from a DER
+ * decoding process (the asn1_der_decoding() function).  The type used
+ * for expansion is the first one following the definition of the
+ * actual value of the OBJECT IDENTIFIER indicated by OBJECTNAME.
+ *
+ * Returns: %ASN1_SUCCESS if substitution OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if @objectName or @octetName are not correct,
+ *   %ASN1_VALUE_NOT_VALID if it wasn't possible to find the type to
+ *   use for expansion, or other errors depending on DER decoding.
+ **/
+int
+asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element,
+			  const char *octetName, const char *objectName)
+{
+  char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE];
+  int retCode = ASN1_SUCCESS, result;
+  int len, len2, len3;
+  asn1_node_const p2;
+  asn1_node aux = NULL;
+  asn1_node octetNode = NULL, objectNode = NULL;
+  char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+
+  if ((definitions == NULL) || (*element == NULL))
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  octetNode = asn1_find_node (*element, octetName);
+  if (octetNode == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+  if (type_field (octetNode->type) != ASN1_ETYPE_OCTET_STRING)
+    return ASN1_ELEMENT_NOT_FOUND;
+  if (octetNode->value == NULL)
+    return ASN1_VALUE_NOT_FOUND;
+
+  objectNode = asn1_find_node (*element, objectName);
+  if (objectNode == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  if (type_field (objectNode->type) != ASN1_ETYPE_OBJECT_ID)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  if (objectNode->value == NULL)
+    return ASN1_VALUE_NOT_FOUND;
+
+
+  /* search the OBJECT_ID into definitions */
+  p2 = definitions->down;
+  while (p2)
+    {
+      if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) &&
+	  (p2->type & CONST_ASSIGN))
+	{
+	  strcpy (name, definitions->name);
+	  strcat (name, ".");
+	  strcat (name, p2->name);
+
+	  len = sizeof (value);
+	  result = asn1_read_value (definitions, name, value, &len);
+
+	  if ((result == ASN1_SUCCESS)
+	      && (!_asn1_strcmp (objectNode->value, value)))
+	    {
+
+	      p2 = p2->right;	/* pointer to the structure to
+				   use for expansion */
+	      while ((p2) && (p2->type & CONST_ASSIGN))
+		p2 = p2->right;
+
+	      if (p2)
+		{
+		  strcpy (name, definitions->name);
+		  strcat (name, ".");
+		  strcat (name, p2->name);
+
+		  result = asn1_create_element (definitions, name, &aux);
+		  if (result == ASN1_SUCCESS)
+		    {
+		      _asn1_cpy_name (aux, octetNode);
+		      len2 =
+			asn1_get_length_der (octetNode->value,
+					     octetNode->value_len, &len3);
+		      if (len2 < 0)
+			return ASN1_DER_ERROR;
+
+		      result =
+			asn1_der_decoding (&aux, octetNode->value + len3,
+					   len2, errorDescription);
+		      if (result == ASN1_SUCCESS)
+			{
+
+			  _asn1_set_right (aux, octetNode->right);
+			  _asn1_set_right (octetNode, aux);
+
+			  result = asn1_delete_structure (&octetNode);
+			  if (result == ASN1_SUCCESS)
+			    {
+			      aux = NULL;
+			      break;
+			    }
+			  else
+			    {	/* error with asn1_delete_structure */
+			      asn1_delete_structure (&aux);
+			      retCode = result;
+			      break;
+			    }
+			}
+		      else
+			{	/* error with asn1_der_decoding */
+			  retCode = result;
+			  break;
+			}
+		    }
+		  else
+		    {		/* error with asn1_create_element */
+		      retCode = result;
+		      break;
+		    }
+		}
+	      else
+		{		/* error with the pointer to the structure to exapand */
+		  retCode = ASN1_VALUE_NOT_VALID;
+		  break;
+		}
+	    }
+	}
+
+      p2 = p2->right;
+
+    }
+
+  if (!p2)
+    retCode = ASN1_VALUE_NOT_VALID;
+
+  return retCode;
+}
+
+/*-
+ * _asn1_decode_simple_der:
+ * @etype: The type of the string to be encoded (ASN1_ETYPE_)
+ * @der: the encoded string
+ * @_der_len: the bytes of the encoded string
+ * @str: a pointer to the data
+ * @str_len: the length of the data
+ * @dflags: DECODE_FLAG_*
+ *
+ * Decodes a simple DER encoded type (e.g. a string, which is not constructed).
+ * The output is a pointer inside the @der.
+ *
+ * Returns: %ASN1_SUCCESS if successful or an error value.
+ -*/
+static int
+_asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
+			 unsigned int _der_len, const unsigned char **str,
+			 unsigned int *str_len, unsigned dflags)
+{
+  int tag_len, len_len;
+  const unsigned char *p;
+  int der_len = _der_len;
+  unsigned char class;
+  unsigned long tag;
+  long ret;
+
+  if (der == NULL || der_len == 0)
+    return ASN1_VALUE_NOT_VALID;
+
+  if (ETYPE_OK (etype) == 0 || ETYPE_IS_STRING (etype) == 0)
+    return ASN1_VALUE_NOT_VALID;
+
+  /* doesn't handle constructed classes */
+  class = ETYPE_CLASS (etype);
+  if (class != ASN1_CLASS_UNIVERSAL)
+    return ASN1_VALUE_NOT_VALID;
+
+  p = der;
+
+  if (dflags & DECODE_FLAG_HAVE_TAG)
+    {
+      ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
+      if (ret != ASN1_SUCCESS)
+	return ret;
+
+      if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype))
+	{
+	  warn ();
+	  return ASN1_DER_ERROR;
+	}
+
+      p += tag_len;
+      der_len -= tag_len;
+      if (der_len <= 0)
+	return ASN1_DER_ERROR;
+    }
+
+  ret = asn1_get_length_der (p, der_len, &len_len);
+  if (ret < 0)
+    return ASN1_DER_ERROR;
+
+  p += len_len;
+  der_len -= len_len;
+  if (der_len <= 0)
+    return ASN1_DER_ERROR;
+
+  *str_len = ret;
+  *str = p;
+
+  return ASN1_SUCCESS;
+}
+
+/**
+ * asn1_decode_simple_der:
+ * @etype: The type of the string to be encoded (ASN1_ETYPE_)
+ * @der: the encoded string
+ * @_der_len: the bytes of the encoded string
+ * @str: a pointer to the data
+ * @str_len: the length of the data
+ *
+ * Decodes a simple DER encoded type (e.g. a string, which is not constructed).
+ * The output is a pointer inside the @der.
+ *
+ * Returns: %ASN1_SUCCESS if successful or an error value.
+ **/
+int
+asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
+			unsigned int _der_len, const unsigned char **str,
+			unsigned int *str_len)
+{
+  return _asn1_decode_simple_der (etype, der, _der_len, str, str_len,
+				  DECODE_FLAG_HAVE_TAG);
+}
+
+static int
+append (uint8_t ** dst, unsigned *dst_size, const unsigned char *src,
+	unsigned src_size)
+{
+  if (src_size == 0)
+    return ASN1_SUCCESS;
+
+  *dst = _asn1_realloc (*dst, *dst_size + src_size);
+  if (*dst == NULL)
+    return ASN1_MEM_ALLOC_ERROR;
+  memcpy (*dst + *dst_size, src, src_size);
+  *dst_size += src_size;
+  return ASN1_SUCCESS;
+}
+
+/*-
+ * _asn1_decode_simple_ber:
+ * @etype: The type of the string to be encoded (ASN1_ETYPE_)
+ * @der: the encoded string
+ * @_der_len: the bytes of the encoded string
+ * @str: a pointer to the data
+ * @str_len: the length of the data
+ * @ber_len: the total length occupied by BER (may be %NULL)
+ * @have_tag: whether a DER tag is included
+ *
+ * Decodes a BER encoded type. The output is an allocated value
+ * of the data. This decodes BER STRINGS only. Other types are
+ * decoded as DER.
+ *
+ * Returns: %ASN1_SUCCESS if successful or an error value.
+ -*/
+static int
+_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
+			 unsigned int _der_len, unsigned char **str,
+			 unsigned int *str_len, unsigned int *ber_len,
+			 unsigned dflags)
+{
+  int tag_len, len_len;
+  const unsigned char *p;
+  int der_len = _der_len;
+  uint8_t *total = NULL;
+  unsigned total_size = 0;
+  unsigned char class;
+  unsigned long tag;
+  unsigned char *out = NULL;
+  const unsigned char *cout = NULL;
+  unsigned out_len;
+  long result;
+
+  if (ber_len)
+    *ber_len = 0;
+
+  if (der == NULL || der_len == 0)
+    {
+      warn ();
+      return ASN1_VALUE_NOT_VALID;
+    }
+
+  if (ETYPE_OK (etype) == 0)
+    {
+      warn ();
+      return ASN1_VALUE_NOT_VALID;
+    }
+
+  /* doesn't handle constructed + definite classes */
+  class = ETYPE_CLASS (etype);
+  if (class != ASN1_CLASS_UNIVERSAL)
+    {
+      warn ();
+      return ASN1_VALUE_NOT_VALID;
+    }
+
+  p = der;
+
+  if (dflags & DECODE_FLAG_HAVE_TAG)
+    {
+      result = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
+      if (result != ASN1_SUCCESS)
+	{
+	  warn ();
+	  return result;
+	}
+
+      if (tag != ETYPE_TAG (etype))
+	{
+	  warn ();
+	  return ASN1_DER_ERROR;
+	}
+
+      p += tag_len;
+
+      DECR_LEN (der_len, tag_len);
+
+      if (ber_len)
+	*ber_len += tag_len;
+    }
+
+  /* indefinite constructed */
+  if ((((dflags & DECODE_FLAG_CONSTRUCTED) || class == ASN1_CLASS_STRUCTURED)
+       && ETYPE_IS_STRING (etype)) && !(dflags & DECODE_FLAG_LEVEL3))
+    {
+      if (der_len == 0)
+	{
+	  warn ();
+	  result = ASN1_DER_ERROR;
+	  goto cleanup;
+	}
+
+      if (der_len > 0 && p[0] == 0x80)	/* indefinite */
+	{
+	  len_len = 1;
+	  DECR_LEN (der_len, len_len);
+	  p += len_len;
+
+	  if (ber_len)
+	    *ber_len += len_len;
+
+	  /* decode the available octet strings */
+	  do
+	    {
+	      unsigned tmp_len;
+	      unsigned flags = DECODE_FLAG_HAVE_TAG;
+
+	      if (dflags & DECODE_FLAG_LEVEL1)
+		flags |= DECODE_FLAG_LEVEL2;
+	      else if (dflags & DECODE_FLAG_LEVEL2)
+		flags |= DECODE_FLAG_LEVEL3;
+	      else
+		flags |= DECODE_FLAG_LEVEL1;
+
+	      result =
+		_asn1_decode_simple_ber (etype, p, der_len, &out, &out_len,
+					 &tmp_len, flags);
+	      if (result != ASN1_SUCCESS)
+		{
+		  warn ();
+		  goto cleanup;
+		}
+
+	      p += tmp_len;
+	      DECR_LEN (der_len, tmp_len);
+
+	      if (ber_len)
+		*ber_len += tmp_len;
+
+	      DECR_LEN (der_len, 2);	/* we need the EOC */
+
+	      result = append (&total, &total_size, out, out_len);
+	      if (result != ASN1_SUCCESS)
+		{
+		  warn ();
+		  goto cleanup;
+		}
+
+	      free (out);
+	      out = NULL;
+
+	      if (p[0] == 0 && p[1] == 0)	/* EOC */
+		{
+		  if (ber_len)
+		    *ber_len += 2;
+		  break;
+		}
+
+	      /* no EOC */
+	      der_len += 2;
+
+	      if (der_len == 2)
+		{
+		  warn ();
+		  result = ASN1_DER_ERROR;
+		  goto cleanup;
+		}
+	    }
+	  while (1);
+	}
+      else			/* constructed */
+	{
+	  long const_len;
+
+	  result = asn1_get_length_ber (p, der_len, &len_len);
+	  if (result < 0)
+	    {
+	      warn ();
+	      result = ASN1_DER_ERROR;
+	      goto cleanup;
+	    }
+
+	  DECR_LEN (der_len, len_len);
+	  p += len_len;
+
+	  const_len = result;
+
+	  if (ber_len)
+	    *ber_len += len_len;
+
+	  /* decode the available octet strings */
+	  while (const_len > 0)
+	    {
+	      unsigned tmp_len;
+	      unsigned flags = DECODE_FLAG_HAVE_TAG;
+
+	      if (dflags & DECODE_FLAG_LEVEL1)
+		flags |= DECODE_FLAG_LEVEL2;
+	      else if (dflags & DECODE_FLAG_LEVEL2)
+		flags |= DECODE_FLAG_LEVEL3;
+	      else
+		flags |= DECODE_FLAG_LEVEL1;
+
+	      result =
+		_asn1_decode_simple_ber (etype, p, der_len, &out, &out_len,
+					 &tmp_len, flags);
+	      if (result != ASN1_SUCCESS)
+		{
+		  warn ();
+		  goto cleanup;
+		}
+
+	      p += tmp_len;
+	      DECR_LEN (der_len, tmp_len);
+	      DECR_LEN (const_len, tmp_len);
+
+	      if (ber_len)
+		*ber_len += tmp_len;
+
+	      result = append (&total, &total_size, out, out_len);
+	      if (result != ASN1_SUCCESS)
+		{
+		  warn ();
+		  goto cleanup;
+		}
+
+	      free (out);
+	      out = NULL;
+	    }
+	}
+    }
+  else if (class == ETYPE_CLASS (etype))
+    {
+      if (ber_len)
+	{
+	  result = asn1_get_length_der (p, der_len, &len_len);
+	  if (result < 0)
+	    {
+	      warn ();
+	      result = ASN1_DER_ERROR;
+	      goto cleanup;
+	    }
+	  *ber_len += result + len_len;
+	}
+
+      /* non-string values are decoded as DER */
+      result =
+	_asn1_decode_simple_der (etype, der, _der_len, &cout, &out_len,
+				 dflags);
+      if (result != ASN1_SUCCESS)
+	{
+	  warn ();
+	  goto cleanup;
+	}
+
+      result = append (&total, &total_size, cout, out_len);
+      if (result != ASN1_SUCCESS)
+	{
+	  warn ();
+	  goto cleanup;
+	}
+    }
+  else
+    {
+      warn ();
+      result = ASN1_DER_ERROR;
+      goto cleanup;
+    }
+
+  *str = total;
+  *str_len = total_size;
+
+  return ASN1_SUCCESS;
+cleanup:
+  free (out);
+  free (total);
+  return result;
+}
+
+/**
+ * asn1_decode_simple_ber:
+ * @etype: The type of the string to be encoded (ASN1_ETYPE_)
+ * @der: the encoded string
+ * @_der_len: the bytes of the encoded string
+ * @str: a pointer to the data
+ * @str_len: the length of the data
+ * @ber_len: the total length occupied by BER (may be %NULL)
+ *
+ * Decodes a BER encoded type. The output is an allocated value
+ * of the data. This decodes BER STRINGS only. Other types are
+ * decoded as DER.
+ *
+ * Returns: %ASN1_SUCCESS if successful or an error value.
+ **/
+int
+asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
+			unsigned int _der_len, unsigned char **str,
+			unsigned int *str_len, unsigned int *ber_len)
+{
+  return _asn1_decode_simple_ber (etype, der, _der_len, str, str_len, ber_len,
+				  DECODE_FLAG_HAVE_TAG);
+}
diff --git a/grub-core/lib/libtasn1/lib/element.c b/grub-core/lib/libtasn1/lib/element.c
new file mode 100644
index 0000000..d4c558e
--- /dev/null
+++ b/grub-core/lib/libtasn1/lib/element.c
@@ -0,0 +1,1109 @@
+/*
+ * Copyright (C) 2000-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+/*****************************************************/
+/* File: element.c                                   */
+/* Description: Functions with the read and write    */
+/*   functions.                                      */
+/*****************************************************/
+
+
+#include <int.h>
+#include "parser_aux.h"
+#include <gstr.h>
+#include "structure.h"
+#include "c-ctype.h"
+#include "element.h"
+
+void
+_asn1_hierarchical_name (asn1_node_const node, char *name, int name_size)
+{
+  asn1_node_const p;
+  char tmp_name[64];
+
+  p = node;
+
+  name[0] = 0;
+
+  while (p != NULL)
+    {
+      if (p->name[0] != 0)
+	{
+	  _asn1_str_cpy (tmp_name, sizeof (tmp_name), name),
+	    _asn1_str_cpy (name, name_size, p->name);
+	  _asn1_str_cat (name, name_size, ".");
+	  _asn1_str_cat (name, name_size, tmp_name);
+	}
+      p = _asn1_find_up (p);
+    }
+
+  if (name[0] == 0)
+    _asn1_str_cpy (name, name_size, "ROOT");
+}
+
+
+/******************************************************************/
+/* Function : _asn1_convert_integer                               */
+/* Description: converts an integer from a null terminated string */
+/*              to der decoding. The convertion from a null       */
+/*              terminated string to an integer is made with      */
+/*              the 'strtol' function.                            */
+/* Parameters:                                                    */
+/*   value: null terminated string to convert.                    */
+/*   value_out: convertion result (memory must be already         */
+/*              allocated).                                       */
+/*   value_out_size: number of bytes of value_out.                */
+/*   len: number of significant byte of value_out.                */
+/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS                         */
+/******************************************************************/
+int
+_asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
+		       int value_out_size, int *len)
+{
+  char negative;
+  unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
+  long valtmp;
+  int k, k2;
+
+  valtmp = _asn1_strtol (value, NULL, 10);
+
+  for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
+    {
+      val[SIZEOF_UNSIGNED_LONG_INT - k - 1] = (valtmp >> (8 * k)) & 0xFF;
+    }
+
+  if (val[0] & 0x80)
+    negative = 1;
+  else
+    negative = 0;
+
+  for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT - 1; k++)
+    {
+      if (negative && (val[k] != 0xFF))
+	break;
+      else if (!negative && val[k])
+	break;
+    }
+
+  if ((negative && !(val[k] & 0x80)) || (!negative && (val[k] & 0x80)))
+    k--;
+
+  *len = SIZEOF_UNSIGNED_LONG_INT - k;
+
+  if (SIZEOF_UNSIGNED_LONG_INT - k > value_out_size)
+    /* VALUE_OUT is too short to contain the value conversion */
+    return ASN1_MEM_ERROR;
+
+  if (value_out != NULL)
+    {
+      for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+	value_out[k2 - k] = val[k2];
+    }
+
+#if 0
+  printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
+  for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
+    printf (", vOut[%d]=%d", k, value_out[k]);
+  printf ("\n");
+#endif
+
+  return ASN1_SUCCESS;
+}
+
+/* Appends a new element into the sequence (or set) defined by this
+ * node. The new element will have a name of '?number', where number
+ * is a monotonically increased serial number.
+ *
+ * The last element in the list may be provided in @pcache, to avoid
+ * traversing the list, an expensive operation in long lists.
+ *
+ * On success it returns in @pcache the added element (which is the
+ * tail in the list of added elements).
+ */
+int
+_asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache)
+{
+  asn1_node p, p2;
+  char temp[LTOSTR_MAX_SIZE + 1];
+  long n;
+
+  if (!node || !(node->down))
+    return ASN1_GENERIC_ERROR;
+
+  p = node->down;
+  while ((type_field (p->type) == ASN1_ETYPE_TAG)
+	 || (type_field (p->type) == ASN1_ETYPE_SIZE))
+    p = p->right;
+
+  p2 = _asn1_copy_structure3 (p);
+  if (p2 == NULL)
+    return ASN1_GENERIC_ERROR;
+
+  if (pcache == NULL || pcache->tail == NULL || pcache->head != node)
+    {
+      while (p->right)
+	{
+	  p = p->right;
+	}
+    }
+  else
+    {
+      p = pcache->tail;
+    }
+
+  _asn1_set_right (p, p2);
+  if (pcache)
+    {
+      pcache->head = node;
+      pcache->tail = p2;
+    }
+
+  if (p->name[0] == 0)
+    _asn1_str_cpy (temp, sizeof (temp), "?1");
+  else
+    {
+      n = strtol (p->name + 1, NULL, 0);
+      n++;
+      temp[0] = '?';
+      _asn1_ltostr (n, temp + 1);
+    }
+  _asn1_set_name (p2, temp);
+  /*  p2->type |= CONST_OPTION; */
+
+  return ASN1_SUCCESS;
+}
+
+
+/**
+ * asn1_write_value:
+ * @node_root: pointer to a structure
+ * @name: the name of the element inside the structure that you want to set.
+ * @ivalue: vector used to specify the value to set. If len is >0,
+ *   VALUE must be a two's complement form integer.  if len=0 *VALUE
+ *   must be a null terminated string with an integer value.
+ * @len: number of bytes of *value to use to set the value:
+ *   value[0]..value[len-1] or 0 if value is a null terminated string
+ *
+ * Set the value of one element inside a structure.
+ *
+ * If an element is OPTIONAL and you want to delete it, you must use
+ * the value=NULL and len=0.  Using "pkix.asn":
+ *
+ * result=asn1_write_value(cert, "tbsCertificate.issuerUniqueID",
+ * NULL, 0);
+ *
+ * Description for each type:
+ *
+ * INTEGER: VALUE must contain a two's complement form integer.
+ *
+ *            value[0]=0xFF ,               len=1 -> integer=-1.
+ *            value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1.
+ *            value[0]=0x01 ,               len=1 -> integer= 1.
+ *            value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1.
+ *            value="123"                 , len=0 -> integer= 123.
+ *
+ * ENUMERATED: As INTEGER (but only with not negative numbers).
+ *
+ * BOOLEAN: VALUE must be the null terminated string "TRUE" or
+ *   "FALSE" and LEN != 0.
+ *
+ *            value="TRUE" , len=1 -> boolean=TRUE.
+ *            value="FALSE" , len=1 -> boolean=FALSE.
+ *
+ * OBJECT IDENTIFIER: VALUE must be a null terminated string with
+ *   each number separated by a dot (e.g. "1.2.3.543.1").  LEN != 0.
+ *
+ *            value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha.
+ *
+ * UTCTime: VALUE must be a null terminated string in one of these
+ *   formats: "YYMMDDhhmmssZ", "YYMMDDhhmmssZ",
+ *   "YYMMDDhhmmss+hh'mm'", "YYMMDDhhmmss-hh'mm'",
+ *   "YYMMDDhhmm+hh'mm'", or "YYMMDDhhmm-hh'mm'".  LEN != 0.
+ *
+ *            value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998
+ *            at 12h 00m Greenwich Mean Time
+ *
+ * GeneralizedTime: VALUE must be in one of this format:
+ *   "YYYYMMDDhhmmss.sZ", "YYYYMMDDhhmmss.sZ",
+ *   "YYYYMMDDhhmmss.s+hh'mm'", "YYYYMMDDhhmmss.s-hh'mm'",
+ *   "YYYYMMDDhhmm+hh'mm'", or "YYYYMMDDhhmm-hh'mm'" where ss.s
+ *   indicates the seconds with any precision like "10.1" or "01.02".
+ *   LEN != 0
+ *
+ *            value="2001010112001.12-0700" , len=1 -> time=Jannuary
+ *            1st, 2001 at 12h 00m 01.12s Pacific Daylight Time
+ *
+ * OCTET STRING: VALUE contains the octet string and LEN is the
+ *   number of octets.
+ *
+ *            value="$\backslash$x01$\backslash$x02$\backslash$x03" ,
+ *            len=3 -> three bytes octet string
+ *
+ * GeneralString: VALUE contains the generalstring and LEN is the
+ *   number of octets.
+ *
+ *            value="$\backslash$x01$\backslash$x02$\backslash$x03" ,
+ *            len=3 -> three bytes generalstring
+ *
+ * BIT STRING: VALUE contains the bit string organized by bytes and
+ *   LEN is the number of bits.
+ *
+ *   value="$\backslash$xCF" , len=6 -> bit string="110011" (six
+ *   bits)
+ *
+ * CHOICE: if NAME indicates a choice type, VALUE must specify one of
+ *   the alternatives with a null terminated string. LEN != 0. Using
+ *   "pkix.asn"\:
+ *
+ *           result=asn1_write_value(cert,
+ *           "certificate1.tbsCertificate.subject", "rdnSequence",
+ *           1);
+ *
+ * ANY: VALUE indicates the der encoding of a structure.  LEN != 0.
+ *
+ * SEQUENCE OF: VALUE must be the null terminated string "NEW" and
+ *   LEN != 0. With this instruction another element is appended in
+ *   the sequence. The name of this element will be "?1" if it's the
+ *   first one, "?2" for the second and so on.
+ *
+ *   Using "pkix.asn"\:
+ *
+ *   result=asn1_write_value(cert,
+ *   "certificate1.tbsCertificate.subject.rdnSequence", "NEW", 1);
+ *
+ * SET OF: the same as SEQUENCE OF.  Using "pkix.asn":
+ *
+ *           result=asn1_write_value(cert,
+ *           "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1);
+ *
+ * Returns: %ASN1_SUCCESS if the value was set,
+ *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and
+ *   %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format.
+ **/
+int
+asn1_write_value (asn1_node node_root, const char *name,
+		  const void *ivalue, int len)
+{
+  asn1_node node, p, p2;
+  unsigned char *temp, *value_temp = NULL, *default_temp = NULL;
+  int len2, k, k2, negative;
+  size_t i;
+  const unsigned char *value = ivalue;
+  unsigned int type;
+
+  node = asn1_find_node (node_root, name);
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  if ((node->type & CONST_OPTION) && (value == NULL) && (len == 0))
+    {
+      asn1_delete_structure (&node);
+      return ASN1_SUCCESS;
+    }
+
+  type = type_field (node->type);
+
+  if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF)
+      && (value == NULL) && (len == 0))
+    {
+      p = node->down;
+      while ((type_field (p->type) == ASN1_ETYPE_TAG)
+	     || (type_field (p->type) == ASN1_ETYPE_SIZE))
+	p = p->right;
+
+      while (p->right)
+	asn1_delete_structure (&p->right);
+
+      return ASN1_SUCCESS;
+    }
+
+  /* Don't allow element deletion for other types */
+  if (value == NULL)
+    {
+      return ASN1_VALUE_NOT_VALID;
+    }
+
+  switch (type)
+    {
+    case ASN1_ETYPE_BOOLEAN:
+      if (!_asn1_strcmp (value, "TRUE"))
+	{
+	  if (node->type & CONST_DEFAULT)
+	    {
+	      p = node->down;
+	      while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
+		p = p->right;
+	      if (p->type & CONST_TRUE)
+		_asn1_set_value (node, NULL, 0);
+	      else
+		_asn1_set_value (node, "T", 1);
+	    }
+	  else
+	    _asn1_set_value (node, "T", 1);
+	}
+      else if (!_asn1_strcmp (value, "FALSE"))
+	{
+	  if (node->type & CONST_DEFAULT)
+	    {
+	      p = node->down;
+	      while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
+		p = p->right;
+	      if (p->type & CONST_FALSE)
+		_asn1_set_value (node, NULL, 0);
+	      else
+		_asn1_set_value (node, "F", 1);
+	    }
+	  else
+	    _asn1_set_value (node, "F", 1);
+	}
+      else
+	return ASN1_VALUE_NOT_VALID;
+      break;
+    case ASN1_ETYPE_INTEGER:
+    case ASN1_ETYPE_ENUMERATED:
+      if (len == 0)
+	{
+	  if ((c_isdigit (value[0])) || (value[0] == '-'))
+	    {
+	      value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+	      if (value_temp == NULL)
+		return ASN1_MEM_ALLOC_ERROR;
+
+	      _asn1_convert_integer (value, value_temp,
+				     SIZEOF_UNSIGNED_LONG_INT, &len);
+	    }
+	  else
+	    {			/* is an identifier like v1 */
+	      if (!(node->type & CONST_LIST))
+		return ASN1_VALUE_NOT_VALID;
+	      p = node->down;
+	      while (p)
+		{
+		  if (type_field (p->type) == ASN1_ETYPE_CONSTANT)
+		    {
+		      if (!_asn1_strcmp (p->name, value))
+			{
+			  value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+			  if (value_temp == NULL)
+			    return ASN1_MEM_ALLOC_ERROR;
+
+			  _asn1_convert_integer (p->value,
+						 value_temp,
+						 SIZEOF_UNSIGNED_LONG_INT,
+						 &len);
+			  break;
+			}
+		    }
+		  p = p->right;
+		}
+	      if (p == NULL)
+		return ASN1_VALUE_NOT_VALID;
+	    }
+	}
+      else
+	{			/* len != 0 */
+	  value_temp = malloc (len);
+	  if (value_temp == NULL)
+	    return ASN1_MEM_ALLOC_ERROR;
+	  memcpy (value_temp, value, len);
+	}
+
+      if (value_temp[0] & 0x80)
+	negative = 1;
+      else
+	negative = 0;
+
+      if (negative && (type_field (node->type) == ASN1_ETYPE_ENUMERATED))
+	{
+	  free (value_temp);
+	  return ASN1_VALUE_NOT_VALID;
+	}
+
+      for (k = 0; k < len - 1; k++)
+	if (negative && (value_temp[k] != 0xFF))
+	  break;
+	else if (!negative && value_temp[k])
+	  break;
+
+      if ((negative && !(value_temp[k] & 0x80)) ||
+	  (!negative && (value_temp[k] & 0x80)))
+	k--;
+
+      _asn1_set_value_lv (node, value_temp + k, len - k);
+
+      if (node->type & CONST_DEFAULT)
+	{
+	  p = node->down;
+	  while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
+	    p = p->right;
+	  if ((c_isdigit (p->value[0])) || (p->value[0] == '-'))
+	    {
+	      default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+	      if (default_temp == NULL)
+		{
+		  free (value_temp);
+		  return ASN1_MEM_ALLOC_ERROR;
+		}
+
+	      _asn1_convert_integer (p->value, default_temp,
+				     SIZEOF_UNSIGNED_LONG_INT, &len2);
+	    }
+	  else
+	    {			/* is an identifier like v1 */
+	      if (!(node->type & CONST_LIST))
+		{
+		  free (value_temp);
+		  return ASN1_VALUE_NOT_VALID;
+		}
+	      p2 = node->down;
+	      while (p2)
+		{
+		  if (type_field (p2->type) == ASN1_ETYPE_CONSTANT)
+		    {
+		      if (!_asn1_strcmp (p2->name, p->value))
+			{
+			  default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+			  if (default_temp == NULL)
+			    {
+			      free (value_temp);
+			      return ASN1_MEM_ALLOC_ERROR;
+			    }
+
+			  _asn1_convert_integer (p2->value,
+						 default_temp,
+						 SIZEOF_UNSIGNED_LONG_INT,
+						 &len2);
+			  break;
+			}
+		    }
+		  p2 = p2->right;
+		}
+	      if (p2 == NULL)
+		{
+		  free (value_temp);
+		  return ASN1_VALUE_NOT_VALID;
+		}
+	    }
+
+
+	  if ((len - k) == len2)
+	    {
+	      for (k2 = 0; k2 < len2; k2++)
+		if (value_temp[k + k2] != default_temp[k2])
+		  {
+		    break;
+		  }
+	      if (k2 == len2)
+		_asn1_set_value (node, NULL, 0);
+	    }
+	  free (default_temp);
+	}
+      free (value_temp);
+      break;
+    case ASN1_ETYPE_OBJECT_ID:
+      for (i = 0; i < _asn1_strlen (value); i++)
+	if ((!c_isdigit (value[i])) && (value[i] != '.') && (value[i] != '+'))
+	  return ASN1_VALUE_NOT_VALID;
+      if (node->type & CONST_DEFAULT)
+	{
+	  p = node->down;
+	  while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
+	    p = p->right;
+	  if (!_asn1_strcmp (value, p->value))
+	    {
+	      _asn1_set_value (node, NULL, 0);
+	      break;
+	    }
+	}
+      _asn1_set_value (node, value, _asn1_strlen (value) + 1);
+      break;
+    case ASN1_ETYPE_UTC_TIME:
+      {
+	len = _asn1_strlen (value);
+	if (len < 11)
+	  return ASN1_VALUE_NOT_VALID;
+	for (k = 0; k < 10; k++)
+	  if (!c_isdigit (value[k]))
+	    return ASN1_VALUE_NOT_VALID;
+	switch (len)
+	  {
+	  case 11:
+	    if (value[10] != 'Z')
+	      return ASN1_VALUE_NOT_VALID;
+	    break;
+	  case 13:
+	    if ((!c_isdigit (value[10])) || (!c_isdigit (value[11])) ||
+		(value[12] != 'Z'))
+	      return ASN1_VALUE_NOT_VALID;
+	    break;
+	  case 15:
+	    if ((value[10] != '+') && (value[10] != '-'))
+	      return ASN1_VALUE_NOT_VALID;
+	    for (k = 11; k < 15; k++)
+	      if (!c_isdigit (value[k]))
+		return ASN1_VALUE_NOT_VALID;
+	    break;
+	  case 17:
+	    if ((!c_isdigit (value[10])) || (!c_isdigit (value[11])))
+	      return ASN1_VALUE_NOT_VALID;
+	    if ((value[12] != '+') && (value[12] != '-'))
+	      return ASN1_VALUE_NOT_VALID;
+	    for (k = 13; k < 17; k++)
+	      if (!c_isdigit (value[k]))
+		return ASN1_VALUE_NOT_VALID;
+	    break;
+	  default:
+	    return ASN1_VALUE_NOT_FOUND;
+	  }
+	_asn1_set_value (node, value, len);
+      }
+      break;
+    case ASN1_ETYPE_GENERALIZED_TIME:
+      len = _asn1_strlen (value);
+      _asn1_set_value (node, value, len);
+      break;
+    case ASN1_ETYPE_OCTET_STRING:
+    case ASN1_ETYPE_GENERALSTRING:
+    case ASN1_ETYPE_NUMERIC_STRING:
+    case ASN1_ETYPE_IA5_STRING:
+    case ASN1_ETYPE_TELETEX_STRING:
+    case ASN1_ETYPE_PRINTABLE_STRING:
+    case ASN1_ETYPE_UNIVERSAL_STRING:
+    case ASN1_ETYPE_BMP_STRING:
+    case ASN1_ETYPE_UTF8_STRING:
+    case ASN1_ETYPE_VISIBLE_STRING:
+      if (len == 0)
+	len = _asn1_strlen (value);
+      _asn1_set_value_lv (node, value, len);
+      break;
+    case ASN1_ETYPE_BIT_STRING:
+      if (len == 0)
+	len = _asn1_strlen (value);
+      asn1_length_der ((len >> 3) + 2, NULL, &len2);
+      temp = malloc ((len >> 3) + 2 + len2);
+      if (temp == NULL)
+	return ASN1_MEM_ALLOC_ERROR;
+
+      asn1_bit_der (value, len, temp, &len2);
+      _asn1_set_value_m (node, temp, len2);
+      temp = NULL;
+      break;
+    case ASN1_ETYPE_CHOICE:
+      p = node->down;
+      while (p)
+	{
+	  if (!_asn1_strcmp (p->name, value))
+	    {
+	      p2 = node->down;
+	      while (p2)
+		{
+		  if (p2 != p)
+		    {
+		      asn1_delete_structure (&p2);
+		      p2 = node->down;
+		    }
+		  else
+		    p2 = p2->right;
+		}
+	      break;
+	    }
+	  p = p->right;
+	}
+      if (!p)
+	return ASN1_ELEMENT_NOT_FOUND;
+      break;
+    case ASN1_ETYPE_ANY:
+      _asn1_set_value_lv (node, value, len);
+      break;
+    case ASN1_ETYPE_SEQUENCE_OF:
+    case ASN1_ETYPE_SET_OF:
+      if (_asn1_strcmp (value, "NEW"))
+	return ASN1_VALUE_NOT_VALID;
+      _asn1_append_sequence_set (node, NULL);
+      break;
+    default:
+      return ASN1_ELEMENT_NOT_FOUND;
+      break;
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+#define PUT_VALUE( ptr, ptr_size, data, data_size) \
+	*len = data_size; \
+	if (ptr_size < data_size) { \
+		return ASN1_MEM_ERROR; \
+	} else { \
+		if (ptr && data_size > 0) \
+		  memcpy (ptr, data, data_size); \
+	}
+
+#define PUT_STR_VALUE( ptr, ptr_size, data) \
+	*len = _asn1_strlen (data) + 1; \
+	if (ptr_size < *len) { \
+		return ASN1_MEM_ERROR; \
+	} else { \
+		/* this strcpy is checked */ \
+		if (ptr) { \
+		  _asn1_strcpy (ptr, data); \
+		} \
+	}
+
+#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
+	*len = data_size + 1; \
+	if (ptr_size < *len) { \
+		return ASN1_MEM_ERROR; \
+	} else { \
+		/* this strcpy is checked */ \
+		if (ptr) { \
+		  if (data_size > 0) \
+		    memcpy (ptr, data, data_size); \
+		  ptr[data_size] = 0; \
+		} \
+	}
+
+#define ADD_STR_VALUE( ptr, ptr_size, data) \
+        *len += _asn1_strlen(data); \
+        if (ptr_size < (int) *len) { \
+                (*len)++; \
+                return ASN1_MEM_ERROR; \
+        } else { \
+                /* this strcat is checked */ \
+                if (ptr) _asn1_strcat (ptr, data); \
+        }
+
+/**
+ * asn1_read_value:
+ * @root: pointer to a structure.
+ * @name: the name of the element inside a structure that you want to read.
+ * @ivalue: vector that will contain the element's content, must be a
+ *   pointer to memory cells already allocated (may be %NULL).
+ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
+ *   holds the sizeof value.
+ *
+ * Returns the value of one element inside a structure.
+ * If an element is OPTIONAL and this returns
+ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
+ * in the der encoding that created the structure.  The first element
+ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
+ * so on. If the @root provided is a node to specific sequence element,
+ * then the keyword "?CURRENT" is also acceptable and indicates the
+ * current sequence element of this node.
+ *
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
+ * INTEGER: VALUE will contain a two's complement form integer.
+ *
+ *            integer=-1  -> value[0]=0xFF , len=1.
+ *            integer=1   -> value[0]=0x01 , len=1.
+ *
+ * ENUMERATED: As INTEGER (but only with not negative numbers).
+ *
+ * BOOLEAN: VALUE will be the null terminated string "TRUE" or
+ *   "FALSE" and LEN=5 or LEN=6.
+ *
+ * OBJECT IDENTIFIER: VALUE will be a null terminated string with
+ *   each number separated by a dot (i.e. "1.2.3.543.1").
+ *
+ *                      LEN = strlen(VALUE)+1
+ *
+ * UTCTime: VALUE will be a null terminated string in one of these
+ *   formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
+ *   LEN=strlen(VALUE)+1.
+ *
+ * GeneralizedTime: VALUE will be a null terminated string in the
+ *   same format used to set the value.
+ *
+ * OCTET STRING: VALUE will contain the octet string and LEN will be
+ *   the number of octets.
+ *
+ * GeneralString: VALUE will contain the generalstring and LEN will
+ *   be the number of octets.
+ *
+ * BIT STRING: VALUE will contain the bit string organized by bytes
+ *   and LEN will be the number of bits.
+ *
+ * CHOICE: If NAME indicates a choice type, VALUE will specify the
+ *   alternative selected.
+ *
+ * ANY: If NAME indicates an any type, VALUE will indicate the DER
+ *   encoding of the structure actually used.
+ *
+ * Returns: %ASN1_SUCCESS if value is returned,
+ *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
+ *   %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
+ *   selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
+ *   to store the result, and in this case @len will contain the number of
+ *   bytes needed. On the occasion that the stored data are of zero-length
+ *   this function may return %ASN1_SUCCESS even if the provided @len is zero.
+ **/
+int
+asn1_read_value (asn1_node_const root, const char *name, void *ivalue,
+		 int *len)
+{
+  return asn1_read_value_type (root, name, ivalue, len, NULL);
+}
+
+/**
+ * asn1_read_value_type:
+ * @root: pointer to a structure.
+ * @name: the name of the element inside a structure that you want to read.
+ * @ivalue: vector that will contain the element's content, must be a
+ *   pointer to memory cells already allocated (may be %NULL).
+ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
+ *   holds the sizeof value.
+ * @etype: The type of the value read (ASN1_ETYPE)
+ *
+ * Returns the type and value of one element inside a structure.
+ * If an element is OPTIONAL and this returns
+ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
+ * in the der encoding that created the structure.  The first element
+ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
+ * so on. If the @root provided is a node to specific sequence element,
+ * then the keyword "?CURRENT" is also acceptable and indicates the
+ * current sequence element of this node.
+ *
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
+ *
+ * INTEGER: VALUE will contain a two's complement form integer.
+ *
+ *            integer=-1  -> value[0]=0xFF , len=1.
+ *            integer=1   -> value[0]=0x01 , len=1.
+ *
+ * ENUMERATED: As INTEGER (but only with not negative numbers).
+ *
+ * BOOLEAN: VALUE will be the null terminated string "TRUE" or
+ *   "FALSE" and LEN=5 or LEN=6.
+ *
+ * OBJECT IDENTIFIER: VALUE will be a null terminated string with
+ *   each number separated by a dot (i.e. "1.2.3.543.1").
+ *
+ *                      LEN = strlen(VALUE)+1
+ *
+ * UTCTime: VALUE will be a null terminated string in one of these
+ *   formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
+ *   LEN=strlen(VALUE)+1.
+ *
+ * GeneralizedTime: VALUE will be a null terminated string in the
+ *   same format used to set the value.
+ *
+ * OCTET STRING: VALUE will contain the octet string and LEN will be
+ *   the number of octets.
+ *
+ * GeneralString: VALUE will contain the generalstring and LEN will
+ *   be the number of octets.
+ *
+ * BIT STRING: VALUE will contain the bit string organized by bytes
+ *   and LEN will be the number of bits.
+ *
+ * CHOICE: If NAME indicates a choice type, VALUE will specify the
+ *   alternative selected.
+ *
+ * ANY: If NAME indicates an any type, VALUE will indicate the DER
+ *   encoding of the structure actually used.
+ *
+ * Returns: %ASN1_SUCCESS if value is returned,
+ *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
+ *   %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
+ *   selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
+ *   to store the result, and in this case @len will contain the number of
+ *   bytes needed. On the occasion that the stored data are of zero-length
+ *   this function may return %ASN1_SUCCESS even if the provided @len is zero.
+ **/
+int
+asn1_read_value_type (asn1_node_const root, const char *name, void *ivalue,
+		      int *len, unsigned int *etype)
+{
+  asn1_node_const node, p, p2;
+  int len2, len3, result;
+  int value_size = *len;
+  unsigned char *value = ivalue;
+  unsigned type;
+
+  node = asn1_find_node (root, name);
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  type = type_field (node->type);
+
+  if ((type != ASN1_ETYPE_NULL) &&
+      (type != ASN1_ETYPE_CHOICE) &&
+      !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) &&
+      (node->value == NULL))
+    return ASN1_VALUE_NOT_FOUND;
+
+  if (etype)
+    *etype = type;
+  switch (type)
+    {
+    case ASN1_ETYPE_NULL:
+      PUT_STR_VALUE (value, value_size, "NULL");
+      break;
+    case ASN1_ETYPE_BOOLEAN:
+      if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+	{
+	  p = node->down;
+	  while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
+	    p = p->right;
+	  if (p->type & CONST_TRUE)
+	    {
+	      PUT_STR_VALUE (value, value_size, "TRUE");
+	    }
+	  else
+	    {
+	      PUT_STR_VALUE (value, value_size, "FALSE");
+	    }
+	}
+      else if (node->value[0] == 'T')
+	{
+	  PUT_STR_VALUE (value, value_size, "TRUE");
+	}
+      else
+	{
+	  PUT_STR_VALUE (value, value_size, "FALSE");
+	}
+      break;
+    case ASN1_ETYPE_INTEGER:
+    case ASN1_ETYPE_ENUMERATED:
+      if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+	{
+	  p = node->down;
+	  while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
+	    p = p->right;
+	  if ((c_isdigit (p->value[0])) || (p->value[0] == '-')
+	      || (p->value[0] == '+'))
+	    {
+	      result = _asn1_convert_integer
+		(p->value, value, value_size, len);
+	      if (result != ASN1_SUCCESS)
+		return result;
+	    }
+	  else
+	    {			/* is an identifier like v1 */
+	      p2 = node->down;
+	      while (p2)
+		{
+		  if (type_field (p2->type) == ASN1_ETYPE_CONSTANT)
+		    {
+		      if (!_asn1_strcmp (p2->name, p->value))
+			{
+			  result = _asn1_convert_integer
+			    (p2->value, value, value_size, len);
+			  if (result != ASN1_SUCCESS)
+			    return result;
+			  break;
+			}
+		    }
+		  p2 = p2->right;
+		}
+	    }
+	}
+      else
+	{
+	  len2 = -1;
+	  result = asn1_get_octet_der
+	    (node->value, node->value_len, &len2, value, value_size, len);
+	  if (result != ASN1_SUCCESS)
+	    return result;
+	}
+      break;
+    case ASN1_ETYPE_OBJECT_ID:
+      if (node->type & CONST_ASSIGN)
+	{
+	  *len = 0;
+	  if (value)
+	    value[0] = 0;
+	  p = node->down;
+	  while (p)
+	    {
+	      if (type_field (p->type) == ASN1_ETYPE_CONSTANT)
+		{
+		  ADD_STR_VALUE (value, value_size, p->value);
+		  if (p->right)
+		    {
+		      ADD_STR_VALUE (value, value_size, ".");
+		    }
+		}
+	      p = p->right;
+	    }
+	  (*len)++;
+	}
+      else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+	{
+	  p = node->down;
+	  while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
+	    p = p->right;
+	  PUT_STR_VALUE (value, value_size, p->value);
+	}
+      else
+	{
+	  PUT_STR_VALUE (value, value_size, node->value);
+	}
+      break;
+    case ASN1_ETYPE_GENERALIZED_TIME:
+    case ASN1_ETYPE_UTC_TIME:
+      PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len);
+      break;
+    case ASN1_ETYPE_OCTET_STRING:
+    case ASN1_ETYPE_GENERALSTRING:
+    case ASN1_ETYPE_NUMERIC_STRING:
+    case ASN1_ETYPE_IA5_STRING:
+    case ASN1_ETYPE_TELETEX_STRING:
+    case ASN1_ETYPE_PRINTABLE_STRING:
+    case ASN1_ETYPE_UNIVERSAL_STRING:
+    case ASN1_ETYPE_BMP_STRING:
+    case ASN1_ETYPE_UTF8_STRING:
+    case ASN1_ETYPE_VISIBLE_STRING:
+      len2 = -1;
+      result = asn1_get_octet_der
+	(node->value, node->value_len, &len2, value, value_size, len);
+      if (result != ASN1_SUCCESS)
+	return result;
+      break;
+    case ASN1_ETYPE_BIT_STRING:
+      len2 = -1;
+      result = asn1_get_bit_der
+	(node->value, node->value_len, &len2, value, value_size, len);
+      if (result != ASN1_SUCCESS)
+	return result;
+      break;
+    case ASN1_ETYPE_CHOICE:
+      PUT_STR_VALUE (value, value_size, node->down->name);
+      break;
+    case ASN1_ETYPE_ANY:
+      len3 = -1;
+      len2 = asn1_get_length_der (node->value, node->value_len, &len3);
+      if (len2 < 0)
+	return ASN1_DER_ERROR;
+      PUT_VALUE (value, value_size, node->value + len3, len2);
+      break;
+    default:
+      return ASN1_ELEMENT_NOT_FOUND;
+      break;
+    }
+  return ASN1_SUCCESS;
+}
+
+
+/**
+ * asn1_read_tag:
+ * @root: pointer to a structure
+ * @name: the name of the element inside a structure.
+ * @tagValue:  variable that will contain the TAG value.
+ * @classValue: variable that will specify the TAG type.
+ *
+ * Returns the TAG and the CLASS of one element inside a structure.
+ * CLASS can have one of these constants: %ASN1_CLASS_APPLICATION,
+ * %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or
+ * %ASN1_CLASS_CONTEXT_SPECIFIC.
+ *
+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
+ *   @name is not a valid element.
+ **/
+int
+asn1_read_tag (asn1_node_const root, const char *name, int *tagValue,
+	       int *classValue)
+{
+  asn1_node node, p, pTag;
+
+  node = asn1_find_node (root, name);
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node->down;
+
+  /* pTag will points to the IMPLICIT TAG */
+  pTag = NULL;
+  if (node->type & CONST_TAG)
+    {
+      while (p)
+	{
+	  if (type_field (p->type) == ASN1_ETYPE_TAG)
+	    {
+	      if ((p->type & CONST_IMPLICIT) && (pTag == NULL))
+		pTag = p;
+	      else if (p->type & CONST_EXPLICIT)
+		pTag = NULL;
+	    }
+	  p = p->right;
+	}
+    }
+
+  if (pTag)
+    {
+      *tagValue = _asn1_strtoul (pTag->value, NULL, 10);
+
+      if (pTag->type & CONST_APPLICATION)
+	*classValue = ASN1_CLASS_APPLICATION;
+      else if (pTag->type & CONST_UNIVERSAL)
+	*classValue = ASN1_CLASS_UNIVERSAL;
+      else if (pTag->type & CONST_PRIVATE)
+	*classValue = ASN1_CLASS_PRIVATE;
+      else
+	*classValue = ASN1_CLASS_CONTEXT_SPECIFIC;
+    }
+  else
+    {
+      unsigned type = type_field (node->type);
+      *classValue = ASN1_CLASS_UNIVERSAL;
+
+      switch (type)
+	{
+	CASE_HANDLED_ETYPES:
+	  *tagValue = _asn1_tags[type].tag;
+	  break;
+	case ASN1_ETYPE_TAG:
+	case ASN1_ETYPE_CHOICE:
+	case ASN1_ETYPE_ANY:
+	  *tagValue = -1;
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  return ASN1_SUCCESS;
+}
+
+/**
+ * asn1_read_node_value:
+ * @node: pointer to a node.
+ * @data: a point to a asn1_data_node_st
+ *
+ * Returns the value a data node inside a asn1_node structure.
+ * The data returned should be handled as constant values.
+ *
+ * Returns: %ASN1_SUCCESS if the node exists.
+ **/
+int
+asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data)
+{
+  data->name = node->name;
+  data->value = node->value;
+  data->value_len = node->value_len;
+  data->type = type_field (node->type);
+
+  return ASN1_SUCCESS;
+}
diff --git a/grub-core/lib/libtasn1/lib/errors.c b/grub-core/lib/libtasn1/lib/errors.c
new file mode 100644
index 0000000..aef5dfe
--- /dev/null
+++ b/grub-core/lib/libtasn1/lib/errors.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <int.h>
+#ifdef STDC_HEADERS
+# include <stdarg.h>
+#endif
+
+#define LIBTASN1_ERROR_ENTRY(name) { #name, name }
+
+struct libtasn1_error_entry
+{
+  const char *name;
+  int number;
+};
+typedef struct libtasn1_error_entry libtasn1_error_entry;
+
+static const libtasn1_error_entry error_algorithms[] = {
+  LIBTASN1_ERROR_ENTRY (ASN1_SUCCESS),
+  LIBTASN1_ERROR_ENTRY (ASN1_FILE_NOT_FOUND),
+  LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_FOUND),
+  LIBTASN1_ERROR_ENTRY (ASN1_IDENTIFIER_NOT_FOUND),
+  LIBTASN1_ERROR_ENTRY (ASN1_DER_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_FOUND),
+  LIBTASN1_ERROR_ENTRY (ASN1_GENERIC_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_VALID),
+  LIBTASN1_ERROR_ENTRY (ASN1_TAG_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_TAG_IMPLICIT),
+  LIBTASN1_ERROR_ENTRY (ASN1_ERROR_TYPE_ANY),
+  LIBTASN1_ERROR_ENTRY (ASN1_SYNTAX_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_MEM_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_MEM_ALLOC_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_DER_OVERFLOW),
+  LIBTASN1_ERROR_ENTRY (ASN1_NAME_TOO_LONG),
+  LIBTASN1_ERROR_ENTRY (ASN1_ARRAY_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_EMPTY),
+  LIBTASN1_ERROR_ENTRY (ASN1_TIME_ENCODING_ERROR),
+  LIBTASN1_ERROR_ENTRY (ASN1_RECURSION),
+  {0, 0}
+};
+
+/**
+ * asn1_perror:
+ * @error: is an error returned by a libtasn1 function.
+ *
+ * Prints a string to stderr with a description of an error.  This
+ * function is like perror().  The only difference is that it accepts
+ * an error returned by a libtasn1 function.
+ *
+ * Since: 1.6
+ **/
+void
+asn1_perror (int error)
+{
+  const char *str = asn1_strerror (error);
+  fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)");
+}
+
+/**
+ * asn1_strerror:
+ * @error: is an error returned by a libtasn1 function.
+ *
+ * Returns a string with a description of an error.  This function is
+ * similar to strerror.  The only difference is that it accepts an
+ * error (number) returned by a libtasn1 function.
+ *
+ * Returns: Pointer to static zero-terminated string describing error
+ *   code.
+ *
+ * Since: 1.6
+ **/
+const char *
+asn1_strerror (int error)
+{
+  const libtasn1_error_entry *p;
+
+  for (p = error_algorithms; p->name != NULL; p++)
+    if (p->number == error)
+      return p->name + sizeof ("ASN1_") - 1;
+
+  return NULL;
+}
diff --git a/grub-core/lib/libtasn1/lib/gstr.c b/grub-core/lib/libtasn1/lib/gstr.c
new file mode 100644
index 0000000..eef4195
--- /dev/null
+++ b/grub-core/lib/libtasn1/lib/gstr.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <int.h>
+#include "gstr.h"
+
+/* These function are like strcat, strcpy. They only
+ * do bounds checking (they shouldn't cause buffer overruns),
+ * and they always produce null terminated strings.
+ *
+ * They should be used only with null terminated strings.
+ */
+void
+_asn1_str_cat (char *dest, size_t dest_tot_size, const char *src)
+{
+  size_t str_size = strlen (src);
+  size_t dest_size = strlen (dest);
+
+  if (dest_tot_size - dest_size > str_size)
+    {
+      strcat (dest, src);
+    }
+  else
+    {
+      if (dest_tot_size > dest_size)
+	{
+	  strncat (dest, src, (dest_tot_size - dest_size) - 1);
+	  dest[dest_tot_size - 1] = 0;
+	}
+    }
+}
+
+/* Returns the bytes copied (not including the null terminator) */
+unsigned int
+_asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src)
+{
+  size_t str_size = strlen (src);
+
+  if (dest_tot_size > str_size)
+    {
+      strcpy (dest, src);
+      return str_size;
+    }
+  else
+    {
+      if (dest_tot_size > 0)
+	{
+	  str_size = dest_tot_size - 1;
+	  memcpy (dest, src, str_size);
+	  dest[str_size] = 0;
+	  return str_size;
+	}
+      else
+	return 0;
+    }
+}
diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c b/grub-core/lib/libtasn1/lib/parser_aux.c
new file mode 100644
index 0000000..c05bd23
--- /dev/null
+++ b/grub-core/lib/libtasn1/lib/parser_aux.c
@@ -0,0 +1,1178 @@
+/*
+ * Copyright (C) 2000-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <limits.h>		/* WORD_BIT */
+
+#include "int.h"
+#include "parser_aux.h"
+#include "gstr.h"
+#include "structure.h"
+#include "element.h"
+#include "c-ctype.h"
+
+char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1];	/* identifier name not found */
+
+/* Return a hash of the N bytes of X using the method described by
+   Bruno Haible in https://www.haible.de/bruno/hashfunc.html.
+   Note that while many hash functions reduce their result via modulo
+   to a 0..table_size-1 range, this function does not do that.
+
+   This implementation has been changed from size_t -> unsigned int. */
+
+#ifdef __clang__
+__attribute__((no_sanitize ("integer")))
+#endif
+     _GL_ATTRIBUTE_PURE static unsigned int _asn1_hash_name (const char *x)
+{
+  const unsigned char *s = (unsigned char *) x;
+  unsigned h = 0;
+
+  while (*s)
+    h = (*s++) + ((h << 9) | (h >> (WORD_BIT - 9)));
+
+  return h;
+}
+
+/******************************************************/
+/* Function : _asn1_add_static_node                   */
+/* Description: creates a new NODE_ASN element and    */
+/* puts it in the list pointed by e_list.       */
+/* Parameters:                                        */
+/*   e_list: of type list_type; must be NULL initially */
+/*   type: type of the new element (see ASN1_ETYPE_   */
+/*         and CONST_ constants).                     */
+/* Return: pointer to the new element.                */
+/******************************************************/
+asn1_node
+_asn1_add_static_node (list_type ** e_list, unsigned int type)
+{
+  list_type *p;
+  asn1_node punt;
+
+  punt = calloc (1, sizeof (struct asn1_node_st));
+  if (punt == NULL)
+    return NULL;
+
+  p = malloc (sizeof (list_type));
+  if (p == NULL)
+    {
+      free (punt);
+      return NULL;
+    }
+
+  p->node = punt;
+  p->next = *e_list;
+  *e_list = p;
+
+  punt->type = type;
+
+  return punt;
+}
+
+static int
+_asn1_add_static_node2 (list_type ** e_list, asn1_node node)
+{
+  list_type *p;
+
+  p = malloc (sizeof (list_type));
+  if (p == NULL)
+    {
+      return -1;
+    }
+
+  p->node = node;
+  p->next = *e_list;
+  *e_list = p;
+
+  return 0;
+}
+
+/**
+ * asn1_find_node:
+ * @pointer: NODE_ASN element pointer.
+ * @name: null terminated string with the element's name to find.
+ *
+ * Searches for an element called @name starting from @pointer.  The
+ * name is composed by different identifiers separated by dots.  When
+ * *@pointer has a name, the first identifier must be the name of
+ * *@pointer, otherwise it must be the name of one child of *@pointer.
+ *
+ * Returns: the search result, or %NULL if not found.
+ **/
+asn1_node
+asn1_find_node (asn1_node_const pointer, const char *name)
+{
+  asn1_node_const p;
+  char *n_end, n[ASN1_MAX_NAME_SIZE + 1];
+  const char *n_start;
+  unsigned int nsize;
+  unsigned int nhash;
+
+  if (pointer == NULL)
+    return NULL;
+
+  if (name == NULL)
+    return NULL;
+
+  p = pointer;
+  n_start = name;
+
+  if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?')
+    {				/* ?CURRENT */
+      n_start = strchr (n_start, '.');
+      if (n_start)
+	n_start++;
+    }
+  else if (p->name[0] != 0)
+    {				/* has *pointer got a name ? */
+      n_end = strchr (n_start, '.');	/* search the first dot */
+      if (n_end)
+	{
+	  nsize = n_end - n_start;
+	  if (nsize >= sizeof (n))
+	    return NULL;
+
+	  memcpy (n, n_start, nsize);
+	  n[nsize] = 0;
+	  n_start = n_end;
+	  n_start++;
+
+	  nhash = _asn1_hash_name (n);
+	}
+      else
+	{
+	  _asn1_str_cpy (n, sizeof (n), n_start);
+	  nhash = _asn1_hash_name (n);
+
+	  n_start = NULL;
+	}
+
+      while (p)
+	{
+	  if (nhash == p->name_hash && (!strcmp (p->name, n)))
+	    break;
+	  else
+	    p = p->right;
+	}			/* while */
+
+      if (p == NULL)
+	return NULL;
+    }
+  else
+    {				/* *pointer doesn't have a name */
+      if (n_start[0] == 0)
+	return (asn1_node) p;
+    }
+
+  while (n_start)
+    {				/* Has the end of NAME been reached? */
+      n_end = strchr (n_start, '.');	/* search the next dot */
+      if (n_end)
+	{
+	  nsize = n_end - n_start;
+	  if (nsize >= sizeof (n))
+	    return NULL;
+
+	  memcpy (n, n_start, nsize);
+	  n[nsize] = 0;
+	  n_start = n_end;
+	  n_start++;
+
+	  nhash = _asn1_hash_name (n);
+	}
+      else
+	{
+	  _asn1_str_cpy (n, sizeof (n), n_start);
+	  nhash = _asn1_hash_name (n);
+	  n_start = NULL;
+	}
+
+      if (p->down == NULL)
+	return NULL;
+
+      p = p->down;
+      if (p == NULL)
+	return NULL;
+
+      /* The identifier "?LAST" indicates the last element
+         in the right chain. */
+      if (n[0] == '?' && n[1] == 'L')	/* ?LAST */
+	{
+	  while (p->right)
+	    p = p->right;
+	}
+      else
+	{			/* no "?LAST" */
+	  while (p)
+	    {
+	      if (p->name_hash == nhash && !strcmp (p->name, n))
+		break;
+	      else
+		p = p->right;
+	    }
+	}
+      if (p == NULL)
+	return NULL;
+    }				/* while */
+
+  return (asn1_node) p;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_set_value                                     */
+/* Description: sets the field VALUE in a NODE_ASN element. The   */
+/*              previous value (if exist) will be lost            */
+/* Parameters:                                                    */
+/*   node: element pointer.                                       */
+/*   value: pointer to the value that you want to set.            */
+/*   len: character number of value.                              */
+/* Return: pointer to the NODE_ASN element.                       */
+/******************************************************************/
+asn1_node
+_asn1_set_value (asn1_node node, const void *value, unsigned int len)
+{
+  if (node == NULL)
+    return node;
+  if (node->value)
+    {
+      if (node->value != node->small_value)
+	free (node->value);
+      node->value = NULL;
+      node->value_len = 0;
+    }
+
+  if (!len)
+    return node;
+
+  if (len < sizeof (node->small_value))
+    {
+      node->value = node->small_value;
+    }
+  else
+    {
+      node->value = malloc (len);
+      if (node->value == NULL)
+	return NULL;
+    }
+  node->value_len = len;
+
+  memcpy (node->value, value, len);
+  return node;
+}
+
+/******************************************************************/
+/* Function : _asn1_set_value_lv                                  */
+/* Description: sets the field VALUE in a NODE_ASN element. The   */
+/*              previous value (if exist) will be lost. The value */
+/*		given is stored as an length-value format (LV     */
+/* Parameters:                                                    */
+/*   node: element pointer.                                       */
+/*   value: pointer to the value that you want to set.            */
+/*   len: character number of value.                              */
+/* Return: pointer to the NODE_ASN element.                       */
+/******************************************************************/
+asn1_node
+_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len)
+{
+  int len2;
+  void *temp;
+
+  if (node == NULL)
+    return node;
+
+  asn1_length_der (len, NULL, &len2);
+  temp = malloc (len + len2);
+  if (temp == NULL)
+    return NULL;
+
+  asn1_octet_der (value, len, temp, &len2);
+  return _asn1_set_value_m (node, temp, len2);
+}
+
+/* the same as _asn1_set_value except that it sets an already malloc'ed
+ * value.
+ */
+asn1_node
+_asn1_set_value_m (asn1_node node, void *value, unsigned int len)
+{
+  if (node == NULL)
+    return node;
+
+  if (node->value)
+    {
+      if (node->value != node->small_value)
+	free (node->value);
+      node->value = NULL;
+      node->value_len = 0;
+    }
+
+  if (!len)
+    return node;
+
+  node->value = value;
+  node->value_len = len;
+
+  return node;
+}
+
+/******************************************************************/
+/* Function : _asn1_append_value                                  */
+/* Description: appends to the field VALUE in a NODE_ASN element. */
+/*							          */
+/* Parameters:                                                    */
+/*   node: element pointer.                                       */
+/*   value: pointer to the value that you want to be appended.    */
+/*   len: character number of value.                              */
+/* Return: pointer to the NODE_ASN element.                       */
+/******************************************************************/
+asn1_node
+_asn1_append_value (asn1_node node, const void *value, unsigned int len)
+{
+  if (node == NULL)
+    return node;
+
+  if (node->value == NULL)
+    return _asn1_set_value (node, value, len);
+
+  if (len == 0)
+    return node;
+
+  if (node->value == node->small_value)
+    {
+      /* value is in node */
+      int prev_len = node->value_len;
+      node->value_len += len;
+      node->value = malloc (node->value_len);
+      if (node->value == NULL)
+	{
+	  node->value_len = 0;
+	  return NULL;
+	}
+
+      if (prev_len > 0)
+	memcpy (node->value, node->small_value, prev_len);
+
+      memcpy (&node->value[prev_len], value, len);
+
+      return node;
+    }
+  else				/* if (node->value != NULL && node->value != node->small_value) */
+    {
+      /* value is allocated */
+      int prev_len = node->value_len;
+      node->value_len += len;
+
+      node->value = _asn1_realloc (node->value, node->value_len);
+      if (node->value == NULL)
+	{
+	  node->value_len = 0;
+	  return NULL;
+	}
+
+      memcpy (&node->value[prev_len], value, len);
+
+      return node;
+    }
+}
+
+/******************************************************************/
+/* Function : _asn1_set_name                                      */
+/* Description: sets the field NAME in a NODE_ASN element. The    */
+/*              previous value (if exist) will be lost            */
+/* Parameters:                                                    */
+/*   node: element pointer.                                       */
+/*   name: a null terminated string with the name that you want   */
+/*         to set.                                                */
+/* Return: pointer to the NODE_ASN element.                       */
+/******************************************************************/
+asn1_node
+_asn1_set_name (asn1_node node, const char *name)
+{
+  if (node == NULL)
+    return node;
+
+  _asn1_str_cpy (node->name, sizeof (node->name), name ? name : "");
+  node->name_hash = _asn1_hash_name (node->name);
+
+  return node;
+}
+
+/******************************************************************/
+/* Function : _asn1_cpy_name                                      */
+/* Description: copies the field NAME in a NODE_ASN element.      */
+/* Parameters:                                                    */
+/*   dst: a dest element pointer.                                 */
+/*   src: a source element pointer.                               */
+/* Return: pointer to the NODE_ASN element.                       */
+/******************************************************************/
+asn1_node
+_asn1_cpy_name (asn1_node dst, asn1_node_const src)
+{
+  if (dst == NULL)
+    return dst;
+
+  if (src == NULL)
+    {
+      dst->name[0] = 0;
+      dst->name_hash = _asn1_hash_name (dst->name);
+      return dst;
+    }
+
+  _asn1_str_cpy (dst->name, sizeof (dst->name), src->name);
+  dst->name_hash = src->name_hash;
+
+  return dst;
+}
+
+/******************************************************************/
+/* Function : _asn1_set_right                                     */
+/* Description: sets the field RIGHT in a NODE_ASN element.       */
+/* Parameters:                                                    */
+/*   node: element pointer.                                       */
+/*   right: pointer to a NODE_ASN element that you want be pointed*/
+/*          by NODE.                                              */
+/* Return: pointer to *NODE.                                      */
+/******************************************************************/
+asn1_node
+_asn1_set_right (asn1_node node, asn1_node right)
+{
+  if (node == NULL)
+    return node;
+  node->right = right;
+  if (right)
+    right->left = node;
+  return node;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_get_last_right                                */
+/* Description: return the last element along the right chain.    */
+/* Parameters:                                                    */
+/*   node: starting element pointer.                              */
+/* Return: pointer to the last element along the right chain.     */
+/******************************************************************/
+asn1_node
+_asn1_get_last_right (asn1_node_const node)
+{
+  asn1_node_const p;
+
+  if (node == NULL)
+    return NULL;
+  p = node;
+  while (p->right)
+    p = p->right;
+  return (asn1_node) p;
+}
+
+/******************************************************************/
+/* Function : _asn1_remove_node                                   */
+/* Description: gets free the memory allocated for an NODE_ASN    */
+/*              element (not the elements pointed by it).         */
+/* Parameters:                                                    */
+/*   node: NODE_ASN element pointer.                              */
+/*   flags: ASN1_DELETE_FLAG_*                                    */
+/******************************************************************/
+void
+_asn1_remove_node (asn1_node node, unsigned int flags)
+{
+  if (node == NULL)
+    return;
+
+  if (node->value != NULL)
+    {
+      if (flags & ASN1_DELETE_FLAG_ZEROIZE)
+	{
+	  safe_memset (node->value, 0, node->value_len);
+	}
+
+      if (node->value != node->small_value)
+	free (node->value);
+    }
+  free (node);
+}
+
+/******************************************************************/
+/* Function : _asn1_find_up                                       */
+/* Description: return the father of the NODE_ASN element.        */
+/* Parameters:                                                    */
+/*   node: NODE_ASN element pointer.                              */
+/* Return: Null if not found.                                     */
+/******************************************************************/
+asn1_node
+_asn1_find_up (asn1_node_const node)
+{
+  asn1_node_const p;
+
+  if (node == NULL)
+    return NULL;
+
+  p = node;
+
+  while ((p->left != NULL) && (p->left->right == p))
+    p = p->left;
+
+  return p->left;
+}
+
+static unsigned
+_asn1_is_up (asn1_node_const up_cand, asn1_node_const down)
+{
+  asn1_node_const d, u;
+
+  if (up_cand == NULL || down == NULL)
+    return 0;
+
+  d = down;
+
+  while ((u = _asn1_find_up (d)) != NULL && u != d)
+    {
+      if (u == up_cand)
+	return 1;
+      d = u;
+    }
+
+  return 0;
+}
+
+/******************************************************************/
+/* Function : _asn1_delete_node_from_list                         */
+/* Description: deletes the list element given                    */
+/******************************************************************/
+void
+_asn1_delete_node_from_list (list_type * list, asn1_node node)
+{
+  list_type *p = list;
+
+  while (p)
+    {
+      if (p->node == node)
+	p->node = NULL;
+      p = p->next;
+    }
+}
+
+/******************************************************************/
+/* Function : _asn1_delete_list                                   */
+/* Description: deletes the list elements (not the elements       */
+/*  pointed by them).                                             */
+/******************************************************************/
+void
+_asn1_delete_list (list_type * e_list)
+{
+  list_type *p;
+
+  while (e_list)
+    {
+      p = e_list;
+      e_list = e_list->next;
+      free (p);
+    }
+}
+
+/******************************************************************/
+/* Function : _asn1_delete_list_and nodes                         */
+/* Description: deletes the list elements and the elements        */
+/*  pointed by them.                                              */
+/******************************************************************/
+void
+_asn1_delete_list_and_nodes (list_type * e_list)
+{
+  list_type *p;
+
+  while (e_list)
+    {
+      p = e_list;
+      e_list = e_list->next;
+      _asn1_remove_node (p->node, 0);
+      free (p);
+    }
+}
+
+
+char *
+_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE])
+{
+  uint64_t d, r;
+  char temp[LTOSTR_MAX_SIZE];
+  int count, k, start;
+  uint64_t val;
+
+  if (v < 0)
+    {
+      str[0] = '-';
+      start = 1;
+      val = -((uint64_t) v);
+    }
+  else
+    {
+      val = v;
+      start = 0;
+    }
+
+  count = 0;
+  do
+    {
+      d = val / 10;
+      r = val - d * 10;
+      temp[start + count] = '0' + (char) r;
+      count++;
+      val = d;
+    }
+  while (val && ((start + count) < LTOSTR_MAX_SIZE - 1));
+
+  for (k = 0; k < count; k++)
+    str[k + start] = temp[start + count - k - 1];
+  str[count + start] = 0;
+  return str;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_change_integer_value                          */
+/* Description: converts into DER coding the value assign to an   */
+/*   INTEGER constant.                                            */
+/* Parameters:                                                    */
+/*   node: root of an ASN1element.                                */
+/* Return:                                                        */
+/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
+/*   otherwise ASN1_SUCCESS                                             */
+/******************************************************************/
+int
+_asn1_change_integer_value (asn1_node node)
+{
+  asn1_node p;
+  unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
+  unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
+  int len;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node;
+  while (p)
+    {
+      if ((type_field (p->type) == ASN1_ETYPE_INTEGER)
+	  && (p->type & CONST_ASSIGN))
+	{
+	  if (p->value)
+	    {
+	      _asn1_convert_integer (p->value, val, sizeof (val), &len);
+	      asn1_octet_der (val, len, val2, &len);
+	      _asn1_set_value (p, val2, len);
+	    }
+	}
+
+      if (p->down)
+	{
+	  p = p->down;
+	}
+      else
+	{
+	  if (p == node)
+	    p = NULL;
+	  else if (p->right)
+	    p = p->right;
+	  else
+	    {
+	      while (1)
+		{
+		  p = _asn1_find_up (p);
+		  if (p == node)
+		    {
+		      p = NULL;
+		      break;
+		    }
+		  if (p && p->right)
+		    {
+		      p = p->right;
+		      break;
+		    }
+		}
+	    }
+	}
+    }
+
+  return ASN1_SUCCESS;
+}
+
+#define MAX_CONSTANTS 1024
+/******************************************************************/
+/* Function : _asn1_expand_object_id                              */
+/* Description: expand the IDs of an OBJECT IDENTIFIER constant.  */
+/* Parameters:                                                    */
+/*   list: root of an object list                                 */
+/*   node: root of an ASN1 element.                               */
+/* Return:                                                        */
+/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                      */
+/*   otherwise ASN1_SUCCESS                                       */
+/******************************************************************/
+int
+_asn1_expand_object_id (list_type ** list, asn1_node node)
+{
+  asn1_node p, p2, p3, p4, p5;
+  char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
+  int move, tlen, tries;
+  unsigned max_constants;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  _asn1_str_cpy (name_root, sizeof (name_root), node->name);
+
+  p = node;
+  move = DOWN;
+  tries = 0;
+
+  while (!((p == node) && (move == UP)))
+    {
+      if (move != UP)
+	{
+	  if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID)
+	      && (p->type & CONST_ASSIGN))
+	    {
+	      p2 = p->down;
+	      if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
+		{
+		  if (p2->value && !c_isdigit (p2->value[0]))
+		    {
+		      _asn1_str_cpy (name2, sizeof (name2), name_root);
+		      _asn1_str_cat (name2, sizeof (name2), ".");
+		      _asn1_str_cat (name2, sizeof (name2),
+				     (char *) p2->value);
+		      p3 = asn1_find_node (node, name2);
+		      if (!p3 || _asn1_is_up (p2, p3) ||
+			  (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) ||
+			  !(p3->type & CONST_ASSIGN))
+			return ASN1_ELEMENT_NOT_FOUND;
+
+		      _asn1_set_down (p, p2->right);
+		      if (p2->down)
+			_asn1_delete_structure (*list, &p2->down, 0);
+		      _asn1_delete_node_from_list (*list, p2);
+		      _asn1_remove_node (p2, 0);
+		      p2 = p;
+		      p4 = p3->down;
+		      max_constants = 0;
+		      while (p4)
+			{
+			  if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
+			    {
+			      max_constants++;
+			      if (max_constants == MAX_CONSTANTS)
+				return ASN1_RECURSION;
+
+			      p5 =
+				_asn1_add_single_node (ASN1_ETYPE_CONSTANT);
+			      _asn1_set_name (p5, p4->name);
+			      if (p4->value)
+				{
+				  tlen = _asn1_strlen (p4->value);
+				  if (tlen > 0)
+				    _asn1_set_value (p5, p4->value, tlen + 1);
+				}
+			      _asn1_add_static_node2 (list, p5);
+
+			      if (p2 == p)
+				{
+				  _asn1_set_right (p5, p->down);
+				  _asn1_set_down (p, p5);
+				}
+			      else
+				{
+				  _asn1_set_right (p5, p2->right);
+				  _asn1_set_right (p2, p5);
+				}
+			      p2 = p5;
+			    }
+			  p4 = p4->right;
+			}
+		      move = DOWN;
+
+		      tries++;
+		      if (tries >= EXPAND_OBJECT_ID_MAX_RECURSION)
+			return ASN1_RECURSION;
+
+		      continue;
+		    }
+		}
+	    }
+	  move = DOWN;
+	}
+      else
+	move = RIGHT;
+
+      tries = 0;
+      if (move == DOWN)
+	{
+	  if (p->down)
+	    p = p->down;
+	  else
+	    move = RIGHT;
+	}
+
+      if (p == node)
+	{
+	  move = UP;
+	  continue;
+	}
+
+      if (move == RIGHT)
+	{
+	  if (p && p->right)
+	    p = p->right;
+	  else
+	    move = UP;
+	}
+      if (move == UP)
+	p = _asn1_find_up (p);
+    }
+
+  /*******************************/
+  /*       expand DEFAULT        */
+  /*******************************/
+  p = node;
+  move = DOWN;
+
+  while (!((p == node) && (move == UP)))
+    {
+      if (move != UP)
+	{
+	  if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
+	      (p->type & CONST_DEFAULT))
+	    {
+	      p2 = p->down;
+	      if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
+		{
+		  _asn1_str_cpy (name2, sizeof (name2), name_root);
+		  _asn1_str_cat (name2, sizeof (name2), ".");
+		  if (p2->value)
+		    _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
+		  p3 = asn1_find_node (node, name2);
+		  if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
+		      || !(p3->type & CONST_ASSIGN))
+		    return ASN1_ELEMENT_NOT_FOUND;
+		  p4 = p3->down;
+		  name2[0] = 0;
+		  while (p4)
+		    {
+		      if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
+			{
+			  if (p4->value == NULL)
+			    return ASN1_VALUE_NOT_FOUND;
+
+			  if (name2[0])
+			    _asn1_str_cat (name2, sizeof (name2), ".");
+			  _asn1_str_cat (name2, sizeof (name2),
+					 (char *) p4->value);
+			}
+		      p4 = p4->right;
+		    }
+		  tlen = strlen (name2);
+		  if (tlen > 0)
+		    _asn1_set_value (p2, name2, tlen + 1);
+		}
+	    }
+	  move = DOWN;
+	}
+      else
+	move = RIGHT;
+
+      if (move == DOWN)
+	{
+	  if (p->down)
+	    p = p->down;
+	  else
+	    move = RIGHT;
+	}
+
+      if (p == node)
+	{
+	  move = UP;
+	  continue;
+	}
+
+      if (move == RIGHT)
+	{
+	  if (p && p->right)
+	    p = p->right;
+	  else
+	    move = UP;
+	}
+      if (move == UP)
+	p = _asn1_find_up (p);
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_type_set_config                               */
+/* Description: sets the CONST_SET and CONST_NOT_USED properties  */
+/*   in the fields of the SET elements.                           */
+/* Parameters:                                                    */
+/*   node: root of an ASN1 element.                               */
+/* Return:                                                        */
+/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
+/*   otherwise ASN1_SUCCESS                                             */
+/******************************************************************/
+int
+_asn1_type_set_config (asn1_node node)
+{
+  asn1_node p, p2;
+  int move;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node;
+  move = DOWN;
+
+  while (!((p == node) && (move == UP)))
+    {
+      if (move != UP)
+	{
+	  if (type_field (p->type) == ASN1_ETYPE_SET)
+	    {
+	      p2 = p->down;
+	      while (p2)
+		{
+		  if (type_field (p2->type) != ASN1_ETYPE_TAG)
+		    p2->type |= CONST_SET | CONST_NOT_USED;
+		  p2 = p2->right;
+		}
+	    }
+	  move = DOWN;
+	}
+      else
+	move = RIGHT;
+
+      if (move == DOWN)
+	{
+	  if (p->down)
+	    p = p->down;
+	  else
+	    move = RIGHT;
+	}
+
+      if (p == node)
+	{
+	  move = UP;
+	  continue;
+	}
+
+      if (move == RIGHT)
+	{
+	  if (p && p->right)
+	    p = p->right;
+	  else
+	    move = UP;
+	}
+      if (move == UP)
+	p = _asn1_find_up (p);
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_check_identifier                              */
+/* Description: checks the definitions of all the identifiers     */
+/*   and the first element of an OBJECT_ID (e.g. {pkix 0 4}).     */
+/*   The _asn1_identifierMissing global variable is filled if     */
+/*   necessary.                                                   */
+/* Parameters:                                                    */
+/*   node: root of an ASN1 element.                               */
+/* Return:                                                        */
+/*   ASN1_ELEMENT_NOT_FOUND      if NODE is NULL,                 */
+/*   ASN1_IDENTIFIER_NOT_FOUND   if an identifier is not defined, */
+/*   otherwise ASN1_SUCCESS                                       */
+/******************************************************************/
+int
+_asn1_check_identifier (asn1_node_const node)
+{
+  asn1_node_const p, p2;
+  char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node;
+  while (p)
+    {
+      if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
+	{
+	  _asn1_str_cpy (name2, sizeof (name2), node->name);
+	  _asn1_str_cat (name2, sizeof (name2), ".");
+	  _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
+	  p2 = asn1_find_node (node, name2);
+	  if (p2 == NULL)
+	    {
+	      if (p->value)
+		_asn1_str_cpy (_asn1_identifierMissing,
+			       sizeof (_asn1_identifierMissing),
+			       (char *) p->value);
+	      else
+		_asn1_strcpy (_asn1_identifierMissing, "(null)");
+	      return ASN1_IDENTIFIER_NOT_FOUND;
+	    }
+	}
+      else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
+	       (p->type & CONST_DEFAULT))
+	{
+	  p2 = p->down;
+	  if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
+	    {
+	      _asn1_str_cpy (name2, sizeof (name2), node->name);
+	      if (p2->value)
+		{
+		  _asn1_str_cat (name2, sizeof (name2), ".");
+		  _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
+		  _asn1_str_cpy (_asn1_identifierMissing,
+				 sizeof (_asn1_identifierMissing),
+				 (char *) p2->value);
+		}
+	      else
+		_asn1_strcpy (_asn1_identifierMissing, "(null)");
+
+	      p2 = asn1_find_node (node, name2);
+	      if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ||
+		  !(p2->type & CONST_ASSIGN))
+		return ASN1_IDENTIFIER_NOT_FOUND;
+	      else
+		_asn1_identifierMissing[0] = 0;
+	    }
+	}
+      else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
+	       (p->type & CONST_ASSIGN))
+	{
+	  p2 = p->down;
+	  if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
+	    {
+	      if (p2->value && !c_isdigit (p2->value[0]))
+		{
+		  _asn1_str_cpy (name2, sizeof (name2), node->name);
+		  _asn1_str_cat (name2, sizeof (name2), ".");
+		  _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
+		  _asn1_str_cpy (_asn1_identifierMissing,
+				 sizeof (_asn1_identifierMissing),
+				 (char *) p2->value);
+
+		  p2 = asn1_find_node (node, name2);
+		  if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID)
+		      || !(p2->type & CONST_ASSIGN))
+		    return ASN1_IDENTIFIER_NOT_FOUND;
+		  else
+		    _asn1_identifierMissing[0] = 0;
+		}
+	    }
+	}
+
+      if (p->down)
+	{
+	  p = p->down;
+	}
+      else if (p->right)
+	p = p->right;
+      else
+	{
+	  while (p)
+	    {
+	      p = _asn1_find_up (p);
+	      if (p == node)
+		{
+		  p = NULL;
+		  break;
+		}
+	      if (p && p->right)
+		{
+		  p = p->right;
+		  break;
+		}
+	    }
+	}
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_set_default_tag                               */
+/* Description: sets the default IMPLICIT or EXPLICIT property in */
+/*   the tagged elements that don't have this declaration.        */
+/* Parameters:                                                    */
+/*   node: pointer to a DEFINITIONS element.                      */
+/* Return:                                                        */
+/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to   */
+/*     a DEFINITIONS element,                                     */
+/*   otherwise ASN1_SUCCESS                                       */
+/******************************************************************/
+int
+_asn1_set_default_tag (asn1_node node)
+{
+  asn1_node p;
+
+  if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS))
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node;
+  while (p)
+    {
+      if ((type_field (p->type) == ASN1_ETYPE_TAG) &&
+	  !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
+	{
+	  if (node->type & CONST_EXPLICIT)
+	    p->type |= CONST_EXPLICIT;
+	  else
+	    p->type |= CONST_IMPLICIT;
+	}
+
+      if (p->down)
+	{
+	  p = p->down;
+	}
+      else if (p->right)
+	p = p->right;
+      else
+	{
+	  while (1)
+	    {
+	      p = _asn1_find_up (p);
+	      if (p == node)
+		{
+		  p = NULL;
+		  break;
+		}
+	      if (p && p->right)
+		{
+		  p = p->right;
+		  break;
+		}
+	    }
+	}
+    }
+
+  return ASN1_SUCCESS;
+}
diff --git a/grub-core/lib/libtasn1/lib/structure.c b/grub-core/lib/libtasn1/lib/structure.c
new file mode 100644
index 0000000..512dd60
--- /dev/null
+++ b/grub-core/lib/libtasn1/lib/structure.c
@@ -0,0 +1,1225 @@
+/*
+ * Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * The LIBTASN1 library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+
+/*****************************************************/
+/* File: structure.c                                 */
+/* Description: Functions to create and delete an    */
+/*  ASN1 tree.                                       */
+/*****************************************************/
+
+
+#include <int.h>
+#include <structure.h>
+#include "parser_aux.h"
+#include <gstr.h>
+
+
+extern char _asn1_identifierMissing[];
+
+
+/******************************************************/
+/* Function : _asn1_add_single_node                     */
+/* Description: creates a new NODE_ASN element.       */
+/* Parameters:                                        */
+/*   type: type of the new element (see ASN1_ETYPE_         */
+/*         and CONST_ constants).                     */
+/* Return: pointer to the new element.                */
+/******************************************************/
+asn1_node
+_asn1_add_single_node (unsigned int type)
+{
+  asn1_node punt;
+
+  punt = calloc (1, sizeof (struct asn1_node_st));
+  if (punt == NULL)
+    return NULL;
+
+  punt->type = type;
+
+  return punt;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_find_left                                     */
+/* Description: returns the NODE_ASN element with RIGHT field that*/
+/*              points the element NODE.                          */
+/* Parameters:                                                    */
+/*   node: NODE_ASN element pointer.                              */
+/* Return: NULL if not found.                                     */
+/******************************************************************/
+asn1_node
+_asn1_find_left (asn1_node_const node)
+{
+  if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
+    return NULL;
+
+  return node->left;
+}
+
+
+int
+_asn1_create_static_structure (asn1_node_const pointer,
+			       char *output_file_name, char *vector_name)
+{
+  FILE *file;
+  asn1_node_const p;
+  unsigned long t;
+
+  file = fopen (output_file_name, "w");
+
+  if (file == NULL)
+    return ASN1_FILE_NOT_FOUND;
+
+  fprintf (file, "#if HAVE_CONFIG_H\n");
+  fprintf (file, "# include \"config.h\"\n");
+  fprintf (file, "#endif\n\n");
+
+  fprintf (file, "#include <libtasn1.h>\n\n");
+
+  fprintf (file, "const asn1_static_node %s[] = {\n", vector_name);
+
+  p = pointer;
+
+  while (p)
+    {
+      fprintf (file, "  { ");
+
+      if (p->name[0] != 0)
+	fprintf (file, "\"%s\", ", p->name);
+      else
+	fprintf (file, "NULL, ");
+
+      t = p->type;
+      if (p->down)
+	t |= CONST_DOWN;
+      if (p->right)
+	t |= CONST_RIGHT;
+
+      fprintf (file, "%lu, ", t);
+
+      if (p->value)
+	fprintf (file, "\"%s\"},\n", p->value);
+      else
+	fprintf (file, "NULL },\n");
+
+      if (p->down)
+	{
+	  p = p->down;
+	}
+      else if (p->right)
+	{
+	  p = p->right;
+	}
+      else
+	{
+	  while (1)
+	    {
+	      p = _asn1_find_up (p);
+	      if (p == pointer)
+		{
+		  p = NULL;
+		  break;
+		}
+	      if (p->right)
+		{
+		  p = p->right;
+		  break;
+		}
+	    }
+	}
+    }
+
+  fprintf (file, "  { NULL, 0, NULL }\n};\n");
+
+  fclose (file);
+
+  return ASN1_SUCCESS;
+}
+
+
+/**
+ * asn1_array2tree:
+ * @array: specify the array that contains ASN.1 declarations
+ * @definitions: return the pointer to the structure created by
+ *   *ARRAY ASN.1 declarations
+ * @errorDescription: return the error description.
+ *
+ * Creates the structures needed to manage the ASN.1 definitions.
+ * @array is a vector created by asn1_parser2array().
+ *
+ * Returns: %ASN1_SUCCESS if structure was created correctly,
+ *   %ASN1_ELEMENT_NOT_EMPTY if *@definitions not NULL,
+ *   %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier
+ *   that is not defined (see @errorDescription for more information),
+ *   %ASN1_ARRAY_ERROR if the array pointed by @array is wrong.
+ **/
+int
+asn1_array2tree (const asn1_static_node * array, asn1_node * definitions,
+		 char *errorDescription)
+{
+  asn1_node p, p_last = NULL;
+  unsigned long k;
+  int move;
+  int result;
+  unsigned int type;
+  list_type *e_list = NULL;
+
+  if (errorDescription)
+    errorDescription[0] = 0;
+
+  if (*definitions != NULL)
+    return ASN1_ELEMENT_NOT_EMPTY;
+
+  move = UP;
+
+  for (k = 0; array[k].value || array[k].type || array[k].name; k++)
+    {
+      type = convert_old_type (array[k].type);
+
+      p = _asn1_add_static_node (&e_list, type & (~CONST_DOWN));
+      if (array[k].name)
+	_asn1_set_name (p, array[k].name);
+      if (array[k].value)
+	_asn1_set_value (p, array[k].value, strlen (array[k].value) + 1);
+
+      if (*definitions == NULL)
+	*definitions = p;
+
+      if (move == DOWN)
+	{
+	  if (p_last && p_last->down)
+	    _asn1_delete_structure (e_list, &p_last->down, 0);
+	  _asn1_set_down (p_last, p);
+	}
+      else if (move == RIGHT)
+	{
+	  if (p_last && p_last->right)
+	    _asn1_delete_structure (e_list, &p_last->right, 0);
+	  _asn1_set_right (p_last, p);
+	}
+
+      p_last = p;
+
+      if (type & CONST_DOWN)
+	move = DOWN;
+      else if (type & CONST_RIGHT)
+	move = RIGHT;
+      else
+	{
+	  while (p_last != *definitions)
+	    {
+	      p_last = _asn1_find_up (p_last);
+
+	      if (p_last == NULL)
+		break;
+
+	      if (p_last->type & CONST_RIGHT)
+		{
+		  p_last->type &= ~CONST_RIGHT;
+		  move = RIGHT;
+		  break;
+		}
+	    }			/* while */
+	}
+    }				/* while */
+
+  if (p_last == *definitions)
+    {
+      result = _asn1_check_identifier (*definitions);
+      if (result == ASN1_SUCCESS)
+	{
+	  _asn1_change_integer_value (*definitions);
+	  result = _asn1_expand_object_id (&e_list, *definitions);
+	}
+    }
+  else
+    {
+      result = ASN1_ARRAY_ERROR;
+    }
+
+  if (errorDescription != NULL)
+    {
+      if (result == ASN1_IDENTIFIER_NOT_FOUND)
+	{
+	  Estrcpy (errorDescription, ":: identifier '");
+	  Estrcat (errorDescription, _asn1_identifierMissing);
+	  Estrcat (errorDescription, "' not found");
+	}
+      else
+	errorDescription[0] = 0;
+    }
+
+  if (result != ASN1_SUCCESS)
+    {
+      _asn1_delete_list_and_nodes (e_list);
+      *definitions = NULL;
+    }
+  else
+    _asn1_delete_list (e_list);
+
+  return result;
+}
+
+/**
+ * asn1_delete_structure:
+ * @structure: pointer to the structure that you want to delete.
+ *
+ * Deletes the structure *@structure.  At the end, *@structure is set
+ * to NULL.
+ *
+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
+ *   *@structure was NULL.
+ **/
+int
+asn1_delete_structure (asn1_node * structure)
+{
+  return _asn1_delete_structure (NULL, structure, 0);
+}
+
+/**
+ * asn1_delete_structure2:
+ * @structure: pointer to the structure that you want to delete.
+ * @flags: additional flags (see %ASN1_DELETE_FLAG_ZEROIZE)
+ *
+ * Deletes the structure *@structure.  At the end, *@structure is set
+ * to NULL.
+ *
+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
+ *   *@structure was NULL.
+ **/
+int
+asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
+{
+  return _asn1_delete_structure (NULL, structure, flags);
+}
+
+int
+_asn1_delete_structure (list_type * e_list, asn1_node * structure,
+			unsigned int flags)
+{
+  asn1_node p, p2, p3;
+
+  if (*structure == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = *structure;
+  while (p)
+    {
+      if (p->down)
+	{
+	  p = p->down;
+	}
+      else
+	{			/* no down */
+	  p2 = p->right;
+	  if (p != *structure)
+	    {
+	      p3 = _asn1_find_up (p);
+	      _asn1_set_down (p3, p2);
+	      if (e_list)
+		_asn1_delete_node_from_list (e_list, p);
+	      _asn1_remove_node (p, flags);
+	      p = p3;
+	    }
+	  else
+	    {			/* p==root */
+	      p3 = _asn1_find_left (p);
+	      if (!p3)
+		{
+		  p3 = _asn1_find_up (p);
+		  if (p3)
+		    _asn1_set_down (p3, p2);
+		  else
+		    {
+		      if (p->right)
+			p->right->left = NULL;
+		    }
+		}
+	      else
+		_asn1_set_right (p3, p2);
+	      if (e_list)
+		_asn1_delete_node_from_list (e_list, p);
+	      _asn1_remove_node (p, flags);
+	      p = NULL;
+	    }
+	}
+    }
+
+  *structure = NULL;
+  return ASN1_SUCCESS;
+}
+
+
+/**
+ * asn1_delete_element:
+ * @structure: pointer to the structure that contains the element you
+ *   want to delete.
+ * @element_name: element's name you want to delete.
+ *
+ * Deletes the element named *@element_name inside *@structure.
+ *
+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
+ *   the @element_name was not found.
+ **/
+int
+asn1_delete_element (asn1_node structure, const char *element_name)
+{
+  asn1_node p2, p3, source_node;
+
+  source_node = asn1_find_node (structure, element_name);
+
+  if (source_node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p2 = source_node->right;
+  p3 = _asn1_find_left (source_node);
+  if (!p3)
+    {
+      p3 = _asn1_find_up (source_node);
+      if (p3)
+	_asn1_set_down (p3, p2);
+      else if (source_node->right)
+	source_node->right->left = NULL;
+    }
+  else
+    _asn1_set_right (p3, p2);
+
+  return asn1_delete_structure (&source_node);
+}
+
+#ifndef __clang_analyzer__
+asn1_node
+_asn1_copy_structure3 (asn1_node_const source_node)
+{
+  asn1_node_const p_s;
+  asn1_node dest_node, p_d, p_d_prev;
+  int move;
+
+  if (source_node == NULL)
+    return NULL;
+
+  dest_node = _asn1_add_single_node (source_node->type);
+  if (dest_node == NULL)
+    return dest_node;
+
+  p_s = source_node;
+  p_d = dest_node;
+
+  move = DOWN;
+
+  do
+    {
+      if (move != UP)
+	{
+	  if (p_s->name[0] != 0)
+	    _asn1_cpy_name (p_d, p_s);
+	  if (p_s->value)
+	    _asn1_set_value (p_d, p_s->value, p_s->value_len);
+	  if (p_s->down)
+	    {
+	      p_s = p_s->down;
+	      p_d_prev = p_d;
+	      p_d = _asn1_add_single_node (p_s->type);
+	      _asn1_set_down (p_d_prev, p_d);
+	      continue;
+	    }
+	  p_d->start = p_s->start;
+	  p_d->end = p_s->end;
+	}
+
+      if (p_s == source_node)
+	break;
+
+      if (p_s->right)
+	{
+	  move = RIGHT;
+	  p_s = p_s->right;
+	  p_d_prev = p_d;
+	  p_d = _asn1_add_single_node (p_s->type);
+	  _asn1_set_right (p_d_prev, p_d);
+	}
+      else
+	{
+	  move = UP;
+	  p_s = _asn1_find_up (p_s);
+	  p_d = _asn1_find_up (p_d);
+	}
+    }
+  while (p_s != source_node);
+  return dest_node;
+}
+#else
+
+/* Non-production code */
+asn1_node
+_asn1_copy_structure3 (asn1_node_const source_node)
+{
+  return NULL;
+}
+#endif /* __clang_analyzer__ */
+
+
+static asn1_node
+_asn1_copy_structure2 (asn1_node_const root, const char *source_name)
+{
+  asn1_node source_node;
+
+  source_node = asn1_find_node (root, source_name);
+
+  return _asn1_copy_structure3 (source_node);
+
+}
+
+
+static int
+_asn1_type_choice_config (asn1_node node)
+{
+  asn1_node p, p2, p3, p4;
+  int move, tlen;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node;
+  move = DOWN;
+
+  while (!((p == node) && (move == UP)))
+    {
+      if (move != UP)
+	{
+	  if ((type_field (p->type) == ASN1_ETYPE_CHOICE)
+	      && (p->type & CONST_TAG))
+	    {
+	      p2 = p->down;
+	      while (p2)
+		{
+		  if (type_field (p2->type) != ASN1_ETYPE_TAG)
+		    {
+		      p2->type |= CONST_TAG;
+		      p3 = _asn1_find_left (p2);
+		      while (p3)
+			{
+			  if (type_field (p3->type) == ASN1_ETYPE_TAG)
+			    {
+			      p4 = _asn1_add_single_node (p3->type);
+			      tlen = _asn1_strlen (p3->value);
+			      if (tlen > 0)
+				_asn1_set_value (p4, p3->value, tlen + 1);
+			      _asn1_set_right (p4, p2->down);
+			      _asn1_set_down (p2, p4);
+			    }
+			  p3 = _asn1_find_left (p3);
+			}
+		    }
+		  p2 = p2->right;
+		}
+	      p->type &= ~(CONST_TAG);
+	      p2 = p->down;
+	      while (p2)
+		{
+		  p3 = p2->right;
+		  if (type_field (p2->type) == ASN1_ETYPE_TAG)
+		    asn1_delete_structure (&p2);
+		  p2 = p3;
+		}
+	    }
+	  move = DOWN;
+	}
+      else
+	move = RIGHT;
+
+      if (move == DOWN)
+	{
+	  if (p->down)
+	    p = p->down;
+	  else
+	    move = RIGHT;
+	}
+
+      if (p == node)
+	{
+	  move = UP;
+	  continue;
+	}
+
+      if (move == RIGHT)
+	{
+	  if (p->right)
+	    p = p->right;
+	  else
+	    move = UP;
+	}
+      if (move == UP)
+	p = _asn1_find_up (p);
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+static int
+_asn1_expand_identifier (asn1_node * node, asn1_node_const root)
+{
+  asn1_node p, p2, p3;
+  char name2[ASN1_MAX_NAME_SIZE + 2];
+  int move;
+
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = *node;
+  move = DOWN;
+
+  while (!((p == *node) && (move == UP)))
+    {
+      if (move != UP)
+	{
+	  if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
+	    {
+	      snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value);
+	      p2 = _asn1_copy_structure2 (root, name2);
+	      if (p2 == NULL)
+		{
+		  return ASN1_IDENTIFIER_NOT_FOUND;
+		}
+	      _asn1_cpy_name (p2, p);
+	      p2->right = p->right;
+	      p2->left = p->left;
+	      if (p->right)
+		p->right->left = p2;
+	      p3 = p->down;
+	      if (p3)
+		{
+		  while (p3->right)
+		    p3 = p3->right;
+		  _asn1_set_right (p3, p2->down);
+		  _asn1_set_down (p2, p->down);
+		}
+
+	      p3 = _asn1_find_left (p);
+	      if (p3)
+		_asn1_set_right (p3, p2);
+	      else
+		{
+		  p3 = _asn1_find_up (p);
+		  if (p3)
+		    _asn1_set_down (p3, p2);
+		  else
+		    {
+		      p2->left = NULL;
+		    }
+		}
+
+	      if (p->type & CONST_SIZE)
+		p2->type |= CONST_SIZE;
+	      if (p->type & CONST_TAG)
+		p2->type |= CONST_TAG;
+	      if (p->type & CONST_OPTION)
+		p2->type |= CONST_OPTION;
+	      if (p->type & CONST_DEFAULT)
+		p2->type |= CONST_DEFAULT;
+	      if (p->type & CONST_SET)
+		p2->type |= CONST_SET;
+	      if (p->type & CONST_NOT_USED)
+		p2->type |= CONST_NOT_USED;
+
+	      if (p == *node)
+		*node = p2;
+	      _asn1_remove_node (p, 0);
+	      p = p2;
+	      move = DOWN;
+	      continue;
+	    }
+	  move = DOWN;
+	}
+      else
+	move = RIGHT;
+
+      if (move == DOWN)
+	{
+	  if (p->down)
+	    p = p->down;
+	  else
+	    move = RIGHT;
+	}
+
+      if (p == *node)
+	{
+	  move = UP;
+	  continue;
+	}
+
+      if (move == RIGHT)
+	{
+	  if (p->right)
+	    p = p->right;
+	  else
+	    move = UP;
+	}
+      if (move == UP)
+	p = _asn1_find_up (p);
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+/**
+ * asn1_create_element:
+ * @definitions: pointer to the structure returned by "parser_asn1" function
+ * @source_name: the name of the type of the new structure (must be
+ *   inside p_structure).
+ * @element: pointer to the structure created.
+ *
+ * Creates a structure of type @source_name.  Example using
+ *  "pkix.asn":
+ *
+ * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
+ *
+ * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
+ *   @source_name is not known.
+ **/
+int
+asn1_create_element (asn1_node_const definitions, const char *source_name,
+		     asn1_node * element)
+{
+  asn1_node dest_node;
+  int res;
+
+  dest_node = _asn1_copy_structure2 (definitions, source_name);
+
+  if (dest_node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  _asn1_set_name (dest_node, "");
+
+  res = _asn1_expand_identifier (&dest_node, definitions);
+  _asn1_type_choice_config (dest_node);
+
+  *element = dest_node;
+
+  return res;
+}
+
+
+/**
+ * asn1_print_structure:
+ * @out: pointer to the output file (e.g. stdout).
+ * @structure: pointer to the structure that you want to visit.
+ * @name: an element of the structure
+ * @mode: specify how much of the structure to print, can be
+ *   %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
+ *   %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
+ *
+ * Prints on the @out file descriptor the structure's tree starting
+ * from the @name element inside the structure @structure.
+ **/
+void
+asn1_print_structure (FILE * out, asn1_node_const structure, const char *name,
+		      int mode)
+{
+  asn1_node_const p, root;
+  int k, indent = 0, len, len2, len3;
+
+  if (out == NULL)
+    return;
+
+  root = asn1_find_node (structure, name);
+
+  if (root == NULL)
+    return;
+
+  p = root;
+  while (p)
+    {
+      if (mode == ASN1_PRINT_ALL)
+	{
+	  for (k = 0; k < indent; k++)
+	    fprintf (out, " ");
+	  fprintf (out, "name:");
+	  if (p->name[0] != 0)
+	    fprintf (out, "%s  ", p->name);
+	  else
+	    fprintf (out, "NULL  ");
+	}
+      else
+	{
+	  switch (type_field (p->type))
+	    {
+	    case ASN1_ETYPE_CONSTANT:
+	    case ASN1_ETYPE_TAG:
+	    case ASN1_ETYPE_SIZE:
+	      break;
+	    default:
+	      for (k = 0; k < indent; k++)
+		fprintf (out, " ");
+	      fprintf (out, "name:");
+	      if (p->name[0] != 0)
+		fprintf (out, "%s  ", p->name);
+	      else
+		fprintf (out, "NULL  ");
+	    }
+	}
+
+      if (mode != ASN1_PRINT_NAME)
+	{
+	  unsigned type = type_field (p->type);
+	  switch (type)
+	    {
+	    case ASN1_ETYPE_CONSTANT:
+	      if (mode == ASN1_PRINT_ALL)
+		fprintf (out, "type:CONST");
+	      break;
+	    case ASN1_ETYPE_TAG:
+	      if (mode == ASN1_PRINT_ALL)
+		fprintf (out, "type:TAG");
+	      break;
+	    case ASN1_ETYPE_SIZE:
+	      if (mode == ASN1_PRINT_ALL)
+		fprintf (out, "type:SIZE");
+	      break;
+	    case ASN1_ETYPE_DEFAULT:
+	      fprintf (out, "type:DEFAULT");
+	      break;
+	    case ASN1_ETYPE_IDENTIFIER:
+	      fprintf (out, "type:IDENTIFIER");
+	      break;
+	    case ASN1_ETYPE_ANY:
+	      fprintf (out, "type:ANY");
+	      break;
+	    case ASN1_ETYPE_CHOICE:
+	      fprintf (out, "type:CHOICE");
+	      break;
+	    case ASN1_ETYPE_DEFINITIONS:
+	      fprintf (out, "type:DEFINITIONS");
+	      break;
+	    CASE_HANDLED_ETYPES:
+	      fprintf (out, "%s", _asn1_tags[type].desc);
+	      break;
+	    default:
+	      break;
+	    }
+	}
+
+      if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL))
+	{
+	  switch (type_field (p->type))
+	    {
+	    case ASN1_ETYPE_CONSTANT:
+	      if (mode == ASN1_PRINT_ALL)
+		if (p->value)
+		  fprintf (out, "  value:%s", p->value);
+	      break;
+	    case ASN1_ETYPE_TAG:
+	      if (mode == ASN1_PRINT_ALL)
+		if (p->value)
+		  fprintf (out, "  value:%s", p->value);
+	      break;
+	    case ASN1_ETYPE_SIZE:
+	      if (mode == ASN1_PRINT_ALL)
+		if (p->value)
+		  fprintf (out, "  value:%s", p->value);
+	      break;
+	    case ASN1_ETYPE_DEFAULT:
+	      if (p->value)
+		fprintf (out, "  value:%s", p->value);
+	      else if (p->type & CONST_TRUE)
+		fprintf (out, "  value:TRUE");
+	      else if (p->type & CONST_FALSE)
+		fprintf (out, "  value:FALSE");
+	      break;
+	    case ASN1_ETYPE_IDENTIFIER:
+	      if (p->value)
+		fprintf (out, "  value:%s", p->value);
+	      break;
+	    case ASN1_ETYPE_INTEGER:
+	      if (p->value)
+		{
+		  len2 = -1;
+		  len = asn1_get_length_der (p->value, p->value_len, &len2);
+		  fprintf (out, "  value:0x");
+		  if (len > 0)
+		    for (k = 0; k < len; k++)
+		      fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
+		}
+	      break;
+	    case ASN1_ETYPE_ENUMERATED:
+	      if (p->value)
+		{
+		  len2 = -1;
+		  len = asn1_get_length_der (p->value, p->value_len, &len2);
+		  fprintf (out, "  value:0x");
+		  if (len > 0)
+		    for (k = 0; k < len; k++)
+		      fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
+		}
+	      break;
+	    case ASN1_ETYPE_BOOLEAN:
+	      if (p->value)
+		{
+		  if (p->value[0] == 'T')
+		    fprintf (out, "  value:TRUE");
+		  else if (p->value[0] == 'F')
+		    fprintf (out, "  value:FALSE");
+		}
+	      break;
+	    case ASN1_ETYPE_BIT_STRING:
+	      if (p->value)
+		{
+		  len2 = -1;
+		  len = asn1_get_length_der (p->value, p->value_len, &len2);
+		  if (len > 0)
+		    {
+		      fprintf (out, "  value(%i):",
+			       (len - 1) * 8 - (p->value[len2]));
+		      for (k = 1; k < len; k++)
+			fprintf (out, "%02x",
+				 (unsigned) (p->value)[k + len2]);
+		    }
+		}
+	      break;
+	    case ASN1_ETYPE_GENERALIZED_TIME:
+	    case ASN1_ETYPE_UTC_TIME:
+	      if (p->value)
+		{
+		  fprintf (out, "  value:");
+		  for (k = 0; k < p->value_len; k++)
+		    fprintf (out, "%c", (p->value)[k]);
+		}
+	      break;
+	    case ASN1_ETYPE_GENERALSTRING:
+	    case ASN1_ETYPE_NUMERIC_STRING:
+	    case ASN1_ETYPE_IA5_STRING:
+	    case ASN1_ETYPE_TELETEX_STRING:
+	    case ASN1_ETYPE_PRINTABLE_STRING:
+	    case ASN1_ETYPE_UNIVERSAL_STRING:
+	    case ASN1_ETYPE_UTF8_STRING:
+	    case ASN1_ETYPE_VISIBLE_STRING:
+	      if (p->value)
+		{
+		  len2 = -1;
+		  len = asn1_get_length_der (p->value, p->value_len, &len2);
+		  fprintf (out, "  value:");
+		  if (len > 0)
+		    for (k = 0; k < len; k++)
+		      fprintf (out, "%c", (p->value)[k + len2]);
+		}
+	      break;
+	    case ASN1_ETYPE_BMP_STRING:
+	    case ASN1_ETYPE_OCTET_STRING:
+	      if (p->value)
+		{
+		  len2 = -1;
+		  len = asn1_get_length_der (p->value, p->value_len, &len2);
+		  fprintf (out, "  value:");
+		  if (len > 0)
+		    for (k = 0; k < len; k++)
+		      fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
+		}
+	      break;
+	    case ASN1_ETYPE_OBJECT_ID:
+	      if (p->value)
+		fprintf (out, "  value:%s", p->value);
+	      break;
+	    case ASN1_ETYPE_ANY:
+	      if (p->value)
+		{
+		  len3 = -1;
+		  len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+		  fprintf (out, "  value:");
+		  if (len2 > 0)
+		    for (k = 0; k < len2; k++)
+		      fprintf (out, "%02x", (unsigned) (p->value)[k + len3]);
+		}
+	      break;
+	    case ASN1_ETYPE_SET:
+	    case ASN1_ETYPE_SET_OF:
+	    case ASN1_ETYPE_CHOICE:
+	    case ASN1_ETYPE_DEFINITIONS:
+	    case ASN1_ETYPE_SEQUENCE_OF:
+	    case ASN1_ETYPE_SEQUENCE:
+	    case ASN1_ETYPE_NULL:
+	      break;
+	    default:
+	      break;
+	    }
+	}
+
+      if (mode == ASN1_PRINT_ALL)
+	{
+	  if (p->type & 0x1FFFFF00)
+	    {
+	      fprintf (out, "  attr:");
+	      if (p->type & CONST_UNIVERSAL)
+		fprintf (out, "UNIVERSAL,");
+	      if (p->type & CONST_PRIVATE)
+		fprintf (out, "PRIVATE,");
+	      if (p->type & CONST_APPLICATION)
+		fprintf (out, "APPLICATION,");
+	      if (p->type & CONST_EXPLICIT)
+		fprintf (out, "EXPLICIT,");
+	      if (p->type & CONST_IMPLICIT)
+		fprintf (out, "IMPLICIT,");
+	      if (p->type & CONST_TAG)
+		fprintf (out, "TAG,");
+	      if (p->type & CONST_DEFAULT)
+		fprintf (out, "DEFAULT,");
+	      if (p->type & CONST_TRUE)
+		fprintf (out, "TRUE,");
+	      if (p->type & CONST_FALSE)
+		fprintf (out, "FALSE,");
+	      if (p->type & CONST_LIST)
+		fprintf (out, "LIST,");
+	      if (p->type & CONST_MIN_MAX)
+		fprintf (out, "MIN_MAX,");
+	      if (p->type & CONST_OPTION)
+		fprintf (out, "OPTION,");
+	      if (p->type & CONST_1_PARAM)
+		fprintf (out, "1_PARAM,");
+	      if (p->type & CONST_SIZE)
+		fprintf (out, "SIZE,");
+	      if (p->type & CONST_DEFINED_BY)
+		fprintf (out, "DEF_BY,");
+	      if (p->type & CONST_GENERALIZED)
+		fprintf (out, "GENERALIZED,");
+	      if (p->type & CONST_UTC)
+		fprintf (out, "UTC,");
+	      if (p->type & CONST_SET)
+		fprintf (out, "SET,");
+	      if (p->type & CONST_NOT_USED)
+		fprintf (out, "NOT_USED,");
+	      if (p->type & CONST_ASSIGN)
+		fprintf (out, "ASSIGNMENT,");
+	    }
+	}
+
+      if (mode == ASN1_PRINT_ALL)
+	{
+	  fprintf (out, "\n");
+	}
+      else
+	{
+	  switch (type_field (p->type))
+	    {
+	    case ASN1_ETYPE_CONSTANT:
+	    case ASN1_ETYPE_TAG:
+	    case ASN1_ETYPE_SIZE:
+	      break;
+	    default:
+	      fprintf (out, "\n");
+	    }
+	}
+
+      if (p->down)
+	{
+	  p = p->down;
+	  indent += 2;
+	}
+      else if (p == root)
+	{
+	  p = NULL;
+	  break;
+	}
+      else if (p->right)
+	p = p->right;
+      else
+	{
+	  while (1)
+	    {
+	      p = _asn1_find_up (p);
+	      if (p == root)
+		{
+		  p = NULL;
+		  break;
+		}
+	      indent -= 2;
+	      if (p->right)
+		{
+		  p = p->right;
+		  break;
+		}
+	    }
+	}
+    }
+}
+
+
+
+/**
+ * asn1_number_of_elements:
+ * @element: pointer to the root of an ASN1 structure.
+ * @name: the name of a sub-structure of ROOT.
+ * @num: pointer to an integer where the result will be stored
+ *
+ * Counts the number of elements of a sub-structure called NAME with
+ * names equal to "?1","?2", ...
+ *
+ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
+ *   @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
+ **/
+int
+asn1_number_of_elements (asn1_node_const element, const char *name, int *num)
+{
+  asn1_node_const node, p;
+
+  if (num == NULL)
+    return ASN1_GENERIC_ERROR;
+
+  *num = 0;
+
+  node = asn1_find_node (element, name);
+  if (node == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  p = node->down;
+
+  while (p)
+    {
+      if (p->name[0] == '?')
+	(*num)++;
+      p = p->right;
+    }
+
+  return ASN1_SUCCESS;
+}
+
+
+/**
+ * asn1_find_structure_from_oid:
+ * @definitions: ASN1 definitions
+ * @oidValue: value of the OID to search (e.g. "1.2.3.4").
+ *
+ * Search the structure that is defined just after an OID definition.
+ *
+ * Returns: %NULL when @oidValue not found, otherwise the pointer to a
+ *   constant string that contains the element name defined just after
+ *   the OID.
+ **/
+const char *
+asn1_find_structure_from_oid (asn1_node_const definitions,
+			      const char *oidValue)
+{
+  char name[2 * ASN1_MAX_NAME_SIZE + 2];
+  char value[ASN1_MAX_NAME_SIZE];
+  asn1_node p;
+  int len;
+  int result;
+  const char *definitionsName;
+
+  if ((definitions == NULL) || (oidValue == NULL))
+    return NULL;		/* ASN1_ELEMENT_NOT_FOUND; */
+
+  definitionsName = definitions->name;
+
+  /* search the OBJECT_ID into definitions */
+  p = definitions->down;
+  while (p)
+    {
+      if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
+	  (p->type & CONST_ASSIGN))
+	{
+	  snprintf (name, sizeof (name), "%s.%s", definitionsName, p->name);
+
+	  len = ASN1_MAX_NAME_SIZE;
+	  result = asn1_read_value (definitions, name, value, &len);
+
+	  if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value)))
+	    {
+	      p = p->right;
+	      if (p == NULL)	/* reach the end of ASN1 definitions */
+		return NULL;	/* ASN1_ELEMENT_NOT_FOUND; */
+
+	      return p->name;
+	    }
+	}
+      p = p->right;
+    }
+
+  return NULL;			/* ASN1_ELEMENT_NOT_FOUND; */
+}
+
+/**
+ * asn1_copy_node:
+ * @dst: Destination asn1 node.
+ * @dst_name: Field name in destination node.
+ * @src: Source asn1 node.
+ * @src_name: Field name in source node.
+ *
+ * Create a deep copy of a asn1_node variable. That
+ * function requires @dst to be expanded using asn1_create_element().
+ *
+ * Returns: Return %ASN1_SUCCESS on success.
+ **/
+int
+asn1_copy_node (asn1_node dst, const char *dst_name,
+		asn1_node_const src, const char *src_name)
+{
+  int result;
+  asn1_node dst_node;
+  void *data = NULL;
+  int size = 0;
+
+  result = asn1_der_coding (src, src_name, NULL, &size, NULL);
+  if (result != ASN1_MEM_ERROR)
+    return result;
+
+  data = malloc (size);
+  if (data == NULL)
+    return ASN1_MEM_ERROR;
+
+  result = asn1_der_coding (src, src_name, data, &size, NULL);
+  if (result != ASN1_SUCCESS)
+    {
+      free (data);
+      return result;
+    }
+
+  dst_node = asn1_find_node (dst, dst_name);
+  if (dst_node == NULL)
+    {
+      free (data);
+      return ASN1_ELEMENT_NOT_FOUND;
+    }
+
+  result = asn1_der_decoding (&dst_node, data, size, NULL);
+
+  free (data);
+
+  return result;
+}
+
+/**
+ * asn1_dup_node:
+ * @src: Source asn1 node.
+ * @src_name: Field name in source node.
+ *
+ * Create a deep copy of a asn1_node variable. This function
+ * will return an exact copy of the provided structure.
+ *
+ * Returns: Return %NULL on failure.
+ **/
+asn1_node
+asn1_dup_node (asn1_node_const src, const char *src_name)
+{
+  return _asn1_copy_structure2 (src, src_name);
+}
diff --git a/grub-core/lib/libtasn1/tests/CVE-2018-1000654.c b/grub-core/lib/libtasn1/tests/CVE-2018-1000654.c
new file mode 100644
index 0000000..0c22b70
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/CVE-2018-1000654.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/****************************************************************/
+/* Description: reproducer for CVE-2018-1000654			*/
+/****************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "CVE-2018-1000654-1_asn1_tab.h"
+#include "CVE-2018-1000654-2_asn1_tab.h"
+
+int
+main (int argc, char *argv[])
+{
+  int result, verbose = 0;
+  asn1_node definitions = NULL;
+  char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+
+  if (argc > 1)
+    verbose = 1;
+
+  printf ("Test 1\n");
+
+  result =
+    asn1_array2tree (CVE_2018_1000654_1_asn1_tab, &definitions,
+		     errorDescription);
+  if (result != ASN1_RECURSION)
+    {
+      asn1_perror (result);
+      printf ("ErrorDescription = %s\n\n", errorDescription);
+      exit (1);
+    }
+
+  asn1_delete_structure (&definitions);
+
+  printf ("Test 2\n");
+
+  result =
+    asn1_array2tree (CVE_2018_1000654_2_asn1_tab, &definitions,
+		     errorDescription);
+  if (result != ASN1_RECURSION)
+    {
+      asn1_perror (result);
+      printf ("ErrorDescription = %s\n\n", errorDescription);
+      exit (1);
+    }
+
+  asn1_delete_structure (&definitions);
+
+  if (verbose)
+    printf ("Success\n");
+  exit (0);
+}
diff --git a/grub-core/lib/libtasn1/tests/Test_overflow.c b/grub-core/lib/libtasn1/tests/Test_overflow.c
new file mode 100644
index 0000000..c61dea4
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/Test_overflow.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* Written by Simon Josefsson */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "libtasn1.h"
+
+int
+main (int argc, char **argv)
+{
+  /* Test that values larger than long are rejected.  This has worked
+     fine with all versions of libtasn1. */
+  int verbose = 0;
+
+  if (argc > 1)
+    verbose = 1;
+
+  {
+    unsigned char der[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
+    long l;
+    int len;
+
+    l = asn1_get_length_der (der, sizeof der, &len);
+
+    if (l == -2L)
+      {
+	if (verbose)
+	  puts ("OK: asn1_get_length_der bignum");
+      }
+    else
+      {
+	printf ("ERROR: asn1_get_length_der bignum (l %ld len %d)\n", l, len);
+	return 1;
+      }
+  }
+
+  /* Test that values larger than int but smaller than long are
+     rejected.  This limitation was introduced with libtasn1 2.12. */
+  if (LONG_MAX > INT_MAX)
+    {
+      unsigned long num = ((long) UINT_MAX) << 2;
+      unsigned char der[20];
+      int der_len;
+      long l;
+      int len;
+
+      asn1_length_der (num, der, &der_len);
+
+      l = asn1_get_length_der (der, der_len, &len);
+
+      if (l == -2L)
+	{
+	  if (verbose)
+	    puts ("OK: asn1_get_length_der intnum");
+	}
+      else
+	{
+	  printf ("ERROR: asn1_get_length_der intnum (l %ld len %d)\n", l,
+		  len);
+	  return 1;
+	}
+    }
+
+  /* Test that values larger than would fit in the input string are
+     rejected.  This problem was fixed in libtasn1 2.12. */
+  {
+    unsigned long num = 64;
+    unsigned char der[20];
+    int der_len;
+    long l;
+    int len;
+
+    asn1_length_der (num, der, &der_len);
+
+    der_len = sizeof (der);
+    l = asn1_get_length_der (der, der_len, &len);
+
+    if (l == -4L)
+      {
+	if (verbose)
+	  puts ("OK: asn1_get_length_der overflow-small");
+      }
+    else
+      {
+	printf ("ERROR: asn1_get_length_der overflow-small (l %ld len %d)\n",
+		l, len);
+	return 1;
+      }
+  }
+
+  /* Test that values larger than would fit in the input string are
+     rejected.  This problem was fixed in libtasn1 2.12. */
+  {
+    unsigned long num = 1073741824;
+    unsigned char der[20];
+    int der_len;
+    long l;
+    int len;
+
+    asn1_length_der (num, der, &der_len);
+
+    der_len = sizeof (der);
+    l = asn1_get_length_der (der, der_len, &len);
+
+    if (l == -4L)
+      {
+	if (verbose)
+	  puts ("OK: asn1_get_length_der overflow-large1");
+      }
+    else
+      {
+	printf ("ERROR: asn1_get_length_der overflow-large1 (l %ld len %d)\n",
+		l, len);
+	return 1;
+      }
+  }
+
+  /* Test that values larger than would fit in the input string are
+     rejected.  This problem was fixed in libtasn1 2.12. */
+  {
+    unsigned long num = 2147483649;
+    unsigned char der[20];
+    int der_len;
+    long l;
+    int len;
+
+    asn1_length_der (num, der, &der_len);
+
+    der_len = sizeof (der);
+    l = asn1_get_length_der (der, der_len, &len);
+
+    if (l == -2L)
+      {
+	if (verbose)
+	  puts ("OK: asn1_get_length_der overflow-large2");
+      }
+    else
+      {
+	printf ("ERROR: asn1_get_length_der overflow-large2 (l %ld len %d)\n",
+		l, len);
+	return 1;
+      }
+  }
+
+  return 0;
+}
diff --git a/grub-core/lib/libtasn1/tests/Test_simple.c b/grub-core/lib/libtasn1/tests/Test_simple.c
new file mode 100644
index 0000000..6cd07e0
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/Test_simple.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2011-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by Simon Josefsson
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "libtasn1.h"
+
+struct tv
+{
+  int bitlen;
+  const char *bitstr;
+  int derlen;
+  const char *der;
+};
+
+static const struct tv tv[] = {
+  {0, "", 2, "\x01\x00"},
+  {1, "\x00", 3, "\x02\x07\x00"},
+  {2, "\x00", 3, "\x02\x06\x00"},
+  {3, "\x00", 3, "\x02\x05\x00"},
+  {4, "\x00", 3, "\x02\x04\x00"},
+  {5, "\x00", 3, "\x02\x03\x00"},
+  {6, "\x00", 3, "\x02\x02\x00"},
+  {7, "\x00", 3, "\x02\x01\x00"},
+  {8, "\x00\x00", 3, "\x02\x00\x00"},
+  {9, "\x00\x00", 4, "\x03\x07\x00\x00"},
+  {10, "\x00\x00", 4, "\x03\x06\x00\x00"},
+  {11, "\x00\x00", 4, "\x03\x05\x00\x00"},
+  {12, "\x00\x00", 4, "\x03\x04\x00\x00"},
+  {13, "\x00\x00", 4, "\x03\x03\x00\x00"},
+  {14, "\x00\x00", 4, "\x03\x02\x00\x00"},
+  {15, "\x00\x00", 4, "\x03\x01\x00\x00"},
+  {16, "\x00\x00", 4, "\x03\x00\x00\x00"},
+  {17, "\x00\x00\x00", 5, "\x04\x07\x00\x00\x00"},
+  {18, "\x00\x00\x00", 5, "\x04\x06\x00\x00\x00"},
+  {19, "\x00\x00\x00", 5, "\x04\x05\x00\x00\x00"},
+  {1, "\xFF", 3, "\x02\x07\x80"},
+  {2, "\xFF", 3, "\x02\x06\xc0"},
+  {3, "\xFF", 3, "\x02\x05\xe0"},
+  {4, "\xFF", 3, "\x02\x04\xf0"},
+  {5, "\xFF", 3, "\x02\x03\xf8"},
+  {6, "\xFF", 3, "\x02\x02\xfc"},
+  {7, "\xFF", 3, "\x02\x01\xfe"},
+  {8, "\xFF\xFF", 3, "\x02\x00\xff"},
+  {9, "\xFF\xFF", 4, "\x03\x07\xff\x80"},
+  {10, "\xFF\xFF", 4, "\x03\x06\xff\xc0"},
+  {11, "\xFF\xFF", 4, "\x03\x05\xff\xe0"},
+  {12, "\xFF\xFF", 4, "\x03\x04\xff\xf0"},
+  {13, "\xFF\xFF", 4, "\x03\x03\xff\xf8"},
+  {14, "\xFF\xFF", 4, "\x03\x02\xff\xfc"},
+  {15, "\xFF\xFF", 4, "\x03\x01\xff\xfe"},
+  {16, "\xFF\xFF", 4, "\x03\x00\xff\xff"},
+  {17, "\xFF\xFF\xFF", 5, "\x04\x07\xff\xff\x80"},
+  {18, "\xFF\xFF\xFF", 5, "\x04\x06\xff\xff\xc0"},
+  {19, "\xFF\xFF\xFF", 5, "\x04\x05\xff\xff\xe0"},
+};
+
+int
+main (int argc, char *argv[])
+{
+  int result;
+  unsigned char der[100];
+  unsigned char str[100];
+  int der_len = sizeof (der);
+  int str_size = sizeof (str);
+  int ret_len, bit_len;
+  size_t i;
+
+  {
+    unsigned int etype = 38;
+    unsigned int my_str_len = 10;
+    unsigned char my_str[10];
+    unsigned int tl_len = 10;
+    unsigned char tl[10];
+
+    /* https://gitlab.com/gnutls/libtasn1/-/issues/32 */
+    result = asn1_encode_simple_der (etype, my_str, my_str_len, tl, &tl_len);
+    if (result != ASN1_VALUE_NOT_VALID)
+      {
+	fprintf (stderr, "asn1_encode_simple_der out of range etype\n");
+	return 1;
+      }
+  }
+
+  /* Dummy test */
+
+  asn1_bit_der (NULL, 0, der, &der_len);
+  result = asn1_get_bit_der (der, 0, &ret_len, str, str_size, &bit_len);
+  if (result != ASN1_GENERIC_ERROR)
+    {
+      fprintf (stderr, "asn1_get_bit_der zero\n");
+      return 1;
+    }
+
+  /* Encode short strings with increasing bit lengths */
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      /* Encode */
+
+      asn1_bit_der ((const unsigned char *) tv[i].bitstr, tv[i].bitlen,
+		    der, &der_len);
+
+#if 0
+      {
+	size_t j;
+	for (j = 0; j < der_len; j++)
+	  printf ("\\x%02x", der[j]);
+	printf ("\n");
+      }
+#endif
+
+      if (der_len != tv[i].derlen || memcmp (der, tv[i].der, der_len) != 0)
+	{
+	  fprintf (stderr, "asn1_bit_der iter %lu\n", (unsigned long) i);
+	  return 1;
+	}
+
+      /* Decode it */
+
+      result = asn1_get_bit_der (der, der_len, &ret_len, str,
+				 str_size, &bit_len);
+      if (result != ASN1_SUCCESS || ret_len != tv[i].derlen
+	  || bit_len != tv[i].bitlen)
+	{
+	  fprintf (stderr, "asn1_get_bit_der iter %lu, err: %d\n",
+		   (unsigned long) i, result);
+	  return 1;
+	}
+    }
+
+
+  /* Decode sample from "A Layman's Guide to a Subset of ASN.1, BER,
+     and DER" section 5.4 "BIT STRING": "The BER encoding of the BIT
+     STRING value "011011100101110111" can be any of the following,
+     among others, depending on the choice of padding bits, the form
+     of length octets [...]".
+   */
+
+  /* 03 04 06 6e 5d c0  DER encoding */
+
+  memcpy (der, "\x04\x06\x6e\x5d\xc0", 5);
+  der_len = 5;
+
+  result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len);
+  if (result != ASN1_SUCCESS || ret_len != 5
+      || bit_len != 18 || memcmp (str, "\x6e\x5d\xc0", 3) != 0)
+    {
+      fprintf (stderr, "asn1_get_bit_der example\n");
+      return 1;
+    }
+
+  der_len = sizeof (der);
+  asn1_bit_der (str, bit_len, der, &der_len);
+  if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+    {
+      fprintf (stderr, "asn1_bit_der example roundtrip\n");
+      return 1;
+    }
+
+  /* 03 04 06 6e 5d e0 padded with "100000" */
+
+  memcpy (der, "\x04\x06\x6e\x5d\xe0", 5);
+  der_len = 5;
+
+  result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len);
+  if (result != ASN1_SUCCESS || ret_len != 5
+      || bit_len != 18 || memcmp (str, "\x6e\x5d\xe0", 3) != 0)
+    {
+      fprintf (stderr, "asn1_get_bit_der example padded\n");
+      return 1;
+    }
+
+  der_len = sizeof (der);
+  asn1_bit_der (str, bit_len, der, &der_len);
+  if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+    {
+      fprintf (stderr, "asn1_bit_der example roundtrip\n");
+      return 1;
+    }
+
+  /* 03 81 04 06 6e 5d c0 long form of length octets */
+
+  memcpy (der, "\x81\x04\x06\x6e\x5d\xc0", 6);
+  der_len = 6;
+
+  result = asn1_get_bit_der (der, der_len, &ret_len, str, str_size, &bit_len);
+
+  if (result != ASN1_SUCCESS || ret_len != 6
+      || bit_len != 18 || memcmp (str, "\x6e\x5d\xc0", 3) != 0)
+    {
+      fprintf (stderr, "asn1_get_bit_der example long form\n");
+      return 1;
+    }
+
+  der_len = sizeof (der);
+  asn1_bit_der (str, bit_len, der, &der_len);
+  if (der_len != 5 || memcmp (der, "\x04\x06\x6e\x5d\xc0", 5) != 0)
+    {
+      fprintf (stderr, "asn1_bit_der example roundtrip\n");
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/grub-core/lib/libtasn1/tests/Test_strings.c b/grub-core/lib/libtasn1/tests/Test_strings.c
new file mode 100644
index 0000000..27f7215
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/Test_strings.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by Simon Josefsson
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "libtasn1.h"
+
+struct tv
+{
+  unsigned int etype;
+  unsigned int str_len;
+  const void *str;
+  unsigned int der_len;
+  const void *der;
+};
+
+static const struct tv tv[] = {
+  {ASN1_ETYPE_IA5_STRING, 20,
+   "\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72",
+   22,
+   "\x16\x14\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72"},
+  {ASN1_ETYPE_PRINTABLE_STRING, 5, "\x4e\x69\x6b\x6f\x73",
+   7, "\x13\x05\x4e\x69\x6b\x6f\x73"},
+  {ASN1_ETYPE_UTF8_STRING, 12, "Αττική",
+   14, "\x0c\x0c\xce\x91\xcf\x84\xcf\x84\xce\xb9\xce\xba\xce\xae"},
+  {ASN1_ETYPE_TELETEX_STRING, 15,
+   "\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e",
+   17,
+   "\x14\x0f\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e"},
+  {ASN1_ETYPE_OCTET_STRING, 36,
+   "\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A",
+   38,
+   "\x04\x24\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A"}
+};
+
+#define SSTR(x) sizeof(x)-1,x
+static const struct tv ber[] = {
+  {ASN1_ETYPE_OCTET_STRING,
+   SSTR ("\xa0\xa0"),
+   SSTR ("\x24\x80\x04\x82\x00\x02\xa0\xa0\x00\x00")},
+  {ASN1_ETYPE_OCTET_STRING,
+   SSTR ("\xa0\xa0\xb0\xb0\xb0"),
+   SSTR
+   ("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x00\x00")},
+  {ASN1_ETYPE_OCTET_STRING,
+   SSTR ("\xa0\xa0\xb0\xb0\xb0\xa1\xa1"),
+   SSTR
+   ("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x24\x80\x04\x82\x00\x02\xa1\xa1\x00\x00\x00\x00")},
+  {ASN1_ETYPE_OCTET_STRING,
+   SSTR ("\xa0\xa0\xb0\xb0\xb0\xa1\xa1\xc1"),
+   SSTR
+   ("\x24\x80\x04\x82\x00\x02\xa0\xa0\x04\x82\x00\x03\xb0\xb0\xb0\x24\x80\x04\x82\x00\x02\xa1\xa1\x04\x82\x00\x01\xc1\x00\x00\x00\x00")},
+};
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+  unsigned char tl[ASN1_MAX_TL_SIZE];
+  unsigned int tl_len, der_len, str_len;
+  const unsigned char *str;
+  unsigned char *b;
+  unsigned int i;
+
+  /* Dummy test */
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      /* Encode */
+      tl_len = sizeof (tl);
+      ret = asn1_encode_simple_der (tv[i].etype, tv[i].str, tv[i].str_len,
+				    tl, &tl_len);
+      if (ret != ASN1_SUCCESS)
+	{
+	  fprintf (stderr, "Encoding error in %u: %s\n", i,
+		   asn1_strerror (ret));
+	  return 1;
+	}
+      der_len = tl_len + tv[i].str_len;
+
+      if (der_len != tv[i].der_len || memcmp (tl, tv[i].der, tl_len) != 0)
+	{
+	  fprintf (stderr,
+		   "DER encoding differs in %u! (size: %u, expected: %u)\n",
+		   i, der_len, tv[i].der_len);
+	  return 1;
+	}
+
+      /* decoding */
+      ret =
+	asn1_decode_simple_der (tv[i].etype, tv[i].der, tv[i].der_len, &str,
+				&str_len);
+      if (ret != ASN1_SUCCESS)
+	{
+	  fprintf (stderr, "Decoding error in %u: %s\n", i,
+		   asn1_strerror (ret));
+	  return 1;
+	}
+
+      if (str_len != tv[i].str_len || memcmp (str, tv[i].str, str_len) != 0)
+	{
+	  fprintf (stderr,
+		   "DER decoded data differ in %u! (size: %u, expected: %u)\n",
+		   i, der_len, tv[i].str_len);
+	  return 1;
+	}
+    }
+
+  /* BER decoding */
+  for (i = 0; i < sizeof (ber) / sizeof (ber[0]); i++)
+    {
+      /* decoding */
+      ret =
+	asn1_decode_simple_ber (ber[i].etype, ber[i].der, ber[i].der_len, &b,
+				&str_len, NULL);
+      if (ret != ASN1_SUCCESS)
+	{
+	  fprintf (stderr, "BER decoding error in %u: %s\n", i,
+		   asn1_strerror (ret));
+	  return 1;
+	}
+
+      if (str_len != ber[i].str_len || memcmp (b, ber[i].str, str_len) != 0)
+	{
+	  fprintf (stderr,
+		   "BER decoded data differ in %u! (size: %u, expected: %u)\n",
+		   i, str_len, ber[i].str_len);
+	  return 1;
+	}
+      free (b);
+    }
+
+
+  return 0;
+}
diff --git a/grub-core/lib/libtasn1/tests/object-id-decoding.c b/grub-core/lib/libtasn1/tests/object-id-decoding.c
new file mode 100644
index 0000000..06a6c52
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/object-id-decoding.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "libtasn1.h"
+
+struct tv
+{
+  int der_len;
+  const unsigned char *der;
+  const char *oid;
+  int expected_error;
+};
+
+static const struct tv tv[] = {
+  {.der_len = 5,
+   .der = (void *) "\x06\x03\x80\x37\x03",
+   .oid = "2.999.3",
+   .expected_error = ASN1_DER_ERROR	/* leading 0x80 */
+   },
+  {.der_len = 12,
+   .der = (void *) "\x06\x0a\x2b\x06\x01\x80\x01\x92\x08\x09\x05\x01",
+   .oid = "1.3.6.1.4.1.2312.9.5.1",
+   .expected_error = ASN1_DER_ERROR	/* leading 0x80 */
+   },
+  {.der_len = 6,
+   .der = (void *) "\x06\x04\x01\x02\x03\x04",
+   .oid = "0.1.2.3.4",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 5,
+   .der = (void *) "\x06\x03\x51\x02\x03",
+   .oid = "2.1.2.3",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 5,
+   .der = (void *) "\x06\x03\x88\x37\x03",
+   .oid = "2.999.3",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 12,
+   .der = (void *) "\x06\x0a\x2b\x06\x01\x04\x01\x92\x08\x09\x05\x01",
+   .oid = "1.3.6.1.4.1.2312.9.5.1",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 19,
+   .der =
+   (void *)
+   "\x06\x11\xfa\x80\x00\x00\x00\x0e\x01\x0e\xfa\x80\x00\x00\x00\x0e\x63\x6f\x6d",
+   .oid = "2.1998768.0.0.14.1.14.1998848.0.0.14.99.111.109",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 19,
+   .der =
+   (void *)
+   "\x06\x11\x2b\x06\x01\x04\x01\x92\x08\x09\x02\xaa\xda\xbe\xbe\xfa\x72\x01\x07",
+   .oid = "1.3.6.1.4.1.2312.9.2.1467399257458.1.7",
+   .expected_error = ASN1_SUCCESS},
+};
+
+int
+main (int argc, char *argv[])
+{
+  char str[128];
+  int ret, ret_len;
+  size_t i;
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      /* decode */
+      ret =
+	asn1_get_object_id_der (tv[i].der + 1,
+				tv[i].der_len - 1, &ret_len, str,
+				sizeof (str));
+      if (ret != tv[i].expected_error)
+	{
+	  fprintf (stderr,
+		   "%d: asn1_get_object_id_der iter %lu: got '%s' expected %d\n",
+		   __LINE__, (unsigned long) i, asn1_strerror (ret),
+		   tv[i].expected_error);
+	  return 1;
+	}
+
+      if (tv[i].expected_error != ASN1_SUCCESS)
+	continue;
+
+      if (ret_len != tv[i].der_len - 1)
+	{
+	  fprintf (stderr,
+		   "%d: iter %lu: error in DER, length returned is %d, had %d\n",
+		   __LINE__, (unsigned long) i, ret_len, tv[i].der_len - 1);
+	  return 1;
+	}
+
+      if (strcmp (tv[i].oid, str) != 0)
+	{
+	  fprintf (stderr,
+		   "%d: strcmp iter %lu: got invalid OID: %s, expected: %s\n",
+		   __LINE__, (unsigned long) i, str, tv[i].oid);
+	  return 1;
+	}
+
+    }
+
+  return 0;
+}
diff --git a/grub-core/lib/libtasn1/tests/object-id-encoding.c b/grub-core/lib/libtasn1/tests/object-id-encoding.c
new file mode 100644
index 0000000..1a33969
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/object-id-encoding.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 Nikos Mavrogiannopoulos
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "libtasn1.h"
+
+struct tv
+{
+  int der_len;
+  const unsigned char *der;
+  const char *oid;
+  int expected_error;
+};
+
+static const struct tv tv[] = {
+  {.der_len = 0,
+   .der = (void *) "",
+   .oid = "5.999.3",
+   .expected_error = ASN1_VALUE_NOT_VALID	/* cannot start with 5 */
+   },
+  {.der_len = 0,
+   .der = (void *) "",
+   .oid = "0.48.9",
+   .expected_error = ASN1_VALUE_NOT_VALID	/* second field cannot be 48 */
+   },
+  {.der_len = 0,
+   .der = (void *) "",
+   .oid = "1.40.9",
+   .expected_error = ASN1_VALUE_NOT_VALID	/* second field cannot be 40 */
+   },
+  {.der_len = 4,
+   .der = (void *) "\x06\x02\x4f\x63",
+   .oid = "1.39.99",
+   .expected_error = ASN1_SUCCESS,
+   },
+  {.der_len = 6,
+   .der = (void *) "\x06\x04\x01\x02\x03\x04",
+   .oid = "0.1.2.3.4",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 5,
+   .der = (void *) "\x06\x03\x51\x02\x03",
+   .oid = "2.1.2.3",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 5,
+   .der = (void *) "\x06\x03\x88\x37\x03",
+   .oid = "2.999.3",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 12,
+   .der = (void *) "\x06\x0a\x2b\x06\x01\x04\x01\x92\x08\x09\x05\x01",
+   .oid = "1.3.6.1.4.1.2312.9.5.1",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 19,
+   .der =
+   (void *)
+   "\x06\x11\xfa\x80\x00\x00\x00\x0e\x01\x0e\xfa\x80\x00\x00\x00\x0e\x63\x6f\x6d",
+   .oid = "2.1998768.0.0.14.1.14.1998848.0.0.14.99.111.109",
+   .expected_error = ASN1_SUCCESS},
+  {.der_len = 19,
+   .der =
+   (void *)
+   "\x06\x11\x2b\x06\x01\x04\x01\x92\x08\x09\x02\xaa\xda\xbe\xbe\xfa\x72\x01\x07",
+   .oid = "1.3.6.1.4.1.2312.9.2.1467399257458.1.7",
+   .expected_error = ASN1_SUCCESS},
+};
+
+int
+main (int argc, char *argv[])
+{
+  unsigned char der[128];
+  int ret, der_len, i, j;
+
+  for (i = 0; i < (int) (sizeof (tv) / sizeof (tv[0])); i++)
+    {
+      der_len = sizeof (der);
+      ret = asn1_object_id_der (tv[i].oid, der, &der_len, 0);
+      if (ret != ASN1_SUCCESS)
+	{
+	  if (ret == tv[i].expected_error)
+	    continue;
+	  fprintf (stderr,
+		   "%d: iter %lu, encoding of OID failed: %s\n",
+		   __LINE__, (unsigned long) i, asn1_strerror (ret));
+	  return 1;
+	}
+      else if (ret != tv[i].expected_error)
+	{
+	  fprintf (stderr,
+		   "%d: iter %lu, encoding of OID %s succeeded when expecting failure\n",
+		   __LINE__, (unsigned long) i, tv[i].oid);
+	  return 1;
+	}
+
+      if (der_len != tv[i].der_len || memcmp (der, tv[i].der, der_len) != 0)
+	{
+	  fprintf (stderr,
+		   "%d: iter %lu, re-encoding of OID %s resulted to different string (%d vs %d bytes)\n",
+		   __LINE__, (unsigned long) i, tv[i].oid, der_len,
+		   tv[i].der_len);
+	  fprintf (stderr, "\nGot:\t\t");
+	  for (j = 0; j < der_len; j++)
+	    fprintf (stderr, "%.2x", der[j]);
+
+	  fprintf (stderr, "\nExpected:\t");
+	  for (j = 0; j < tv[i].der_len; j++)
+	    fprintf (stderr, "%.2x", tv[i].der[j]);
+	  fprintf (stderr, "\n");
+
+	  return 1;
+	}
+    }
+
+  return 0;
+}
diff --git a/grub-core/lib/libtasn1/tests/octet-string.c b/grub-core/lib/libtasn1/tests/octet-string.c
new file mode 100644
index 0000000..69eb18a
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/octet-string.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2011-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by Simon Josefsson and Nikos Mavrogiannopoulos
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "libtasn1.h"
+
+struct tv
+{
+  const char *name;
+  int der_len;
+  const unsigned char *der_str;
+  int len;
+  const unsigned char *string;
+  int expected_error;
+  int ber;
+};
+
+static const struct tv tv[] = {
+  {.name = "primitive octet strings",
+   .der_len = 10,
+   .der_str = (void *) "\x04\x08\x01\x23\x45\x67\x89\xab\xcd\xef",
+   .len = 8,
+   .string = (void *) "\x01\x23\x45\x67\x89\xab\xcd\xef",
+   .ber = 0},
+  {.der_len = 22,
+   .der_str =
+   (void *)
+   "\x04\x14\x13\x00\xd9\xa8\x47\xf7\xf2\x1c\xf4\xb0\xec\x5f\xc1\x73\xe5\x1b\x25\xc2\x62\x27",
+   .len = 20,
+   .string =
+   (void *)
+   "\x13\x00\xD9\xA8\x47\xF7\xF2\x1C\xF4\xB0\xEC\x5F\xC1\x73\xE5\x1B\x25\xC2\x62\x27"},
+
+  {.name = "long type of length",
+   .der_len = 23,
+   .der_str =
+   (void *)
+   "\x04\x81\x14\x13\x00\xd9\xa8\x47\xf7\xf2\x1c\xf4\xb0\xec\x5f\xc1\x73\xe5\x1b\x25\xc2\x62\x27",
+   .len = 20,
+   .string =
+   (void *)
+   "\x13\x00\xD9\xA8\x47\xF7\xF2\x1C\xF4\xB0\xEC\x5F\xC1\x73\xE5\x1B\x25\xC2\x62\x27",
+   .ber = 1},
+  {.der_len = 11,
+   .der_str = (void *) "\x04\x81\x08\x01\x23\x45\x67\x89\xab\xcd\xef",
+   .len = 8,
+   .string = (void *) "\x01\x23\x45\x67\x89\xab\xcd\xef",
+   .ber = 1},
+
+  {.name = "constructed - indefinite",
+   .der_len = 11,
+   .der_str = (void *) "\x24\x80\x04\x05\x01\x02\x03\x04\x05\x00\x00",
+   .len = 5,
+   .string = (void *) "\x01\x02\x03\x04\x05",
+   .ber = 1,
+   },
+
+  {.name = "constructed - definite - concat",
+   .der_len = 12,
+   .der_str = (void *) "\x24\x0a\x04\x04\x0a\x0b\x0c\x0d\x04\x02\x0e\x0f",
+   .len = 6,
+   .string = (void *) "\x0a\x0b\x0c\x0d\x0e\x0f",
+   .ber = 1,
+   },
+  {.name = "constructed - definite - recursive",
+   .der_len = 15,
+   .der_str =
+   (void *) "\x24\x0d\x04\x04\x0a\x0b\x0c\x0d\x24\x05\x04\x00\x04\x01\x0f",
+   .len = 5,
+   .string = (void *) "\x0a\x0b\x0c\x0d\x0f",
+   .ber = 1,
+   },
+  {.name = "constructed - definite - single",
+   .der_len = 7,
+   .der_str = (void *) "\x24\x05\x04\x03\x01\x02\x03",
+   .len = 3,
+   .string = (void *) "\x01\x02\x03",
+   .ber = 1,
+   },
+
+  /* a large amount of recursive indefinite encoding */
+  {.name = "a large amount of recursive indefinite encoding",
+   .der_len = 29325,
+   .der_str =
+   (void *)
+   "\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80\x24\x80",
+   .len = 0,
+   .ber = 1,
+   .expected_error = ASN1_DER_ERROR}
+};
+
+int
+main (int argc, char *argv[])
+{
+  unsigned char str[100];
+  unsigned char der[100];
+  int der_len = sizeof (der);
+  int str_size = sizeof (str);
+  unsigned char *tmp = NULL;
+  int ret, ret_len, j;
+  size_t i;
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      /* Decode */
+
+      if (tv[i].ber == 0)
+	{
+	  str_size = sizeof (str);
+	  ret =
+	    asn1_get_octet_der (tv[i].der_str + 1,
+				tv[i].der_len - 1, &ret_len, str,
+				sizeof (str), &str_size);
+	  if (ret != tv[i].expected_error)
+	    {
+	      fprintf (stderr,
+		       "%d: asn1_get_octet_der: %s: got %d expected %d\n",
+		       __LINE__, tv[i].name, ret, tv[i].expected_error);
+	      return 1;
+	    }
+	  if (tv[i].expected_error)
+	    continue;
+
+	  if (ret_len != tv[i].der_len - 1)
+	    {
+	      fprintf (stderr,
+		       "%d: error in DER, length returned is %d, had %d\n",
+		       __LINE__, ret_len, tv[i].der_len - 1);
+	      return 1;
+	    }
+
+	  if (str_size != tv[i].len
+	      || memcmp (tv[i].string, str, tv[i].len) != 0)
+	    {
+	      fprintf (stderr,
+		       "%d: memcmp: %s: got invalid decoding\n",
+		       __LINE__, tv[i].name);
+
+	      fprintf (stderr, "\nGot:\t\t");
+	      for (j = 0; j < str_size; j++)
+		fprintf (stderr, "%.2x", str[j]);
+
+	      fprintf (stderr, "\nExpected:\t");
+	      for (j = 0; j < tv[i].len; j++)
+		fprintf (stderr, "%.2x", tv[i].string[j]);
+	      fprintf (stderr, "\n");
+	      return 1;
+	    }
+
+	  /* Encode */
+	  der_len = sizeof (der);
+	  asn1_octet_der (str, str_size, der, &der_len);
+
+	  if (der_len != tv[i].der_len - 1
+	      || memcmp (tv[i].der_str + 1, der, tv[i].der_len - 1) != 0)
+	    {
+	      fprintf (stderr,
+		       "encoding: %s: got invalid encoding\n", tv[i].name);
+	      return 1;
+	    }
+	}
+
+      ret =
+	asn1_decode_simple_ber (ASN1_ETYPE_OCTET_STRING,
+				tv[i].der_str, tv[i].der_len,
+				&tmp, (unsigned int *) &str_size,
+				(unsigned int *) &der_len);
+      if (ret != tv[i].expected_error)
+	{
+	  fprintf (stderr,
+		   "%d: asn1_decode_simple_ber: %s: got %s expected %s\n",
+		   __LINE__, tv[i].name, asn1_strerror (ret),
+		   asn1_strerror (tv[i].expected_error));
+	  return 1;
+	}
+      if (tv[i].expected_error)
+	continue;
+
+      if (der_len != tv[i].der_len)
+	{
+	  fprintf (stderr,
+		   "%d: error: %s: DER, length returned is %d, had %d\n",
+		   __LINE__, tv[i].name, der_len, tv[i].der_len);
+	  return 1;
+	}
+
+      if (str_size != tv[i].len || memcmp (tv[i].string, tmp, tv[i].len) != 0)
+	{
+	  fprintf (stderr,
+		   "%d: memcmp: %s: got invalid decoding\n",
+		   __LINE__, tv[i].name);
+	  fprintf (stderr, "\nGot:\t\t");
+	  for (j = 0; j < str_size; j++)
+	    fprintf (stderr, "%.2x", tmp[j]);
+
+	  fprintf (stderr, "\nExpected:\t");
+	  for (j = 0; j < tv[i].len; j++)
+	    fprintf (stderr, "%.2x", tv[i].string[j]);
+	  fprintf (stderr, "\n");
+	  return 1;
+	}
+      free (tmp);
+      tmp = NULL;
+
+    }
+
+  return 0;
+}
diff --git a/grub-core/lib/libtasn1/tests/reproducers.c b/grub-core/lib/libtasn1/tests/reproducers.c
new file mode 100644
index 0000000..a09d8b0
--- /dev/null
+++ b/grub-core/lib/libtasn1/tests/reproducers.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ *
+ * This file is part of LIBTASN1.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/****************************************************************/
+/* Description: run reproducers for several fixed issues        */
+/****************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <libtasn1.h>
+
+#include <int.h>
+
+/* produces endless loop (fixed by d4b624b2):
+ * The following translates into a single node with all pointers
+ * (right,left,down) set to NULL. */
+const asn1_static_node endless_asn1_tab[] = {
+  {"TEST_TREE", 536875024, NULL},
+  {NULL, 0, NULL}
+};
+
+/* produces memory leak (fixed by f16d1ff9):
+ * 152 bytes in 1 blocks are definitely lost in loss record 1 of 1
+ *    at 0x4837B65: calloc (vg_replace_malloc.c:762)
+ *    by 0x4851C0D: _asn1_add_static_node (parser_aux.c:71)
+ *    by 0x4853AAC: asn1_array2tree (structure.c:200)
+ *    by 0x10923B: main (single_node.c:67)
+ */
+const asn1_static_node tab[] = {
+  {"a", CONST_DOWN, ""},
+  {"b", 0, ""},
+  {"c", 0, ""},
+  {NULL, 0, NULL}
+};
+
+int
+main (int argc, char *argv[])
+{
+  int result, verbose = 0;
+  asn1_node definitions = NULL;
+  char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+
+  if (argc > 1)
+    verbose = 1;
+
+  result = asn1_array2tree (endless_asn1_tab, &definitions, errorDescription);
+  if (result != ASN1_SUCCESS)
+    {
+      asn1_perror (result);
+      printf ("ErrorDescription = %s\n\n", errorDescription);
+      exit (EXIT_FAILURE);
+    }
+
+  asn1_delete_structure (&definitions);
+
+  definitions = NULL;
+  result = asn1_array2tree (tab, &definitions, errorDescription);
+  if (result != ASN1_SUCCESS)
+    {
+      asn1_perror (result);
+      printf ("ErrorDescription = %s\n\n", errorDescription);
+      exit (EXIT_FAILURE);
+    }
+
+  asn1_delete_structure (&definitions);
+
+  if (verbose)
+    printf ("Success\n");
+
+  exit (EXIT_SUCCESS);
+}
diff --git a/util/import_gcrypt_inth.sed b/util/import_gcrypt_inth.sed
new file mode 100644
index 0000000..ebe9371
--- /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
