grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v8 02/22] libtasn1: import libtasn1-4.19.0


From: Vladimir 'phcoder' Serbinenko
Subject: Re: [PATCH v8 02/22] libtasn1: import libtasn1-4.19.0
Date: Wed, 17 Jan 2024 04:47:56 +0300

LGTM
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>

On Tue, Jan 16, 2024 at 12:22 PM Gary Lin via Grub-devel
<grub-devel@gnu.org> wrote:
>
> From: Daniel Axtens <dja@axtens.net>
>
> Import a very trimmed-down set of libtasn1 files:
>
> pushd /tmp
> wget https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.19.0.tar.gz
> tar -xf libtasn1-4.19.0.tar.gz
> popd
> pushd grub-core/lib
> rm -rf libtasn1
> mkdir libtasn1
> cp /tmp/libtasn1-4.19.0/{README.md,COPYING} libtasn1/
> mkdir libtasn1/lib
> cp 
> /tmp/libtasn1-4.19.0/lib/{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h}
>  libtasn1/lib
> cp /tmp/libtasn1-4.19.0/lib/includes/libtasn1.h ../../include/grub/
> git add libtasn1/ ../../include/grub/libtasn1.h
> popd
>
> Signed-off-by: Daniel Axtens <dja@axtens.net>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  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/element.h    |   42 +
>  grub-core/lib/libtasn1/lib/errors.c     |  100 +
>  grub-core/lib/libtasn1/lib/gstr.c       |   74 +
>  grub-core/lib/libtasn1/lib/gstr.h       |   50 +
>  grub-core/lib/libtasn1/lib/int.h        |  221 ++
>  grub-core/lib/libtasn1/lib/parser_aux.c | 1178 +++++++++++
>  grub-core/lib/libtasn1/lib/parser_aux.h |  172 ++
>  grub-core/lib/libtasn1/lib/structure.c  | 1225 +++++++++++
>  grub-core/lib/libtasn1/lib/structure.h  |   46 +
>  include/grub/libtasn1.h                 |  643 ++++++
>  15 files changed, 8900 insertions(+)
>  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/element.h
>  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/gstr.h
>  create mode 100644 grub-core/lib/libtasn1/lib/int.h
>  create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.c
>  create mode 100644 grub-core/lib/libtasn1/lib/parser_aux.h
>  create mode 100644 grub-core/lib/libtasn1/lib/structure.c
>  create mode 100644 grub-core/lib/libtasn1/lib/structure.h
>  create mode 100644 include/grub/libtasn1.h
>
> diff --git a/grub-core/lib/libtasn1/COPYING b/grub-core/lib/libtasn1/COPYING
> new file mode 100644
> index 000000000..e8b3628db
> --- /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 000000000..b0305b93e
> --- /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 000000000..ea5bc370e
> --- /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 000000000..b9245c486
> --- /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 000000000..d4c558e10
> --- /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/element.h 
> b/grub-core/lib/libtasn1/lib/element.h
> new file mode 100644
> index 000000000..8dd0ceba8
> --- /dev/null
> +++ b/grub-core/lib/libtasn1/lib/element.h
> @@ -0,0 +1,42 @@
> +/*
> + * 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
> + */
> +
> +#ifndef _ELEMENT_H
> +# define _ELEMENT_H
> +
> +
> +struct node_tail_cache_st
> +{
> +  asn1_node head;              /* the first element of the sequence */
> +  asn1_node tail;
> +};
> +
> +int _asn1_append_sequence_set (asn1_node node,
> +                              struct node_tail_cache_st *pcached);
> +
> +int _asn1_convert_integer (const unsigned char *value,
> +                          unsigned char *value_out,
> +                          int value_out_size, int *len);
> +
> +void _asn1_hierarchical_name (asn1_node_const node, char *name,
> +                             int name_size);
> +
> +#endif
> diff --git a/grub-core/lib/libtasn1/lib/errors.c 
> b/grub-core/lib/libtasn1/lib/errors.c
> new file mode 100644
> index 000000000..aef5dfe6f
> --- /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 000000000..eef419554
> --- /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/gstr.h 
> b/grub-core/lib/libtasn1/lib/gstr.h
> new file mode 100644
> index 000000000..99be6c4af
> --- /dev/null
> +++ b/grub-core/lib/libtasn1/lib/gstr.h
> @@ -0,0 +1,50 @@
> +/*
> + * 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
> + */
> +
> +#ifndef GSTR_H
> +# define GSTR_H
> +
> +unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size,
> +                           const char *src);
> +void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src);
> +
> +# define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
> +# define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
> +
> +inline static void
> +safe_memset (void *data, int c, size_t size)
> +{
> +  volatile unsigned volatile_zero = 0;
> +  volatile char *vdata = (volatile char *) data;
> +
> +  /* This is based on a nice trick for safe memset,
> +   * sent by David Jacobson in the openssl-dev mailing list.
> +   */
> +
> +  if (size > 0)
> +    do
> +      {
> +       memset (data, c, size);
> +      }
> +    while (vdata[volatile_zero] != c);
> +}
> +
> +#endif /* GSTR_H */
> diff --git a/grub-core/lib/libtasn1/lib/int.h 
> b/grub-core/lib/libtasn1/lib/int.h
> new file mode 100644
> index 000000000..d94d51c8c
> --- /dev/null
> +++ b/grub-core/lib/libtasn1/lib/int.h
> @@ -0,0 +1,221 @@
> +/*
> + * 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
> + */
> +
> +#ifndef INT_H
> +# define INT_H
> +
> +# ifdef HAVE_CONFIG_H
> +#  include <config.h>
> +# endif
> +
> +# include <string.h>
> +# include <stdlib.h>
> +# include <stdio.h>
> +# include <stdint.h>
> +
> +# ifdef HAVE_SYS_TYPES_H
> +#  include <sys/types.h>
> +# endif
> +
> +# include <libtasn1.h>
> +
> +# define ASN1_SMALL_VALUE_SIZE 16
> +
> +/* This structure is also in libtasn1.h, but then contains less
> +   fields.  You cannot make any modifications to these first fields
> +   without breaking ABI.  */
> +struct asn1_node_st
> +{
> +  /* public fields: */
> +  char name[ASN1_MAX_NAME_SIZE + 1];   /* Node name */
> +  unsigned int name_hash;
> +  unsigned int type;           /* Node type */
> +  unsigned char *value;                /* Node value */
> +  int value_len;
> +  asn1_node down;              /* Pointer to the son node */
> +  asn1_node right;             /* Pointer to the brother node */
> +  asn1_node left;              /* Pointer to the next list element */
> +  /* private fields: */
> +  unsigned char small_value[ASN1_SMALL_VALUE_SIZE];    /* For small values */
> +
> +  /* values used during decoding/coding */
> +  int tmp_ival;
> +  unsigned start;              /* the start of the DER sequence - if decoded 
> */
> +  unsigned end;                        /* the end of the DER sequence - if 
> decoded */
> +};
> +
> +typedef struct tag_and_class_st
> +{
> +  unsigned tag;
> +  unsigned class;
> +  const char *desc;
> +} tag_and_class_st;
> +
> +/* the types that are handled in _asn1_tags */
> +# define CASE_HANDLED_ETYPES \
> +       case ASN1_ETYPE_NULL: \
> +       case ASN1_ETYPE_BOOLEAN: \
> +       case ASN1_ETYPE_INTEGER: \
> +       case ASN1_ETYPE_ENUMERATED: \
> +       case ASN1_ETYPE_OBJECT_ID: \
> +       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: \
> +       case ASN1_ETYPE_SEQUENCE: \
> +       case ASN1_ETYPE_SEQUENCE_OF: \
> +       case ASN1_ETYPE_SET: \
> +       case ASN1_ETYPE_UTC_TIME: \
> +       case ASN1_ETYPE_GENERALIZED_TIME: \
> +       case ASN1_ETYPE_SET_OF
> +
> +# define ETYPE_TAG(etype) (_asn1_tags[etype].tag)
> +# define ETYPE_CLASS(etype) (_asn1_tags[etype].class)
> +# define ETYPE_OK(etype) (((etype) != ASN1_ETYPE_INVALID && \
> +                          (etype) < _asn1_tags_size && \
> +                          _asn1_tags[(etype)].desc != NULL)?1:0)
> +
> +# define ETYPE_IS_STRING(etype) ((etype == ASN1_ETYPE_GENERALSTRING || \
> +       etype == ASN1_ETYPE_NUMERIC_STRING || etype == ASN1_ETYPE_IA5_STRING 
> || \
> +       etype == ASN1_ETYPE_TELETEX_STRING || etype == 
> ASN1_ETYPE_PRINTABLE_STRING || \
> +       etype == ASN1_ETYPE_UNIVERSAL_STRING || etype == 
> ASN1_ETYPE_BMP_STRING || \
> +       etype == ASN1_ETYPE_UTF8_STRING || etype == ASN1_ETYPE_VISIBLE_STRING 
> || \
> +       etype == ASN1_ETYPE_OCTET_STRING)?1:0)
> +
> +extern unsigned int _asn1_tags_size;
> +extern const tag_and_class_st _asn1_tags[];
> +
> +# define _asn1_strlen(s) strlen((const char *) s)
> +# define _asn1_strtol(n,e,b) strtol((const char *) n, e, b)
> +# 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)
> +# else
> +#  define _asn1_strtou64(n,e,b) strtoull((const char *) n, e, b)
> +# endif
> +
> +# define MAX_LOG_SIZE 1024     /* maximum number of characters of a log 
> message */
> +
> +/* Define used for visiting trees. */
> +# define UP     1
> +# define RIGHT  2
> +# define DOWN   3
> +
> +/***********************************************************************/
> +/* List of constants to better specify the type of typedef asn1_node_st.   */
> +/***********************************************************************/
> +/*  Used with TYPE_TAG  */
> +# define CONST_UNIVERSAL   (1U<<8)
> +# define CONST_PRIVATE     (1U<<9)
> +# define CONST_APPLICATION (1U<<10)
> +# define CONST_EXPLICIT    (1U<<11)
> +# define CONST_IMPLICIT    (1U<<12)
> +
> +# define CONST_TAG         (1U<<13)    /*  Used in ASN.1 assignement  */
> +# define CONST_OPTION      (1U<<14)
> +# define CONST_DEFAULT     (1U<<15)
> +# define CONST_TRUE        (1U<<16)
> +# define CONST_FALSE       (1U<<17)
> +
> +# define CONST_LIST        (1U<<18)    /*  Used with TYPE_INTEGER and 
> TYPE_BIT_STRING  */
> +# define CONST_MIN_MAX     (1U<<19)
> +
> +# define CONST_1_PARAM     (1U<<20)
> +
> +# define CONST_SIZE        (1U<<21)
> +
> +# define CONST_DEFINED_BY  (1U<<22)
> +
> +/* Those two are deprecated and used for backwards compatibility */
> +# define CONST_GENERALIZED (1U<<23)
> +# define CONST_UTC         (1U<<24)
> +
> +/* #define CONST_IMPORTS     (1U<<25) */
> +
> +# define CONST_NOT_USED    (1U<<26)
> +# define CONST_SET         (1U<<27)
> +# define CONST_ASSIGN      (1U<<28)
> +
> +# define CONST_DOWN        (1U<<29)
> +# define CONST_RIGHT       (1U<<30)
> +
> +
> +# define ASN1_ETYPE_TIME 17
> +/****************************************/
> +/* Returns the first 8 bits.            */
> +/* Used with the field type of asn1_node_st */
> +/****************************************/
> +inline static unsigned int
> +type_field (unsigned int ntype)
> +{
> +  return (ntype & 0xff);
> +}
> +
> +/* To convert old types from a static structure */
> +inline static unsigned int
> +convert_old_type (unsigned int ntype)
> +{
> +  unsigned int type = ntype & 0xff;
> +  if (type == ASN1_ETYPE_TIME)
> +    {
> +      if (ntype & CONST_UTC)
> +       type = ASN1_ETYPE_UTC_TIME;
> +      else
> +       type = ASN1_ETYPE_GENERALIZED_TIME;
> +
> +      ntype &= ~(CONST_UTC | CONST_GENERALIZED);
> +      ntype &= 0xffffff00;
> +      ntype |= type;
> +
> +      return ntype;
> +    }
> +  else
> +    return ntype;
> +}
> +
> +static inline void *
> +_asn1_realloc (void *ptr, size_t size)
> +{
> +  void *ret;
> +
> +  if (size == 0)
> +    return ptr;
> +
> +  ret = realloc (ptr, size);
> +  if (ret == NULL)
> +    {
> +      free (ptr);
> +    }
> +  return ret;
> +}
> +
> +#endif /* INT_H */
> 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 000000000..c05bd2339
> --- /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/parser_aux.h 
> b/grub-core/lib/libtasn1/lib/parser_aux.h
> new file mode 100644
> index 000000000..3eac1fa30
> --- /dev/null
> +++ b/grub-core/lib/libtasn1/lib/parser_aux.h
> @@ -0,0 +1,172 @@
> +/*
> + * 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
> + */
> +
> +#ifndef _PARSER_AUX_H
> +# define _PARSER_AUX_H
> +
> +/***********************************************/
> +/* Type: list_type                             */
> +/* Description: type used in the list during   */
> +/* the structure creation.                     */
> +/***********************************************/
> +typedef struct list_struct
> +{
> +  asn1_node node;
> +  struct list_struct *next;
> +} list_type;
> +
> +/***************************************/
> +/*  Functions used by ASN.1 parser     */
> +/***************************************/
> +asn1_node _asn1_add_static_node (list_type ** e_list, unsigned int type);
> +
> +void _asn1_delete_list (list_type * e_list);
> +
> +void _asn1_delete_list_and_nodes (list_type * e_list);
> +
> +void _asn1_delete_node_from_list (list_type * list, asn1_node node);
> +
> +asn1_node
> +_asn1_set_value (asn1_node node, const void *value, unsigned int len);
> +
> +asn1_node _asn1_set_value_m (asn1_node node, void *value, unsigned int len);
> +
> +asn1_node
> +_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len);
> +
> +asn1_node
> +_asn1_append_value (asn1_node node, const void *value, unsigned int len);
> +
> +asn1_node _asn1_set_name (asn1_node node, const char *name);
> +
> +asn1_node _asn1_cpy_name (asn1_node dst, asn1_node_const src);
> +
> +asn1_node _asn1_set_right (asn1_node node, asn1_node right);
> +
> +asn1_node _asn1_get_last_right (asn1_node_const node);
> +
> +void _asn1_remove_node (asn1_node node, unsigned int flags);
> +
> +/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null 
> termination */
> +# define LTOSTR_MAX_SIZE 22
> +char *_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]);
> +
> +asn1_node _asn1_find_up (asn1_node_const node);
> +
> +int _asn1_change_integer_value (asn1_node node);
> +
> +# define EXPAND_OBJECT_ID_MAX_RECURSION 16
> +int _asn1_expand_object_id (list_type ** list, asn1_node node);
> +
> +int _asn1_type_set_config (asn1_node node);
> +
> +int _asn1_check_identifier (asn1_node_const node);
> +
> +int _asn1_set_default_tag (asn1_node node);
> +
> +/******************************************************************/
> +/* Function : _asn1_get_right                                     */
> +/* Description: returns the element pointed by the RIGHT field of */
> +/*              a NODE_ASN element.                               */
> +/* Parameters:                                                    */
> +/*   node: NODE_ASN element pointer.                              */
> +/* Return: field RIGHT of NODE.                                   */
> +/******************************************************************/
> +inline static asn1_node
> +_asn1_get_right (asn1_node_const node)
> +{
> +  if (node == NULL)
> +    return NULL;
> +  return node->right;
> +}
> +
> +/******************************************************************/
> +/* Function : _asn1_set_down                                      */
> +/* Description: sets the field DOWN in a NODE_ASN element.        */
> +/* Parameters:                                                    */
> +/*   node: element pointer.                                       */
> +/*   down: pointer to a NODE_ASN element that you want be pointed */
> +/*          by NODE.                                              */
> +/* Return: pointer to *NODE.                                      */
> +/******************************************************************/
> +inline static asn1_node
> +_asn1_set_down (asn1_node node, asn1_node down)
> +{
> +  if (node == NULL)
> +    return node;
> +  node->down = down;
> +  if (down)
> +    down->left = node;
> +  return node;
> +}
> +
> +/******************************************************************/
> +/* Function : _asn1_get_down                                      */
> +/* Description: returns the element pointed by the DOWN field of  */
> +/*              a NODE_ASN element.                               */
> +/* Parameters:                                                    */
> +/*   node: NODE_ASN element pointer.                              */
> +/* Return: field DOWN of NODE.                                    */
> +/******************************************************************/
> +inline static asn1_node
> +_asn1_get_down (asn1_node_const node)
> +{
> +  if (node == NULL)
> +    return NULL;
> +  return node->down;
> +}
> +
> +/******************************************************************/
> +/* Function : _asn1_get_name                                      */
> +/* Description: returns the name of a NODE_ASN element.           */
> +/* Parameters:                                                    */
> +/*   node: NODE_ASN element pointer.                              */
> +/* Return: a null terminated string.                              */
> +/******************************************************************/
> +inline static char *
> +_asn1_get_name (asn1_node_const node)
> +{
> +  if (node == NULL)
> +    return NULL;
> +  return (char *) node->name;
> +}
> +
> +/******************************************************************/
> +/* Function : _asn1_mod_type                                      */
> +/* Description: change the field TYPE of an NODE_ASN element.     */
> +/*              The new value is the old one | (bitwise or) the   */
> +/*              paramener VALUE.                                  */
> +/* Parameters:                                                    */
> +/*   node: NODE_ASN element pointer.                              */
> +/*   value: the integer value that must be or-ed with the current */
> +/*          value of field TYPE.                                  */
> +/* Return: NODE pointer.                                          */
> +/******************************************************************/
> +inline static asn1_node
> +_asn1_mod_type (asn1_node node, unsigned int value)
> +{
> +  if (node == NULL)
> +    return node;
> +  node->type |= value;
> +  return node;
> +}
> +
> +#endif
> diff --git a/grub-core/lib/libtasn1/lib/structure.c 
> b/grub-core/lib/libtasn1/lib/structure.c
> new file mode 100644
> index 000000000..512dd601f
> --- /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/lib/structure.h 
> b/grub-core/lib/libtasn1/lib/structure.h
> new file mode 100644
> index 000000000..b973ce963
> --- /dev/null
> +++ b/grub-core/lib/libtasn1/lib/structure.h
> @@ -0,0 +1,46 @@
> +/*
> + * 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.h                             */
> +/* Description: list of exported object by       */
> +/*   "structure.c"                               */
> +/*************************************************/
> +
> +#ifndef _STRUCTURE_H
> +# define _STRUCTURE_H
> +
> +# include "parser_aux.h"       /* list_type */
> +
> +int _asn1_create_static_structure (asn1_node_const pointer,
> +                                  char *output_file_name, char *vector_name);
> +
> +asn1_node _asn1_copy_structure3 (asn1_node_const source_node);
> +
> +asn1_node _asn1_add_single_node (unsigned int type);
> +
> +asn1_node _asn1_find_left (asn1_node_const node);
> +
> +int
> +_asn1_delete_structure (list_type * e_list, asn1_node * structure,
> +                       unsigned int flags);
> +
> +#endif
> diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h
> new file mode 100644
> index 000000000..51cc7879f
> --- /dev/null
> +++ b/include/grub/libtasn1.h
> @@ -0,0 +1,643 @@
> +/*
> + * Copyright (C) 2002-2022 Free Software Foundation, Inc.
> + *
> + * This file is part of LIBTASN1.
> + *
> + * LIBTASN1 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.
> + *
> + * LIBTASN1 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 LIBTASN1; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> + * 02110-1301, USA
> + *
> + */
> +
> +/**
> + * SECTION:libtasn1
> + * @short_description: GNU ASN.1 library
> + *
> + * The Libtasn1 library provides Abstract Syntax Notation One (ASN.1, as
> + * specified by the X.680 ITU-T recommendation) parsing and structures
> + * management, and Distinguished Encoding Rules (DER, as per X.690)
> + * encoding and decoding functions.
> + */
> +
> +
> +#ifndef LIBTASN1_H
> +# define LIBTASN1_H
> +
> +# ifndef ASN1_API
> +#  if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY
> +#   define ASN1_API __attribute__((__visibility__("default")))
> +#  elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC
> +#   define ASN1_API __declspec(dllexport)
> +#  elif defined _MSC_VER && ! defined ASN1_STATIC
> +#   define ASN1_API __declspec(dllimport)
> +#  else
> +#   define ASN1_API
> +#  endif
> +# endif
> +
> +# ifdef __GNUC__
> +#  define __LIBTASN1_CONST__  __attribute__((const))
> +#  define __LIBTASN1_PURE__  __attribute__((pure))
> +# else
> +#  define __LIBTASN1_CONST__
> +#  define __LIBTASN1_PURE__
> +# endif
> +
> +# include <sys/types.h>
> +# include <time.h>
> +# include <stdio.h>            /* for FILE* */
> +
> +# ifdef __cplusplus
> +extern "C"
> +{
> +# endif
> +
> +/**
> + * ASN1_VERSION:
> + *
> + * Version of the library as a string.
> + */
> +# define ASN1_VERSION "4.19.0"
> +
> +/**
> + * ASN1_VERSION_MAJOR:
> + *
> + * Major version number of the library.
> + */
> +# define ASN1_VERSION_MAJOR 4
> +
> +/**
> + * ASN1_VERSION_MINOR:
> + *
> + * Minor version number of the library.
> + */
> +# define ASN1_VERSION_MINOR 19
> +
> +/**
> + * ASN1_VERSION_PATCH:
> + *
> + * Patch version number of the library.
> + */
> +# define ASN1_VERSION_PATCH 0
> +
> +/**
> + * ASN1_VERSION_NUMBER:
> + *
> + * Version number of the library as a number.
> + */
> +# define ASN1_VERSION_NUMBER 0x041300
> +
> +
> +# if defined __GNUC__ && !defined ASN1_INTERNAL_BUILD
> +#  define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + 
> __GNUC_PATCHLEVEL__)
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
> +#  endif
> +# endif
> +
> +# ifndef _ASN1_GCC_ATTR_DEPRECATED
> +#  define _ASN1_GCC_ATTR_DEPRECATED
> +# endif
> +
> +/*****************************************/
> +/* Errors returned by libtasn1 functions */
> +/*****************************************/
> +# define ASN1_SUCCESS                  0
> +# define ASN1_FILE_NOT_FOUND           1
> +# define ASN1_ELEMENT_NOT_FOUND                2
> +# define ASN1_IDENTIFIER_NOT_FOUND     3
> +# define ASN1_DER_ERROR                        4
> +# define ASN1_VALUE_NOT_FOUND          5
> +# define ASN1_GENERIC_ERROR            6
> +# define ASN1_VALUE_NOT_VALID          7
> +# define ASN1_TAG_ERROR                        8
> +# define ASN1_TAG_IMPLICIT             9
> +# define ASN1_ERROR_TYPE_ANY           10
> +# define ASN1_SYNTAX_ERROR             11
> +# define ASN1_MEM_ERROR                        12
> +# define ASN1_MEM_ALLOC_ERROR          13
> +# define ASN1_DER_OVERFLOW             14
> +# define ASN1_NAME_TOO_LONG            15
> +# define ASN1_ARRAY_ERROR              16
> +# define ASN1_ELEMENT_NOT_EMPTY                17
> +# define ASN1_TIME_ENCODING_ERROR      18
> +# define ASN1_RECURSION                        19
> +
> +/*************************************/
> +/* Constants used in asn1_visit_tree */
> +/*************************************/
> +# define ASN1_PRINT_NAME                       1
> +# define ASN1_PRINT_NAME_TYPE          2
> +# define ASN1_PRINT_NAME_TYPE_VALUE    3
> +# define ASN1_PRINT_ALL                        4
> +
> +/*****************************************/
> +/* Constants returned by asn1_read_tag   */
> +/*****************************************/
> +# define ASN1_CLASS_UNIVERSAL          0x00    /* old: 1 */
> +# define ASN1_CLASS_APPLICATION                0x40    /* old: 2 */
> +# define ASN1_CLASS_CONTEXT_SPECIFIC   0x80    /* old: 3 */
> +# define ASN1_CLASS_PRIVATE            0xC0    /* old: 4 */
> +# define ASN1_CLASS_STRUCTURED         0x20
> +
> +/*****************************************/
> +/* Constants returned by asn1_read_tag   */
> +/*****************************************/
> +# define ASN1_TAG_BOOLEAN              0x01
> +# define ASN1_TAG_INTEGER              0x02
> +# define ASN1_TAG_SEQUENCE             0x10
> +# define ASN1_TAG_SET                  0x11
> +# define ASN1_TAG_OCTET_STRING         0x04
> +# define ASN1_TAG_BIT_STRING           0x03
> +# define ASN1_TAG_UTCTime              0x17
> +# define ASN1_TAG_GENERALIZEDTime      0x18
> +# define ASN1_TAG_OBJECT_ID            0x06
> +# define ASN1_TAG_ENUMERATED           0x0A
> +# define ASN1_TAG_NULL                 0x05
> +# define ASN1_TAG_GENERALSTRING                0x1B
> +# define ASN1_TAG_NUMERIC_STRING               0x12
> +# define ASN1_TAG_IA5_STRING           0x16
> +# define ASN1_TAG_TELETEX_STRING               0x14
> +# define ASN1_TAG_PRINTABLE_STRING     0x13
> +# define ASN1_TAG_UNIVERSAL_STRING     0x1C
> +# define ASN1_TAG_BMP_STRING           0x1E
> +# define ASN1_TAG_UTF8_STRING          0x0C
> +# define ASN1_TAG_VISIBLE_STRING               0x1A
> +
> +/**
> + * asn1_node:
> + *
> + * Structure definition used for the node of the tree
> + * that represents an ASN.1 DEFINITION.
> + */
> +  typedef struct asn1_node_st asn1_node_st;
> +
> +  typedef asn1_node_st *asn1_node;
> +  typedef const asn1_node_st *asn1_node_const;
> +
> +/**
> + * ASN1_MAX_NAME_SIZE:
> + *
> + * Maximum number of characters of a name
> + * inside a file with ASN1 definitions.
> + */
> +# define ASN1_MAX_NAME_SIZE 64
> +
> +
> +/**
> + * asn1_static_node:
> + * @name: Node name
> + * @type: Node typ
> + * @value: Node value
> + *
> + * For the on-disk format of ASN.1 trees, created by asn1_parser2array().
> + */
> +  typedef struct asn1_static_node_st
> +  {
> +    const char *name;          /* Node name */
> +    unsigned int type;         /* Node type */
> +    const void *value;         /* Node value */
> +  } asn1_static_node;
> +
> +/* List of constants for field type of asn1_static_node */
> +# define ASN1_ETYPE_INVALID        0
> +# define ASN1_ETYPE_CONSTANT       1
> +# define ASN1_ETYPE_IDENTIFIER     2
> +# define ASN1_ETYPE_INTEGER        3
> +# define ASN1_ETYPE_BOOLEAN        4
> +# define ASN1_ETYPE_SEQUENCE       5
> +# define ASN1_ETYPE_BIT_STRING     6
> +# define ASN1_ETYPE_OCTET_STRING   7
> +# define ASN1_ETYPE_TAG            8
> +# define ASN1_ETYPE_DEFAULT        9
> +# define ASN1_ETYPE_SIZE          10
> +# define ASN1_ETYPE_SEQUENCE_OF   11
> +# define ASN1_ETYPE_OBJECT_ID     12
> +# define ASN1_ETYPE_ANY           13
> +# define ASN1_ETYPE_SET           14
> +# define ASN1_ETYPE_SET_OF        15
> +# define ASN1_ETYPE_DEFINITIONS   16
> +# define ASN1_ETYPE_CHOICE        18
> +# define ASN1_ETYPE_IMPORTS       19
> +# define ASN1_ETYPE_NULL          20
> +# define ASN1_ETYPE_ENUMERATED    21
> +# define ASN1_ETYPE_GENERALSTRING 27
> +# define ASN1_ETYPE_NUMERIC_STRING 28
> +# define ASN1_ETYPE_IA5_STRING     29
> +# define ASN1_ETYPE_TELETEX_STRING 30
> +# define ASN1_ETYPE_PRINTABLE_STRING 31
> +# define ASN1_ETYPE_UNIVERSAL_STRING 32
> +# define ASN1_ETYPE_BMP_STRING     33
> +# define ASN1_ETYPE_UTF8_STRING    34
> +# define ASN1_ETYPE_VISIBLE_STRING 35
> +# define ASN1_ETYPE_UTC_TIME       36
> +# define ASN1_ETYPE_GENERALIZED_TIME 37
> +
> +/**
> + * ASN1_DELETE_FLAG_ZEROIZE:
> + *
> + * Used by: asn1_delete_structure2()
> + *
> + * Zeroize values prior to deinitialization.
> + */
> +# define ASN1_DELETE_FLAG_ZEROIZE 1
> +
> +/**
> + * ASN1_DECODE_FLAG_ALLOW_PADDING:
> + *
> + * Used by: asn1_der_decoding2()
> + *
> + * This flag would allow arbitrary data past the DER data.
> + */
> +# define ASN1_DECODE_FLAG_ALLOW_PADDING 1
> +/**
> + * ASN1_DECODE_FLAG_STRICT_DER:
> + *
> + * Used by: asn1_der_decoding2()
> + *
> + * This flag would ensure that no BER decoding takes place.
> + */
> +# define ASN1_DECODE_FLAG_STRICT_DER (1<<1)
> +/**
> + * ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME:
> + *
> + * Used by: asn1_der_decoding2()
> + *
> + * This flag will tolerate Time encoding errors when in strict DER.
> + */
> +# define ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME (1<<2)
> +
> +  /* *INDENT-OFF* */
> +
> +/**
> + * asn1_data_node_st:
> + * @name: Node name
> + * @value: Node value
> + * @value_len: Node value size
> + * @type: Node value type (ASN1_ETYPE_*)
> + *
> + * Data node inside a #asn1_node structure.
> + */
> +  struct asn1_data_node_st
> +  {
> +    const char *name;          /* Node name */
> +    const void *value;         /* Node value */
> +    unsigned int value_len;    /* Node value size */
> +    unsigned int type;         /* Node value type (ASN1_ETYPE_*) */
> +};
> +
> +  /* *INDENT-ON* */
> +
> +  typedef struct asn1_data_node_st asn1_data_node_st;
> +
> +/***********************************/
> +/*  Fixed constants                */
> +/***********************************/
> +
> +/**
> + * ASN1_MAX_ERROR_DESCRIPTION_SIZE:
> + *
> + * Maximum number of characters
> + * of a description message
> + * (null character included).
> + */
> +# define ASN1_MAX_ERROR_DESCRIPTION_SIZE 128
> +
> +/***********************************/
> +/*  Functions definitions          */
> +/***********************************/
> +
> +  extern ASN1_API int
> +    asn1_parser2tree (const char *file,
> +                     asn1_node * definitions, char *error_desc);
> +
> +  extern ASN1_API int
> +    asn1_parser2array (const char *inputFileName,
> +                      const char *outputFileName,
> +                      const char *vectorName, char *error_desc);
> +
> +  extern ASN1_API int
> +    asn1_array2tree (const asn1_static_node * array,
> +                    asn1_node * definitions, char *errorDescription);
> +
> +  extern ASN1_API void
> +    asn1_print_structure (FILE * out, asn1_node_const structure,
> +                         const char *name, int mode);
> +
> +  extern ASN1_API int
> +    asn1_create_element (asn1_node_const definitions,
> +                        const char *source_name, asn1_node * element);
> +
> +  extern ASN1_API int asn1_delete_structure (asn1_node * structure);
> +
> +  extern ASN1_API int asn1_delete_structure2 (asn1_node * structure,
> +                                             unsigned int flags);
> +
> +  extern ASN1_API int
> +    asn1_delete_element (asn1_node structure, const char *element_name);
> +
> +  extern ASN1_API int
> +    asn1_write_value (asn1_node node_root, const char *name,
> +                     const void *ivalue, int len);
> +
> +  extern ASN1_API int
> +    asn1_read_value (asn1_node_const root, const char *name,
> +                    void *ivalue, int *len);
> +
> +  extern ASN1_API int
> +    asn1_read_value_type (asn1_node_const root, const char *name,
> +                         void *ivalue, int *len, unsigned int *etype);
> +
> +  extern ASN1_API int
> +    asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data);
> +
> +  extern ASN1_API int
> +    asn1_number_of_elements (asn1_node_const element, const char *name,
> +                            int *num);
> +
> +  extern ASN1_API int
> +    asn1_der_coding (asn1_node_const element, const char *name,
> +                    void *ider, int *len, char *ErrorDescription);
> +
> +  extern ASN1_API int
> +    asn1_der_decoding2 (asn1_node * element, const void *ider,
> +                       int *max_ider_len, unsigned int flags,
> +                       char *errorDescription);
> +
> +  extern ASN1_API int
> +    asn1_der_decoding (asn1_node * element, const void *ider,
> +                      int ider_len, char *errorDescription);
> +
> +/* Do not use. Use asn1_der_decoding() instead. */
> +  extern ASN1_API int
> +    asn1_der_decoding_element (asn1_node * structure,
> +                              const char *elementName,
> +                              const void *ider, int len,
> +                              char *errorDescription)
> +    _ASN1_GCC_ATTR_DEPRECATED;
> +
> +  extern ASN1_API int
> +    asn1_der_decoding_startEnd (asn1_node element,
> +                               const void *ider, int ider_len,
> +                               const char *name_element,
> +                               int *start, int *end);
> +
> +  extern ASN1_API int
> +    asn1_expand_any_defined_by (asn1_node_const definitions,
> +                               asn1_node * element);
> +
> +  extern ASN1_API int
> +    asn1_expand_octet_string (asn1_node_const definitions,
> +                             asn1_node * element,
> +                             const char *octetName, const char *objectName);
> +
> +  extern ASN1_API int
> +    asn1_read_tag (asn1_node_const root, const char *name,
> +                  int *tagValue, int *classValue);
> +
> +  extern ASN1_API const char *asn1_find_structure_from_oid (asn1_node_const
> +                                                           definitions,
> +                                                           const char
> +                                                           *oidValue);
> +
> +    __LIBTASN1_PURE__
> +    extern ASN1_API const char *asn1_check_version (const char *req_version);
> +
> +  __LIBTASN1_PURE__ extern ASN1_API const char *asn1_strerror (int error);
> +
> +  extern ASN1_API void asn1_perror (int error);
> +
> +# define ASN1_MAX_TAG_SIZE 4
> +# define ASN1_MAX_LENGTH_SIZE 9
> +# define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE)
> +  extern ASN1_API long
> +    asn1_get_length_der (const unsigned char *der, int der_len, int *len);
> +
> +  extern ASN1_API long
> +    asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len);
> +
> +  extern ASN1_API void
> +    asn1_length_der (unsigned long int len, unsigned char *der, int 
> *der_len);
> +
> +/* Other utility functions. */
> +
> +  extern ASN1_API
> +    int asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
> +                               unsigned int _der_len,
> +                               const unsigned char **str,
> +                               unsigned int *str_len);
> +
> +  extern ASN1_API
> +    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);
> +
> +  extern ASN1_API int
> +    asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
> +                           unsigned int str_len, unsigned char *tl,
> +                           unsigned int *tl_len);
> +
> +  extern ASN1_API asn1_node
> +    asn1_find_node (asn1_node_const pointer, const char *name);
> +
> +  extern ASN1_API int
> +    asn1_copy_node (asn1_node dst, const char *dst_name,
> +                   asn1_node_const src, const char *src_name);
> +  extern ASN1_API asn1_node
> +    asn1_dup_node (asn1_node_const src, const char *src_name);
> +
> +/* Internal and low-level DER utility functions. */
> +
> +  extern ASN1_API int
> +    asn1_get_tag_der (const unsigned char *der, int der_len,
> +                     unsigned char *cls, int *len, unsigned long *tag);
> +
> +  extern ASN1_API void
> +    asn1_octet_der (const unsigned char *str, int str_len,
> +                   unsigned char *der, int *der_len);
> +
> +  extern ASN1_API int
> +    asn1_get_octet_der (const unsigned char *der, int der_len,
> +                       int *ret_len, unsigned char *str,
> +                       int str_size, int *str_len);
> +
> +  extern ASN1_API void asn1_bit_der (const unsigned char *str, int bit_len,
> +                                    unsigned char *der, int *der_len);
> +
> +  extern ASN1_API int
> +    asn1_get_bit_der (const unsigned char *der, int der_len,
> +                     int *ret_len, unsigned char *str,
> +                     int str_size, int *bit_len);
> +
> +  extern ASN1_API int
> +    asn1_get_object_id_der (const unsigned char *der,
> +                           int der_len, int *ret_len,
> +                           char *str, int str_size);
> +
> +  extern ASN1_API int
> +    asn1_object_id_der (const char *str, unsigned char *der, int *der_len,
> +                       unsigned flags);
> +
> +/* Compatibility types */
> +
> +/**
> + * asn1_retCode:
> + *
> + * Type formerly returned by libtasn1 functions.
> + *
> + * Deprecated: 3.0: Use int instead.
> + */
> +  typedef int asn1_retCode _ASN1_GCC_ATTR_DEPRECATED;
> +
> +/**
> + * node_asn_struct:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_node instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define node_asn_struct _Pragma ("GCC warning \"'node_asn_struct' macro 
> is deprecated, use 'asn1_node' instead.\"") asn1_node_st
> +#  else
> +#   define node_asn_struct asn1_node_st
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * node_asn:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_node instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define node_asn _Pragma ("GCC warning \"'node_asn' macro is deprecated, 
> use 'asn1_node' instead.\"") asn1_node_st
> +#  else
> +#   define node_asn asn1_node_st
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * ASN1_TYPE:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_node instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define ASN1_TYPE _Pragma ("GCC warning \"'ASN1_TYPE' macro is 
> deprecated, use 'asn1_node' instead.\"") asn1_node
> +#  else
> +#   define ASN1_TYPE asn1_node
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * ASN1_TYPE_EMPTY:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use NULL instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define ASN1_TYPE_EMPTY _Pragma ("GCC warning \"'ASN1_TYPE_EMPTY' macro 
> is deprecated, use 'NULL' instead.\"") NULL
> +#  else
> +#   define ASN1_TYPE_EMPTY NULL
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * static_struct_asn:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_static_node instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define static_struct_asn _Pragma ("GCC warning \"'static_struct_asn' 
> macro is deprecated, use 'asn1_static_node_st' instead.\"") 
> asn1_static_node_st
> +#  else
> +#   define static_struct_asn asn1_static_node_st
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * ASN1_ARRAY_TYPE:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_static_node instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define ASN1_ARRAY_TYPE _Pragma ("GCC warning \"'ASN1_ARRAY_TYPE' macro 
> is deprecated, use 'asn1_static_node' instead.\"") asn1_static_node
> +#  else
> +#   define ASN1_ARRAY_TYPE asn1_static_node
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * asn1_static_node_t:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_static_node instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define asn1_static_node_t _Pragma ("GCC warning \"'asn1_static_node_t' 
> macro is deprecated, use 'asn1_static_node' instead.\"") asn1_static_node
> +#  else
> +#   define asn1_static_node_t asn1_static_node
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * node_data_struct:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_data_node_st instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define node_data_struct _Pragma ("GCC warning \"'node_data_struct' macro 
> is deprecated, use 'asn1_data_node_st' instead.\"") asn1_data_node_st
> +#  else
> +#   define node_data_struct asn1_data_node_st
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +/**
> + * ASN1_DATA_NODE:
> + *
> + * Compat #define.
> + *
> + * Deprecated: 3.0: Use #asn1_data_node_st instead.
> + */
> +# ifndef ASN1_DISABLE_DEPRECATED
> +#  if _ASN1_GCC_VERSION >= 30100
> +#   define ASN1_DATA_NODE _Pragma ("GCC warning \"'asn1_static_node_t' macro 
> is deprecated, use 'asn1_static_node' instead.\"") asn1_data_node_st
> +#  else
> +#   define ASN1_DATA_NODE asn1_data_node_st
> +#  endif
> +# endif                                /* !ASN1_DISABLE_DEPRECATED */
> +
> +# ifdef __cplusplus
> +}
> +# endif
> +
> +#endif                         /* LIBTASN1_H */
> --
> 2.35.3
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



-- 
Regards
Vladimir 'phcoder' Serbinenko



reply via email to

[Prev in Thread] Current Thread [Next in Thread]