Start Up Version
authorFabio Fiorina <fiorinaf@gnutls.org>
Wed, 15 May 2002 19:53:09 +0000 (19:53 +0000)
committerFabio Fiorina <fiorinaf@gnutls.org>
Wed, 15 May 2002 19:53:09 +0000 (19:53 +0000)
25 files changed:
lib/ASN1.c [new file with mode: 0644]
lib/ASN1.y [new file with mode: 0644]
lib/coding.c [new file with mode: 0644]
lib/decoding.c [new file with mode: 0644]
lib/element.c [new file with mode: 0644]
lib/element.h [new file with mode: 0644]
lib/errors.c [new file with mode: 0644]
lib/errors.h [new file with mode: 0644]
lib/errors_int.h [new file with mode: 0644]
lib/int.h [new file with mode: 0644]
lib/parser_aux.c [new file with mode: 0644]
lib/parser_aux.h [new file with mode: 0644]
lib/structure.c [new file with mode: 0644]
lib/structure.h [new file with mode: 0644]
src/asn1Coding.c [new file with mode: 0644]
src/asn1Coding_test.asg [new file with mode: 0644]
src/asn1Coding_test.asn [new file with mode: 0644]
src/asn1Decoding.c [new file with mode: 0644]
src/asn1Parser.c [new file with mode: 0644]
src/pkix_asn1_tab.c [new file with mode: 0644]
tests/Makefile.am [new file with mode: 0644]
tests/Test_parser.c [new file with mode: 0644]
tests/Test_tree.asn [new file with mode: 0644]
tests/Test_tree.c [new file with mode: 0644]
tests/Test_tree_asn1_tab.c [new file with mode: 0644]

diff --git a/lib/ASN1.c b/lib/ASN1.c
new file mode 100644 (file)
index 0000000..ad07843
--- /dev/null
@@ -0,0 +1,2129 @@
+/* A Bison parser, made from ASN1.y
+   by GNU bison 1.33.  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+# define       ASSIG   257
+# define       NUM     258
+# define       IDENTIFIER      259
+# define       OPTIONAL        260
+# define       INTEGER 261
+# define       SIZE    262
+# define       OCTET   263
+# define       STRING  264
+# define       SEQUENCE        265
+# define       BIT     266
+# define       UNIVERSAL       267
+# define       PRIVATE 268
+# define       APPLICATION     269
+# define       DEFAULT 270
+# define       CHOICE  271
+# define       OF      272
+# define       OBJECT  273
+# define       STR_IDENTIFIER  274
+# define       BOOLEAN 275
+# define       TRUE    276
+# define       FALSE   277
+# define       TOKEN_NULL      278
+# define       ANY     279
+# define       DEFINED 280
+# define       BY      281
+# define       SET     282
+# define       EXPLICIT        283
+# define       IMPLICIT        284
+# define       DEFINITIONS     285
+# define       TAGS    286
+# define       BEGIN   287
+# define       END     288
+# define       UTCTime 289
+# define       GeneralizedTime 290
+# define       FROM    291
+# define       IMPORTS 292
+# define       ENUMERATED      293
+
+#line 29 "ASN1.y"
+#include <int.h> 
+#include <errors.h>
+#include <parser_aux.h>
+#include <structure.h>
+
+
+FILE *file_asn1;            /* Pointer to file to parse */
+asn1_retCode result_parse;  /* result of the parser algorithm */
+node_asn *p_tree;        /* pointer to the root of the structure 
+                            created by the parser*/     
+unsigned long lineNumber; /* line number describing the parser position 
+                             inside the file */
+char lastToken[MAX_NAME_SIZE+1];      /* last token find in the file to parse before the
+                                         'parse error' */ 
+char identifierMissing[MAX_NAME_SIZE+1]; /* identifier name not found */
+char *fileName;           /* file to parse */
+
+int yyerror (char *);
+int yylex(void);
+
+
+#line 53 "ASN1.y"
+#ifndef YYSTYPE
+typedef union {
+  unsigned int constant;
+  char str[MAX_NAME_SIZE+1];
+  node_asn* node;
+} yystype;
+# define YYSTYPE yystype
+#endif
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+
+
+#define        YYFINAL         180
+#define        YYFLAG          -32768
+#define        YYNTBASE        50
+
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 293 ? yytranslate[x] : 90)
+
+/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
+static const char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+      42,    43,     2,    40,    44,    41,    49,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    45,     2,    46,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    47,     2,    48,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39
+};
+
+#if YYDEBUG
+static const short yyprhs[] =
+{
+       0,     0,     9,    11,    14,    17,    19,    21,    23,    25,
+      27,    29,    33,    38,    40,    44,    46,    51,    53,    56,
+      58,    60,    62,    66,    71,    73,    76,    79,    82,    85,
+      88,    90,    95,   103,   105,   107,   109,   114,   122,   124,
+     128,   131,   135,   140,   142,   146,   149,   155,   160,   163,
+     165,   168,   170,   172,   174,   176,   178,   180,   182,   184,
+     186,   188,   190,   192,   194,   197,   199,   202,   205,   208,
+     210,   214,   219,   223,   228,   233,   237,   242,   247,   249,
+     254,   258,   266,   273,   278,   280,   282,   284,   287,   292,
+     296,   298
+};
+static const short yyrhs[] =
+{
+      88,    31,    89,    32,     3,    33,    87,    34,     0,     4,
+       0,    40,     4,     0,    41,     4,     0,    51,     0,    52,
+       0,     4,     0,     5,     0,    53,     0,     5,     0,    42,
+      53,    43,     0,     5,    42,    53,    43,     0,    56,     0,
+      57,    44,    56,     0,    54,     0,     5,    42,     4,    43,
+       0,    58,     0,    59,    58,     0,    13,     0,    14,     0,
+      15,     0,    45,     4,    46,     0,    45,    60,     4,    46,
+       0,    61,     0,    61,    29,     0,    61,    30,     0,    16,
+      55,     0,    16,    22,     0,    16,    23,     0,     7,     0,
+       7,    47,    57,    48,     0,    64,    42,    54,    49,    49,
+      54,    43,     0,    21,     0,    35,     0,    36,     0,     8,
+      42,    54,    43,     0,     8,    42,    54,    49,    49,    54,
+      43,     0,    67,     0,    42,    67,    43,     0,     9,    10,
+       0,     9,    10,    68,     0,     5,    42,     4,    43,     0,
+      70,     0,    71,    44,    70,     0,    12,    10,     0,    12,
+      10,    47,    71,    48,     0,    39,    47,    71,    48,     0,
+      19,    20,     0,     5,     0,     5,    68,     0,    64,     0,
+      73,     0,    65,     0,    66,     0,    69,     0,    72,     0,
+      80,     0,    74,     0,    82,     0,    83,     0,    81,     0,
+      24,     0,    75,     0,    62,    75,     0,    76,     0,    76,
+      63,     0,    76,     6,     0,     5,    77,     0,    78,     0,
+      79,    44,    78,     0,    11,    47,    79,    48,     0,    11,
+      18,    75,     0,    11,    68,    18,    75,     0,    28,    47,
+      79,    48,     0,    28,    18,    75,     0,    28,    68,    18,
+      75,     0,    17,    47,    79,    48,     0,    25,     0,    25,
+      26,    27,     5,     0,     5,     3,    76,     0,     5,    19,
+      20,     3,    47,    59,    48,     0,     5,     5,     3,    47,
+      59,    48,     0,     5,     7,     3,    53,     0,    84,     0,
+      85,     0,    86,     0,    87,    86,     0,     5,    47,    59,
+      48,     0,     5,    47,    48,     0,    29,     0,    30,     0
+};
+
+#endif
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,   113,   126,   127,   130,   134,   135,   138,   139,   142,
+     143,   146,   148,   153,   154,   158,   160,   165,   166,   170,
+     171,   172,   175,   177,   181,   182,   183,   186,   188,   189,
+     192,   193,   195,   202,   205,   206,   209,   211,   217,   218,
+     221,   222,   226,   231,   232,   236,   237,   242,   248,   251,
+     253,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   270,   271,   276,   277,   280,   283,   286,
+     287,   291,   293,   295,   300,   302,   304,   309,   313,   314,
+     319,   322,   326,   331,   337,   338,   341,   342,   346,   349,
+     373,   374
+};
+#endif
+
+
+#if (YYDEBUG) || defined YYERROR_VERBOSE
+
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
+static const char *const yytname[] =
+{
+  "$", "error", "$undefined.", "\"::=\"", "NUM", "IDENTIFIER", "OPTIONAL", 
+  "INTEGER", "SIZE", "OCTET", "STRING", "SEQUENCE", "BIT", "UNIVERSAL", 
+  "PRIVATE", "APPLICATION", "DEFAULT", "CHOICE", "OF", "OBJECT", 
+  "STR_IDENTIFIER", "BOOLEAN", "TRUE", "FALSE", "TOKEN_NULL", "ANY", 
+  "DEFINED", "BY", "SET", "EXPLICIT", "IMPLICIT", "DEFINITIONS", "TAGS", 
+  "BEGIN", "END", "UTCTime", "GeneralizedTime", "FROM", "IMPORTS", 
+  "ENUMERATED", "'+'", "'-'", "'('", "')'", "','", "'['", "']'", "'{'", 
+  "'}'", "'.'", "definitions", "pos_num", "neg_num", "pos_neg_num", 
+  "num_identifier", "pos_neg_identifier", "constant", "constant_list", 
+  "obj_constant", "obj_constant_list", "class", "tag_type", "tag", 
+  "default", "integer_def", "boolean_def", "Time", "size_def2", 
+  "size_def", "octet_string_def", "bit_element", "bit_element_list", 
+  "bit_string_def", "enumerated_def", "object_def", "type_assig_right", 
+  "type_assig_right_tag", "type_assig_right_tag_default", "type_assig", 
+  "type_assig_list", "sequence_def", "set_def", "choise_def", "any_def", 
+  "type_def", "constant_def", "type_constant", "type_constant_list", 
+  "definitions_id", "explicit_implicit", NULL
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    50,    51,    51,    52,    53,    53,    54,    54,    55,
+      55,    56,    56,    57,    57,    58,    58,    59,    59,    60,
+      60,    60,    61,    61,    62,    62,    62,    63,    63,    63,
+      64,    64,    64,    65,    66,    66,    67,    67,    68,    68,
+      69,    69,    70,    71,    71,    72,    72,    73,    74,    75,
+      75,    75,    75,    75,    75,    75,    75,    75,    75,    75,
+      75,    75,    75,    76,    76,    77,    77,    77,    78,    79,
+      79,    80,    80,    80,    81,    81,    81,    82,    83,    83,
+      84,    85,    85,    85,    86,    86,    87,    87,    88,    88,
+      89,    89
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     8,     1,     2,     2,     1,     1,     1,     1,     1,
+       1,     3,     4,     1,     3,     1,     4,     1,     2,     1,
+       1,     1,     3,     4,     1,     2,     2,     2,     2,     2,
+       1,     4,     7,     1,     1,     1,     4,     7,     1,     3,
+       2,     3,     4,     1,     3,     2,     5,     4,     2,     1,
+       2,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     2,     1,     2,     2,     2,     1,
+       3,     4,     3,     4,     4,     3,     4,     4,     1,     4,
+       3,     7,     6,     4,     1,     1,     1,     2,     4,     3,
+       1,     1
+};
+
+/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+   doesn't specify something else to do.  Zero means the default is an
+   error. */
+static const short yydefact[] =
+{
+       0,     0,     0,     0,     0,     7,     8,    89,    15,    17,
+       0,    90,    91,     0,     0,    88,    18,     0,     0,     0,
+      16,     0,     0,    84,    85,    86,     0,     0,     0,     0,
+       0,     1,    87,    49,    30,     0,     0,     0,     0,     0,
+      33,    62,    78,     0,    34,    35,     0,     0,    24,     0,
+      51,    53,    54,    55,    56,    52,    58,    63,    80,    57,
+      61,    59,    60,     0,     0,     0,     0,     0,    38,    50,
+       0,    40,     0,     0,     0,    45,     0,    48,     0,     0,
+       0,     0,     0,     0,    19,    20,    21,     0,    25,    26,
+      64,     0,     0,     2,     0,     0,     5,     6,    83,     0,
+       0,     0,     0,     0,    13,     0,    41,    72,     0,    69,
+       0,     0,     0,     0,     0,    75,     0,     0,     0,    43,
+       0,    22,     0,     8,     0,     0,     3,     4,     0,     0,
+      39,     0,     0,     0,    31,    65,    68,     0,    71,    73,
+       0,    77,    79,    74,    76,     0,     0,    47,    23,     0,
+      82,     0,    36,     0,     0,    11,    14,    67,     0,    66,
+      70,    46,     0,    44,     0,    81,     0,    12,    10,    28,
+      29,     9,    27,    42,     0,     0,    32,    37,     0,     0,
+       0
+};
+
+static const short yydefgoto[] =
+{
+     178,    96,    97,    98,     8,   172,   104,   105,     9,    10,
+      87,    48,    49,   159,    50,    51,    52,    68,    69,    53,
+     119,   120,    54,    55,    56,    57,    58,   136,   109,   110,
+      59,    60,    61,    62,    23,    24,    25,    26,     2,    13
+};
+
+static const short yypact[] =
+{
+      10,   -24,     9,     0,    91,-32768,    36,-32768,-32768,-32768,
+       2,-32768,-32768,    52,    42,-32768,-32768,   106,    82,    53,
+  -32768,   121,    14,-32768,-32768,-32768,    11,    32,   124,   125,
+     109,-32768,-32768,     5,    84,   120,    12,   122,    86,   114,
+  -32768,-32768,   110,    54,-32768,-32768,    88,    99,    94,    83,
+      95,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+  -32768,-32768,-32768,    92,    25,   135,    98,   134,-32768,-32768,
+      19,     5,    83,   138,   126,   100,   138,-32768,   118,    83,
+     138,   128,   143,   103,-32768,-32768,-32768,   146,-32768,-32768,
+  -32768,    30,   101,-32768,   147,   148,-32768,-32768,-32768,   107,
+      30,   112,   111,    25,-32768,   -30,-32768,-32768,    32,-32768,
+      -6,    83,   143,    35,   151,-32768,    41,    83,   115,-32768,
+      43,-32768,   113,-32768,   116,     4,-32768,-32768,   101,   -21,
+  -32768,    25,   117,    19,-32768,    20,-32768,   138,-32768,-32768,
+      49,-32768,-32768,-32768,-32768,   154,   143,-32768,-32768,   119,
+  -32768,     7,-32768,   123,   127,-32768,-32768,-32768,    76,-32768,
+  -32768,-32768,   130,-32768,    30,-32768,    30,-32768,-32768,-32768,
+  -32768,-32768,-32768,-32768,   131,   132,-32768,-32768,   161,   162,
+  -32768
+};
+
+static const short yypgoto[] =
+{
+  -32768,-32768,-32768,  -100,   -90,-32768,    31,-32768,   -10,   -65,
+  -32768,-32768,-32768,-32768,-32768,-32768,-32768,    96,    39,-32768,
+      21,    57,-32768,-32768,-32768,   -47,    58,-32768,    34,    -7,
+  -32768,-32768,-32768,-32768,-32768,-32768,   150,-32768,-32768,-32768
+};
+
+
+#define        YYLAST          176
+
+
+static const short yytable[] =
+{
+      16,   124,    90,   132,     5,     6,     5,     6,     5,     6,
+     129,     5,     6,    66,   133,     1,    22,    27,   134,    28,
+      66,    29,   152,     3,   102,   107,   157,   125,   153,    93,
+      72,   154,   115,    30,     5,   123,   158,    33,   137,    34,
+       4,    35,   138,    36,    37,    31,    18,    67,     7,    38,
+      15,    39,   150,    40,    67,   165,    41,    42,   171,    73,
+      43,   103,    66,   151,   139,    94,    95,    44,    45,   113,
+     144,    46,    79,   116,   174,    74,   175,    47,    14,   137,
+      93,   168,    81,   141,    17,   137,    21,   146,    33,   143,
+      34,   147,    35,   146,    36,    37,    67,   161,   169,   170,
+      38,    80,    39,    83,    40,     5,     6,    41,    42,    19,
+     106,    43,    84,    85,    86,    16,    94,    95,    44,    45,
+      11,    12,    46,    88,    89,    20,    22,    63,    64,    65,
+      71,    70,    75,    76,    77,    82,    78,    91,    99,    92,
+     100,    16,    66,   108,   111,   114,   117,   112,   118,   121,
+     122,   126,   127,   131,   128,   130,   142,   145,   162,   148,
+     155,   179,   180,   101,   156,   149,   135,   163,   164,   140,
+     167,   160,   166,   173,   176,   177,    32
+};
+
+static const short yycheck[] =
+{
+      10,    91,    49,   103,     4,     5,     4,     5,     4,     5,
+     100,     4,     5,     8,    44,     5,     5,     3,    48,     5,
+       8,     7,    43,    47,     5,    72,     6,    92,    49,     4,
+      18,   131,    79,    19,     4,     5,    16,     5,    44,     7,
+      31,     9,    48,    11,    12,    34,     4,    42,    48,    17,
+      48,    19,    48,    21,    42,    48,    24,    25,   158,    47,
+      28,    42,     8,   128,   111,    40,    41,    35,    36,    76,
+     117,    39,    18,    80,   164,    36,   166,    45,    42,    44,
+       4,     5,    43,    48,    32,    44,    33,    44,     5,    48,
+       7,    48,     9,    44,    11,    12,    42,    48,    22,    23,
+      17,    47,    19,     4,    21,     4,     5,    24,    25,     3,
+      71,    28,    13,    14,    15,   125,    40,    41,    35,    36,
+      29,    30,    39,    29,    30,    43,     5,     3,     3,    20,
+      10,    47,    10,    47,    20,    47,    26,    42,     3,    47,
+      42,   151,     8,     5,    18,    27,    18,    47,     5,    46,
+       4,     4,     4,    42,    47,    43,     5,    42,     4,    46,
+      43,     0,     0,    67,   133,    49,   108,   146,    49,   112,
+      43,   137,    49,    43,    43,    43,    26
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/local/share/bison/bison.simple"
+
+/* Skeleton output parser for bison,
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser when
+   the %semantic_parser declaration is not specified in the grammar.
+   It was written by Richard Stallman by simplifying the hairy parser
+   used when %semantic_parser is specified.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+#ifdef __cplusplus
+# define YYSTD(x) std::x
+#else
+# define YYSTD(x) x
+#endif
+
+#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  ifdef __cplusplus
+#   include <cstdlib> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T std::size_t
+#  else
+#   ifdef __STDC__
+#    include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#    define YYSIZE_T size_t
+#   endif
+#  endif
+#  define YYSTACK_ALLOC YYSTD (malloc)
+#  define YYSTACK_FREE YYSTD (free)
+# endif
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))     \
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Relocate the TYPE STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Type, Stack)                                 \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       yymemcpy ((char *) yyptr, (char *) (Stack),                     \
+                 yysize * (YYSIZE_T) sizeof (Type));                   \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (Type) + YYSTACK_GAP_MAX;     \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# ifdef __cplusplus
+#  include <cstddef> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T std::size_t
+# else
+#  ifdef __STDC__
+#   include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT        goto yyabortlab
+#define YYERROR                goto yyerrlab1
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL         goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");                        \
+      YYERROR;                                                 \
+    }                                                          \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
+
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)               \
+   Current.last_line   = Rhs[N].last_line;     \
+   Current.last_column = Rhs[N].last_column;
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX                 yylex ()
+#endif /* !YYPURE */
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  ifdef __cplusplus
+#   include <cstdio>  /* INFRINGES ON USER NAME SPACE */
+#  else
+#   include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  endif
+#  define YYFPRINTF YYSTD (fprintf)
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+/* Nonzero means print parse trace. [The following comment makes no
+   sense to me.  Could someone clarify it?  --akim] Since this is
+   uninitialized, it does not stop multiple parsers from coexisting.
+   */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+\f
+#if ! defined (yyoverflow) && ! defined (yymemcpy)
+# if __GNUC__ > 1              /* GNU C and GNU C++ define this.  */
+#  define yymemcpy __builtin_memcpy
+# else                         /* not GNU C or C++ */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+#  if defined (__STDC__) || defined (__cplusplus)
+yymemcpy (char *yyto, const char *yyfrom, YYSIZE_T yycount)
+#  else
+yymemcpy (yyto, yyfrom, yycount)
+     char *yyto;
+     const char *yyfrom;
+     YYSIZE_T yycount;
+#  endif
+{
+  register const char *yyf = yyfrom;
+  register char *yyt = yyto;
+  register YYSIZE_T yyi = yycount;
+
+  while (yyi-- != 0)
+    *yyt++ = *yyf++;
+}
+# endif
+#endif
+
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+#endif
+\f
+#line 341 "/usr/local/share/bison/bison.simple"
+
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# ifdef __cplusplus
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else /* !__cplusplus */
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif /* !__cplusplus */
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+/* YY_DECL_VARIABLES -- depending whether we use a pure parser,
+   variables are global, or local to YYPARSE.  */
+
+#define YY_DECL_NON_LSP_VARIABLES                      \
+/* The lookahead symbol.  */                           \
+int yychar;                                            \
+                                                       \
+/* The semantic value of the lookahead symbol. */      \
+YYSTYPE yylval;                                                \
+                                                       \
+/* Number of parse errors so far.  */                  \
+int yynerrs;
+
+#if YYLSP_NEEDED
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES                      \
+                                               \
+/* Location data for the lookahead symbol.  */ \
+YYLTYPE yylloc;
+#else
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES
+#endif
+
+
+/* If nonreentrant, generate the variables here. */
+
+#if !YYPURE
+YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  /* If reentrant, generate the variables here. */
+#if YYPURE
+  YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack. */
+  short        yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+#if YYLSP_NEEDED
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+#endif
+
+#if YYLSP_NEEDED
+# define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+# define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+#if YYLSP_NEEDED
+  YYLTYPE yyloc;
+#endif
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule. */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+#if YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack. Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       short *yyss1 = yyss;
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  */
+# if YYLSP_NEEDED
+       YYLTYPE *yyls1 = yyls;
+       /* This used to be a conditional around just the two extra args,
+          but that might be undefined if yyoverflow is a macro.  */
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
+                   &yystacksize);
+       yyls = yyls1;
+# else
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yystacksize);
+# endif
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+       goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       short *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (short, yyss);
+       YYSTACK_RELOCATE (YYSTYPE, yyvs);
+# if YYLSP_NEEDED
+       YYSTACK_RELOCATE (YYLTYPE, yyls);
+# endif
+# undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+#if YYLSP_NEEDED
+      yylsp = yyls + yysize - 1;
+#endif
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)             /* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+#if YYDEBUG
+     /* We have to keep this `#if YYDEBUG', since we use variables
+       which are defined only if `YYDEBUG' is set.  */
+      if (yydebug)
+       {
+         YYFPRINTF (stderr, "Next token is %d (%s",
+                    yychar, yytname[yychar1]);
+         /* Give the individual parser a way to print the precise
+            meaning of a token, for further debugging info.  */
+# ifdef YYPRINT
+         YYPRINT (stderr, yychar, yylval);
+# endif
+         YYFPRINTF (stderr, ")\n");
+       }
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+             yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to the semantic value of
+     the lookahead token.  This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+#if YYLSP_NEEDED
+  /* Similarly for the default location.  Let the user run additional
+     commands if for instance locations are ranges.  */
+  yyloc = yylsp[1-yylen];
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+#endif
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+                yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)
+       YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+  switch (yyn) {
+
+case 1:
+#line 116 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_DEFINITIONS|yyvsp[-5].constant);
+                    _asn1_set_name(yyval.node,_asn1_get_name(yyvsp[-7].node));
+                    _asn1_set_name(yyvsp[-7].node,"");
+                    _asn1_set_right(yyvsp[-7].node,yyvsp[-1].node);
+                    _asn1_set_down(yyval.node,yyvsp[-7].node);
+          
+                   p_tree=yyval.node;
+                   }
+    break;
+case 2:
+#line 126 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 3:
+#line 127 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 4:
+#line 130 "ASN1.y"
+{strcpy(yyval.str,"-");
+                       strcat(yyval.str,yyvsp[0].str);}
+    break;
+case 5:
+#line 134 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 6:
+#line 135 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 7:
+#line 138 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 8:
+#line 139 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 9:
+#line 142 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 10:
+#line 143 "ASN1.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 11:
+#line 146 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_CONSTANT); 
+                                       _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 12:
+#line 148 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_CONSTANT);
+                                      _asn1_set_name(yyval.node,yyvsp[-3].str); 
+                                       _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 13:
+#line 153 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 14:
+#line 154 "ASN1.y"
+{yyval.node=yyvsp[-2].node;
+                                            _asn1_set_right(_asn1_get_last_right(yyvsp[-2].node),yyvsp[0].node);}
+    break;
+case 15:
+#line 158 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_CONSTANT); 
+                                   _asn1_set_value(yyval.node,yyvsp[0].str,strlen(yyvsp[0].str)+1);}
+    break;
+case 16:
+#line 160 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_CONSTANT);
+                                   _asn1_set_name(yyval.node,yyvsp[-3].str); 
+                                    _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 17:
+#line 165 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 18:
+#line 166 "ASN1.y"
+{yyval.node=yyvsp[-1].node;
+                                                    _asn1_set_right(_asn1_get_last_right(yyvsp[-1].node),yyvsp[0].node);}
+    break;
+case 19:
+#line 170 "ASN1.y"
+{yyval.constant=CONST_UNIVERSAL;}
+    break;
+case 20:
+#line 171 "ASN1.y"
+{yyval.constant=CONST_PRIVATE;}
+    break;
+case 21:
+#line 172 "ASN1.y"
+{yyval.constant=CONST_APPLICATION;}
+    break;
+case 22:
+#line 175 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_TAG); 
+                            _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 23:
+#line 177 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_TAG | yyvsp[-2].constant); 
+                                _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 24:
+#line 181 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 25:
+#line 182 "ASN1.y"
+{yyval.node=_asn1_mod_type(yyvsp[-1].node,CONST_EXPLICIT);}
+    break;
+case 26:
+#line 183 "ASN1.y"
+{yyval.node=_asn1_mod_type(yyvsp[-1].node,CONST_IMPLICIT);}
+    break;
+case 27:
+#line 186 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_DEFAULT); 
+                                       _asn1_set_value(yyval.node,yyvsp[0].str,strlen(yyvsp[0].str)+1);}
+    break;
+case 28:
+#line 188 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);}
+    break;
+case 29:
+#line 189 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);}
+    break;
+case 30:
+#line 192 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_INTEGER);}
+    break;
+case 31:
+#line 193 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_INTEGER|CONST_LIST);
+                                        _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 32:
+#line 196 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_INTEGER|CONST_MIN_MAX);
+                                         _asn1_set_down(yyval.node,_asn1_add_node(TYPE_SIZE)); 
+                                         _asn1_set_value(_asn1_get_down(yyval.node),yyvsp[-1].str,strlen(yyvsp[-1].str)+1); 
+                                         _asn1_set_name(_asn1_get_down(yyval.node),yyvsp[-4].str);}
+    break;
+case 33:
+#line 202 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_BOOLEAN);}
+    break;
+case 34:
+#line 205 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_TIME|CONST_UTC);}
+    break;
+case 35:
+#line 206 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);}
+    break;
+case 36:
+#line 209 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SIZE|CONST_1_PARAM);
+                                     _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 37:
+#line 212 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SIZE|CONST_MIN_MAX);
+                                     _asn1_set_value(yyval.node,yyvsp[-4].str,strlen(yyvsp[-4].str)+1);
+                                      _asn1_set_name(yyval.node,yyvsp[-1].str);}
+    break;
+case 38:
+#line 217 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 39:
+#line 218 "ASN1.y"
+{yyval.node=yyvsp[-1].node;}
+    break;
+case 40:
+#line 221 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_OCTET_STRING);}
+    break;
+case 41:
+#line 222 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE);
+                                           _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 42:
+#line 226 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_CONSTANT);
+                                  _asn1_set_name(yyval.node,yyvsp[-3].str); 
+                                    _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 43:
+#line 231 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 44:
+#line 232 "ASN1.y"
+{yyval.node=yyvsp[-2].node;
+                                                       _asn1_set_right(_asn1_get_last_right(yyvsp[-2].node),yyvsp[0].node);}
+    break;
+case 45:
+#line 236 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_BIT_STRING);}
+    break;
+case 46:
+#line 238 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST);
+                                _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 47:
+#line 243 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST);
+                                _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 48:
+#line 248 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_OBJECT_ID);}
+    break;
+case 49:
+#line 251 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_IDENTIFIER);
+                                       _asn1_set_value(yyval.node,yyvsp[0].str,strlen(yyvsp[0].str)+1);}
+    break;
+case 50:
+#line 253 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_IDENTIFIER|CONST_SIZE);
+                                       _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);
+                                       _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 51:
+#line 256 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 52:
+#line 257 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 53:
+#line 258 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 55:
+#line 260 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 56:
+#line 261 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 57:
+#line 262 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 58:
+#line 263 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 59:
+#line 264 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 60:
+#line 265 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 61:
+#line 266 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 62:
+#line 267 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_NULL);}
+    break;
+case 63:
+#line 270 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 64:
+#line 271 "ASN1.y"
+{yyval.node=_asn1_mod_type(yyvsp[0].node,CONST_TAG);
+                                               _asn1_set_right(yyvsp[-1].node,_asn1_get_down(yyval.node));
+                                               _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 65:
+#line 276 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 66:
+#line 277 "ASN1.y"
+{yyval.node=_asn1_mod_type(yyvsp[-1].node,CONST_DEFAULT);
+                                                       _asn1_set_right(yyvsp[0].node,_asn1_get_down(yyval.node));
+                                                      _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 67:
+#line 280 "ASN1.y"
+{yyval.node=_asn1_mod_type(yyvsp[-1].node,CONST_OPTION);}
+    break;
+case 68:
+#line 283 "ASN1.y"
+{yyval.node=_asn1_set_name(yyvsp[0].node,yyvsp[-1].str);}
+    break;
+case 69:
+#line 286 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 70:
+#line 287 "ASN1.y"
+{yyval.node=yyvsp[-2].node;
+                                                _asn1_set_right(_asn1_get_last_right(yyvsp[-2].node),yyvsp[0].node);}
+    break;
+case 71:
+#line 291 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SEQUENCE);
+                                              _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 72:
+#line 293 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SEQUENCE_OF);
+                                              _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 73:
+#line 295 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SEQUENCE_OF|CONST_SIZE);
+                                            _asn1_set_right(yyvsp[-2].node,yyvsp[0].node);
+                                            _asn1_set_down(yyval.node,yyvsp[-2].node);}
+    break;
+case 74:
+#line 300 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SET);
+                                     _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 75:
+#line 302 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SET_OF);
+                                     _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 76:
+#line 304 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_SET_OF|CONST_SIZE);
+                                       _asn1_set_right(yyvsp[-2].node,yyvsp[0].node);
+                                       _asn1_set_down(yyval.node,yyvsp[-2].node);}
+    break;
+case 77:
+#line 309 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_CHOICE);
+                                             _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 78:
+#line 313 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_ANY);}
+    break;
+case 79:
+#line 314 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_ANY|CONST_DEFINED_BY);
+                                        _asn1_set_down(yyval.node,_asn1_add_node(TYPE_CONSTANT));
+                                       _asn1_set_name(_asn1_get_down(yyval.node),yyvsp[0].str);}
+    break;
+case 80:
+#line 319 "ASN1.y"
+{yyval.node=_asn1_set_name(yyvsp[0].node,yyvsp[-2].str);}
+    break;
+case 81:
+#line 323 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN);
+                         _asn1_set_name(yyval.node,yyvsp[-6].str);  
+                         _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 82:
+#line 327 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
+                         _asn1_set_name(yyval.node,yyvsp[-5].str);  
+                         _asn1_set_value(yyval.node,yyvsp[-4].str,strlen(yyvsp[-4].str)+1);
+                         _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 83:
+#line 332 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_INTEGER|CONST_ASSIGN);
+                         _asn1_set_name(yyval.node,yyvsp[-3].str);  
+                         _asn1_set_value(yyval.node,yyvsp[0].str,strlen(yyvsp[0].str)+1);}
+    break;
+case 84:
+#line 337 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 85:
+#line 338 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 86:
+#line 341 "ASN1.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 87:
+#line 342 "ASN1.y"
+{yyval.node=yyvsp[-1].node;
+                                                          _asn1_set_right(_asn1_get_last_right(yyvsp[-1].node),yyvsp[0].node);}
+    break;
+case 88:
+#line 346 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_OBJECT_ID);
+                                                          _asn1_set_down(yyval.node,yyvsp[-1].node);
+                                                          _asn1_set_name(yyval.node,yyvsp[-3].str);}
+    break;
+case 89:
+#line 349 "ASN1.y"
+{yyval.node=_asn1_add_node(TYPE_OBJECT_ID);
+                                                          _asn1_set_name(yyval.node,yyvsp[-2].str);}
+    break;
+case 90:
+#line 373 "ASN1.y"
+{yyval.constant=CONST_EXPLICIT;}
+    break;
+case 91:
+#line 374 "ASN1.y"
+{yyval.constant=CONST_IMPLICIT;}
+    break;
+}
+
+#line 727 "/usr/local/share/bison/bison.simple"
+
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#if YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
+#endif
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+       {
+         YYSIZE_T yysize = 0;
+         char *yymsg;
+         int yyx, yycount;
+
+         yycount = 0;
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         for (yyx = yyn < 0 ? -yyn : 0;
+              yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+           if (yycheck[yyx + yyn] == yyx)
+             yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+         yysize += yystrlen ("parse error, unexpected ") + 1;
+         yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
+           {
+             char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
+
+             if (yycount < 5)
+               {
+                 yycount = 0;
+                 for (yyx = yyn < 0 ? -yyn : 0;
+                      yyx < (int) (sizeof (yytname) / sizeof (char *));
+                      yyx++)
+                   if (yycheck[yyx + yyn] == yyx)
+                     {
+                       const char *yyq = ! yycount ? ", expecting " : " or ";
+                       yyp = yystpcpy (yyp, yyq);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yycount++;
+                     }
+               }
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exhausted");
+       }
+      else
+#endif /* defined (YYERROR_VERBOSE) */
+       yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+       YYABORT;
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+                 yychar, yytname[yychar1]));
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;             /* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
+#endif
+
+
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#if YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
+yyerrhandle:
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+#line 378 "ASN1.y"
+
+
+
+
+const char *key_word[]={"::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING"
+                       ,"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL"
+                       ,"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER"
+                       ,"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED"
+                       ,"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS"
+                       ,"BEGIN","END","UTCTime","GeneralizedTime","FROM"
+                       ,"IMPORTS","NULL","ENUMERATED"};
+const int key_word_token[]={ASSIG,OPTIONAL,INTEGER,SIZE,OCTET,STRING
+                       ,SEQUENCE,BIT,UNIVERSAL,PRIVATE,OPTIONAL
+                       ,DEFAULT,CHOICE,OF,OBJECT,STR_IDENTIFIER
+                       ,BOOLEAN,TRUE,FALSE,APPLICATION,ANY,DEFINED
+                       ,SET,BY,EXPLICIT,IMPLICIT,DEFINITIONS,TAGS
+                       ,BEGIN,END,UTCTime,GeneralizedTime,FROM
+                       ,IMPORTS,TOKEN_NULL,ENUMERATED};
+
+/*************************************************************/
+/*  Function: yylex                                          */
+/*  Description: looks for tokens in file_asn1 pointer file. */
+/*  Return: int                                              */
+/*    Token identifier or ASCII code or 0(zero: End Of File) */
+/*************************************************************/
+int 
+yylex() 
+{
+  int c,counter=0,k;
+  char string[MAX_NAME_SIZE+1]; /* will contain the next token */  
+
+  while(1)
+    {
+    while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n')
+      if(c=='\n') lineNumber++;
+
+    if(c==EOF){
+      strcpy(lastToken,"End Of File");
+      return 0;
+    }
+
+    if(c=='(' || c==')' || c=='[' || c==']' || 
+       c=='{' || c=='}' || c==',' || c=='.' ||
+       c=='+'){
+      lastToken[0]=c;lastToken[1]=0;
+      return c;
+    }
+    if(c=='-'){  /* Maybe the first '-' of a comment */
+      if((c=fgetc(file_asn1))!='-'){
+       ungetc(c,file_asn1);
+       lastToken[0]='-';lastToken[1]=0;
+       return '-';
+      }
+      else{ /* Comments */
+       counter=0;
+       /* A comment finishes at the end of line */
+       while((c=fgetc(file_asn1))!=EOF && c!='\n');
+       if(c==EOF){
+         strcpy(lastToken,"End Of File");
+         return 0;
+       }
+       else{
+         lineNumber++;
+         continue; /* next char, please! (repeat the search) */
+       }
+      }
+    }
+    string[counter++]=c;
+    /* Till the end of the token */
+    while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' || 
+            c=='(' || c==')' || c=='[' || c==']' || 
+            c=='{' || c=='}' || c==',' || c=='.'))
+      {
+       if(counter>=MAX_NAME_SIZE){
+         result_parse=ASN1_NAME_TOO_LONG;
+         return 0;
+       }
+       string[counter++]=c;
+      }
+    ungetc(c,file_asn1);
+    string[counter]=0;
+    strcpy(lastToken,string);
+
+    /* Is STRING a number? */
+    for(k=0;k<counter;k++) 
+      if(!isdigit(string[k])) break;
+    if(k>=counter)
+      {
+      strcpy(yylval.str,string);  
+      return NUM; /* return the number */
+      }
+    /* Is STRING a keyword? */
+    for(k=0;k<(sizeof(key_word)/sizeof(char*));k++)  
+      if(!strcmp(string,key_word[k])) return key_word_token[k]; 
+    /* STRING is an IDENTIFIER */
+    strcpy(yylval.str,string);
+    return IDENTIFIER;
+    }
+}
+
+
+/*************************************************************/
+/*  Function: _asn1_create_errorDescription                  */
+/*  Description: creates a string with the description of the*/
+/*    error.                                                 */
+/*  Parameters:                                              */
+/*    error : error to describe.                             */
+/*    errorDescription: string that will contain the         */
+/*                      description.                         */
+/*************************************************************/
+void
+_asn1_create_errorDescription(int error,char *errorDescription)
+{
+  switch(error){
+  case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND: 
+    errorDescription[0]=0;
+    break;
+  case ASN1_SYNTAX_ERROR:
+    strcpy(errorDescription,fileName);
+    strcat(errorDescription,":");
+    _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+    strcat(errorDescription,": parse error near '");
+    strcat(errorDescription,lastToken);
+    strcat(errorDescription,"'");
+    break;
+  case ASN1_NAME_TOO_LONG:
+    strcpy(errorDescription,fileName);
+    strcat(errorDescription,":");
+    _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+    strcat(errorDescription,": name too long (more than ");
+    _asn1_ltostr(MAX_NAME_SIZE,errorDescription+strlen(errorDescription));
+    strcat(errorDescription," characters)");
+    break;
+  case ASN1_IDENTIFIER_NOT_FOUND:
+    strcpy(errorDescription,fileName);
+    strcat(errorDescription,":");
+    strcat(errorDescription,": identifier '");
+    strcat(errorDescription,identifierMissing);
+    strcat(errorDescription,"' not found");
+    break;
+  default:
+    errorDescription[0]=0;
+    break;
+  }
+
+}
+
+
+/**
+  * asn1_parser2tree - function used to start the parse algorithm.
+  * @file_name: specify the path and the name of file that contains ASN.1 declarations.
+  * @definitions: return the pointer to the structure created from 
+  *   "file_name" ASN.1 declarations.  
+  * @errorDescription : return the error description or an empty string if success.
+  * Description:
+  *
+  * Creates the structures needed to manage the definitions included in *FILE_NAME file.
+  *
+  * Returns:
+  *
+  * ASN1_SUCCESS\: the file has a correct syntax and every identifier is known.
+  *
+  * ASN1_ELEMENT_NOT_EMPTY\: *POINTER not ASN1_TYPE_EMPTY.
+  *
+  * ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  * ASN1_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  * ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters.
+  **/
+asn1_retCode
+asn1_parser2tree(char *file_name,ASN1_TYPE *definitions,char *errorDescription){
+
+  p_tree=ASN1_TYPE_EMPTY;
+
+  if(*definitions != ASN1_TYPE_EMPTY)
+    return ASN1_ELEMENT_NOT_EMPTY;
+
+  *definitions=ASN1_TYPE_EMPTY;
+
+  fileName = file_name;
+
+  /* open the file to parse */
+  file_asn1=fopen(file_name,"r");
+
+  if(file_asn1==NULL){
+    result_parse=ASN1_FILE_NOT_FOUND;
+  }
+  else{
+    result_parse=ASN1_SUCCESS;
+
+    lineNumber=1;
+    yyparse();
+
+    fclose(file_asn1);
+    
+    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+      /* set IMPLICIT or EXPLICIT property */
+      _asn1_set_default_tag(p_tree);
+      /* set CONST_SET and CONST_NOT_USED */
+      _asn1_type_set_config(p_tree);
+      /* check the identifier definitions */
+      result_parse=_asn1_check_identifier(p_tree);
+      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+       /* Delete the list and keep the ASN1 structure */
+       _asn1_delete_list();
+       /* Convert into DER coding the value assign to INTEGER constants */
+       _asn1_change_integer_value(p_tree);
+       /* Expand the IDs of OBJECT IDENTIFIER constants */
+       _asn1_expand_object_id(p_tree);
+
+       *definitions=p_tree;
+      }
+      else /* some identifiers not defined */ 
+       /* Delete the list and the ASN1 structure */
+       _asn1_delete_list_and_nodes();
+    }
+    else  /* syntax error */
+      /* Delete the list and the ASN1 structure */
+      _asn1_delete_list_and_nodes();
+  }
+
+  _asn1_create_errorDescription(result_parse,errorDescription);
+
+  return result_parse;
+}
+
+
+/**
+  * asn1_parser2array - function that generates a C structure from an ASN1 file
+  * @inputFileName: specify the path and the name of file that contains ASN.1 declarations.
+  * @outputFileName: specify the path and the name of file that will contain the C vector definition.
+  * @vectorName: specify the name of the C vector.
+  * @errorDescription : return the error description or an empty string if success.
+  * Description:
+  *
+  * Creates a file containing a C vector to use to manage the definitions included in
+  * *INPUTFILENAME file. If *INPUTFILENAME is "/aa/bb/xx.yy" and OUTPUTFILENAME is NULL, the file created is "/aa/bb/xx_asn1_tab.c".
+  * If VECTORNAME is NULL the vector name will be "xx_asn1_tab".
+  *
+  * Returns:
+  *
+  *  ASN1_SUCCESS\: the file has a correct syntax and every identifier is known. 
+  *
+  *  ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  *  ASN1_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  *  ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  *  ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters.
+  **/
+int asn1_parser2array(char *inputFileName,char *outputFileName,char *vectorName,char *errorDescription){
+  char *file_out_name=NULL;
+  char *vector_name=NULL;
+  char *char_p,*slash_p,*dot_p;
+
+  p_tree=NULL;
+
+  fileName = inputFileName;
+    
+  /* open the file to parse */
+  file_asn1=fopen(inputFileName,"r");
+
+  if(file_asn1==NULL)
+    result_parse=ASN1_FILE_NOT_FOUND;
+  else{
+    result_parse=ASN1_SUCCESS;
+
+    lineNumber=1;
+    yyparse();
+
+    fclose(file_asn1);
+
+    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+      /* set IMPLICIT or EXPLICIT property */
+      _asn1_set_default_tag(p_tree);
+      /* set CONST_SET and CONST_NOT_USED */
+      _asn1_type_set_config(p_tree);
+      /* check the identifier definitions */
+      result_parse=_asn1_check_identifier(p_tree);
+
+      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+
+       /* searching the last '/' and '.' in inputFileName */
+       char_p=inputFileName;
+       slash_p=inputFileName;
+       while((char_p=strchr(char_p,'/'))){
+         char_p++;
+         slash_p=char_p;
+       }
+
+       char_p=slash_p;
+       dot_p=inputFileName+strlen(inputFileName);
+       
+       while((char_p=strchr(char_p,'.'))){
+         dot_p=char_p;
+         char_p++;
+       }
+
+       if(outputFileName == NULL){ 
+         /* file_out_name = inputFileName + _asn1_tab.c */
+         file_out_name=(char *)malloc(dot_p-inputFileName+1+
+                                       strlen("_asn1_tab.c"));
+         memcpy(file_out_name,inputFileName,dot_p-inputFileName);
+         file_out_name[dot_p-inputFileName]=0;
+         strcat(file_out_name,"_asn1_tab.c");
+       }
+       else{
+         /* file_out_name = inputFileName */
+         file_out_name=(char *)malloc(strlen(outputFileName)+1);
+         strcpy(file_out_name,outputFileName);
+       }
+
+       if(vectorName == NULL){ 
+         /* vector_name = file name + _asn1_tab */
+         vector_name=(char *)malloc(dot_p-slash_p+1+
+                                       strlen("_asn1_tab"));
+         memcpy(vector_name,slash_p,dot_p-slash_p);
+         vector_name[dot_p-slash_p]=0;
+         strcat(vector_name,"_asn1_tab");
+       }
+       else{
+         /* vector_name = vectorName */
+         vector_name=(char *)malloc(strlen(vectorName)+1);
+         strcpy(vector_name,vectorName);
+       }
+
+       /* Save structure in a file */
+       _asn1_create_static_structure(p_tree,
+                  file_out_name,vector_name);
+
+       free(file_out_name);
+       free(vector_name);
+      } /* result == OK */
+    }   /* result == OK */
+     
+    /* Delete the list and the ASN1 structure */
+    _asn1_delete_list_and_nodes();    
+  } /* inputFile exist */
+
+  _asn1_create_errorDescription(result_parse,errorDescription);
+
+  return result_parse;
+}
+
+
+/*************************************************************/
+/*  Function: yyerror                                        */
+/*  Description: function called when there are syntax errors*/
+/*  Parameters:                                              */
+/*    char *s : error description                            */
+/*  Return: int                                              */
+/*                                                           */
+/*************************************************************/
+int yyerror (char *s)
+{
+  /* Sends the error description to the std_out */
+
+#ifdef DEBUG_PARSER
+  _libasn1_log("yyerror:%s:%d: %s (Last Token:'%s')\n",fileName,
+               lineNumber,s,lastToken); 
+#endif
+
+  if(result_parse!=ASN1_NAME_TOO_LONG) 
+    result_parse=ASN1_SYNTAX_ERROR;
+
+  return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ASN1.y b/lib/ASN1.y
new file mode 100644 (file)
index 0000000..4f10868
--- /dev/null
@@ -0,0 +1,763 @@
+/*           Copyright (C) 2001, 2002  Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: x509_ASN.y                                  */
+/* Description: input file for 'bison' program.      */
+/*   The output file is a parser (in C language) for */
+/*   ASN.1 syntax                                    */
+/*****************************************************/
+
+%{ 
+#include <int.h> 
+#include <errors.h>
+#include <parser_aux.h>
+#include <structure.h>
+
+
+FILE *file_asn1;            /* Pointer to file to parse */
+asn1_retCode result_parse;  /* result of the parser algorithm */
+node_asn *p_tree;        /* pointer to the root of the structure 
+                            created by the parser*/     
+unsigned long lineNumber; /* line number describing the parser position 
+                             inside the file */
+char lastToken[MAX_NAME_SIZE+1];      /* last token find in the file to parse before the
+                                         'parse error' */ 
+char identifierMissing[MAX_NAME_SIZE+1]; /* identifier name not found */
+char *fileName;           /* file to parse */
+
+int yyerror (char *);
+int yylex(void);
+
+%}
+
+
+%union {
+  unsigned int constant;
+  char str[MAX_NAME_SIZE+1];
+  node_asn* node;
+}
+
+
+%token ASSIG "::=" 
+%token <str> NUM
+%token <str> IDENTIFIER
+%token OPTIONAL
+%token INTEGER
+%token SIZE
+%token OCTET
+%token STRING
+%token SEQUENCE
+%token BIT
+%token UNIVERSAL
+%token PRIVATE
+%token APPLICATION
+%token OPTIONAL
+%token DEFAULT
+%token CHOICE
+%token OF
+%token OBJECT
+%token STR_IDENTIFIER
+%token BOOLEAN
+%token TRUE
+%token FALSE
+%token TOKEN_NULL
+%token ANY
+%token DEFINED
+%token BY
+%token SET
+%token EXPLICIT
+%token IMPLICIT
+%token DEFINITIONS
+%token TAGS
+%token BEGIN
+%token END
+%token UTCTime 
+%token GeneralizedTime
+%token FROM
+%token IMPORTS
+%token ENUMERATED
+
+%type <node> octet_string_def constant constant_list type_assig_right 
+%type <node> integer_def type_assig type_assig_list sequence_def type_def
+%type <node> bit_string_def default size_def choise_def object_def 
+%type <node> boolean_def any_def size_def2 obj_constant obj_constant_list
+%type <node> constant_def type_constant type_constant_list definitions
+%type <node> definitions_id Time bit_element bit_element_list set_def
+%type <node> tag_type tag type_assig_right_tag
+%type <node> type_assig_right_tag_default enumerated_def
+%type <str>  pos_num neg_num pos_neg_num pos_neg_identifier num_identifier 
+%type <constant> class explicit_implicit
+
+%%
+
+
+definitions:   definitions_id
+               DEFINITIONS explicit_implicit TAGS "::=" BEGIN  /* imports_def */
+               type_constant_list END
+                   {$$=_asn1_add_node(TYPE_DEFINITIONS|$3);
+                    _asn1_set_name($$,_asn1_get_name($1));
+                    _asn1_set_name($1,"");
+                    _asn1_set_right($1,$7);
+                    _asn1_set_down($$,$1);
+          
+                   p_tree=$$;
+                   }
+;
+
+pos_num :   NUM       {strcpy($$,$1);}
+          | '+' NUM   {strcpy($$,$2);}
+;
+
+neg_num : '-' NUM     {strcpy($$,"-");
+                       strcat($$,$2);}
+;
+
+pos_neg_num :  pos_num  {strcpy($$,$1);}
+             | neg_num  {strcpy($$,$1);}
+;
+
+num_identifier :  NUM            {strcpy($$,$1);}
+                | IDENTIFIER     {strcpy($$,$1);}
+;
+
+pos_neg_identifier :  pos_neg_num    {strcpy($$,$1);}
+                    | IDENTIFIER     {strcpy($$,$1);}
+;
+
+constant: '(' pos_neg_num ')'         {$$=_asn1_add_node(TYPE_CONSTANT); 
+                                       _asn1_set_value($$,$2,strlen($2)+1);}
+        | IDENTIFIER'('pos_neg_num')' {$$=_asn1_add_node(TYPE_CONSTANT);
+                                      _asn1_set_name($$,$1); 
+                                       _asn1_set_value($$,$3,strlen($3)+1);}
+;
+
+constant_list:  constant                   {$$=$1;}
+              | constant_list ',' constant {$$=$1;
+                                            _asn1_set_right(_asn1_get_last_right($1),$3);}
+;
+
+obj_constant:  num_identifier     {$$=_asn1_add_node(TYPE_CONSTANT); 
+                                   _asn1_set_value($$,$1,strlen($1)+1);}
+             | IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT);
+                                   _asn1_set_name($$,$1); 
+                                    _asn1_set_value($$,$3,strlen($3)+1);}
+;
+
+obj_constant_list:  obj_constant                   {$$=$1;}
+                  | obj_constant_list obj_constant {$$=$1;
+                                                    _asn1_set_right(_asn1_get_last_right($1),$2);}
+;
+
+class :  UNIVERSAL    {$$=CONST_UNIVERSAL;}
+       | PRIVATE      {$$=CONST_PRIVATE;}
+       | APPLICATION  {$$=CONST_APPLICATION;}
+;
+
+tag_type :  '[' NUM ']'    {$$=_asn1_add_node(TYPE_TAG); 
+                            _asn1_set_value($$,$2,strlen($2)+1);}
+          | '[' class NUM ']'  {$$=_asn1_add_node(TYPE_TAG | $2); 
+                                _asn1_set_value($$,$3,strlen($3)+1);}
+;
+
+tag :  tag_type           {$$=$1;}
+     | tag_type EXPLICIT  {$$=_asn1_mod_type($1,CONST_EXPLICIT);}
+     | tag_type IMPLICIT  {$$=_asn1_mod_type($1,CONST_IMPLICIT);}
+;
+
+default :  DEFAULT pos_neg_identifier {$$=_asn1_add_node(TYPE_DEFAULT); 
+                                       _asn1_set_value($$,$2,strlen($2)+1);}
+         | DEFAULT TRUE           {$$=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);}
+         | DEFAULT FALSE          {$$=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);}
+;
+
+integer_def: INTEGER                    {$$=_asn1_add_node(TYPE_INTEGER);}
+           | INTEGER'{'constant_list'}' {$$=_asn1_add_node(TYPE_INTEGER|CONST_LIST);
+                                        _asn1_set_down($$,$3);}
+           | integer_def'('num_identifier'.''.'num_identifier')'
+                                        {$$=_asn1_add_node(TYPE_INTEGER|CONST_MIN_MAX);
+                                         _asn1_set_down($$,_asn1_add_node(TYPE_SIZE)); 
+                                         _asn1_set_value(_asn1_get_down($$),$6,strlen($6)+1); 
+                                         _asn1_set_name(_asn1_get_down($$),$3);}
+;
+
+boolean_def: BOOLEAN   {$$=_asn1_add_node(TYPE_BOOLEAN);}
+;
+
+Time:   UTCTime          {$$=_asn1_add_node(TYPE_TIME|CONST_UTC);} 
+      | GeneralizedTime  {$$=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);} 
+;
+
+size_def2: SIZE'('num_identifier')'  {$$=_asn1_add_node(TYPE_SIZE|CONST_1_PARAM);
+                                     _asn1_set_value($$,$3,strlen($3)+1);}
+        | SIZE'('num_identifier'.''.'num_identifier')'  
+                                     {$$=_asn1_add_node(TYPE_SIZE|CONST_MIN_MAX);
+                                     _asn1_set_value($$,$3,strlen($3)+1);
+                                      _asn1_set_name($$,$6);}
+;
+
+size_def:   size_def2          {$$=$1;}
+          | '(' size_def2 ')'  {$$=$2;}
+;
+
+octet_string_def : OCTET STRING           {$$=_asn1_add_node(TYPE_OCTET_STRING);}
+                 | OCTET STRING size_def  {$$=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE);
+                                           _asn1_set_down($$,$3);}
+;
+
+bit_element :  IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT);
+                                  _asn1_set_name($$,$1); 
+                                    _asn1_set_value($$,$3,strlen($3)+1);}
+;
+
+bit_element_list :  bit_element   {$$=$1;}
+                  | bit_element_list ',' bit_element  {$$=$1;
+                                                       _asn1_set_right(_asn1_get_last_right($1),$3);}
+;
+
+bit_string_def : BIT STRING    {$$=_asn1_add_node(TYPE_BIT_STRING);}
+               | BIT STRING'{'bit_element_list'}' 
+                               {$$=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST);
+                                _asn1_set_down($$,$4);}
+;
+
+enumerated_def : ENUMERATED'{'bit_element_list'}' 
+                               {$$=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST);
+                                _asn1_set_down($$,$3);}
+;
+
+
+object_def :  OBJECT STR_IDENTIFIER {$$=_asn1_add_node(TYPE_OBJECT_ID);}
+;
+
+type_assig_right: IDENTIFIER          {$$=_asn1_add_node(TYPE_IDENTIFIER);
+                                       _asn1_set_value($$,$1,strlen($1)+1);}
+                | IDENTIFIER size_def {$$=_asn1_add_node(TYPE_IDENTIFIER|CONST_SIZE);
+                                       _asn1_set_value($$,$1,strlen($1)+1);
+                                       _asn1_set_down($$,$2);}
+                | integer_def         {$$=$1;}
+                | enumerated_def      {$$=$1;}
+                | boolean_def         {$$=$1;}
+                | Time             
+                | octet_string_def    {$$=$1;}
+                | bit_string_def      {$$=$1;}
+                | sequence_def        {$$=$1;}
+                | object_def          {$$=$1;}
+                | choise_def          {$$=$1;}
+                | any_def             {$$=$1;} 
+                | set_def             {$$=$1;}
+                | TOKEN_NULL          {$$=_asn1_add_node(TYPE_NULL);}
+;
+
+type_assig_right_tag :   type_assig_right     {$$=$1;}
+                       | tag type_assig_right {$$=_asn1_mod_type($2,CONST_TAG);
+                                               _asn1_set_right($1,_asn1_get_down($$));
+                                               _asn1_set_down($$,$1);}
+;
+
+type_assig_right_tag_default : type_assig_right_tag   {$$=$1;}
+                      | type_assig_right_tag default  {$$=_asn1_mod_type($1,CONST_DEFAULT);
+                                                       _asn1_set_right($2,_asn1_get_down($$));
+                                                      _asn1_set_down($$,$2);}
+                      | type_assig_right_tag OPTIONAL {$$=_asn1_mod_type($1,CONST_OPTION);}
+;
+type_assig : IDENTIFIER type_assig_right_tag_default  {$$=_asn1_set_name($2,$1);}
+;
+
+type_assig_list : type_assig                   {$$=$1;}
+                | type_assig_list','type_assig {$$=$1;
+                                                _asn1_set_right(_asn1_get_last_right($1),$3);}
+;
+
+sequence_def : SEQUENCE'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SEQUENCE);
+                                              _asn1_set_down($$,$3);}
+   | SEQUENCE OF type_assig_right            {$$=_asn1_add_node(TYPE_SEQUENCE_OF);
+                                              _asn1_set_down($$,$3);}
+   | SEQUENCE size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SEQUENCE_OF|CONST_SIZE);
+                                            _asn1_set_right($2,$4);
+                                            _asn1_set_down($$,$2);}
+; 
+
+set_def :  SET'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SET);
+                                     _asn1_set_down($$,$3);}
+   | SET OF type_assig_right        {$$=_asn1_add_node(TYPE_SET_OF);
+                                     _asn1_set_down($$,$3);}
+   | SET size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SET_OF|CONST_SIZE);
+                                       _asn1_set_right($2,$4);
+                                       _asn1_set_down($$,$2);}
+; 
+
+choise_def :   CHOICE'{'type_assig_list'}'  {$$=_asn1_add_node(TYPE_CHOICE);
+                                             _asn1_set_down($$,$3);}
+;
+
+any_def :  ANY                         {$$=_asn1_add_node(TYPE_ANY);}
+         | ANY DEFINED BY IDENTIFIER   {$$=_asn1_add_node(TYPE_ANY|CONST_DEFINED_BY);
+                                        _asn1_set_down($$,_asn1_add_node(TYPE_CONSTANT));
+                                       _asn1_set_name(_asn1_get_down($$),$4);}
+;
+
+type_def : IDENTIFIER "::=" type_assig_right_tag  {$$=_asn1_set_name($3,$1);}
+;
+
+constant_def :  IDENTIFIER OBJECT STR_IDENTIFIER "::=" '{'obj_constant_list'}'
+                        {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN);
+                         _asn1_set_name($$,$1);  
+                         _asn1_set_down($$,$6);}
+              | IDENTIFIER IDENTIFIER "::=" '{' obj_constant_list '}'
+                        {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
+                         _asn1_set_name($$,$1);  
+                         _asn1_set_value($$,$2,strlen($2)+1);
+                         _asn1_set_down($$,$5);}
+              | IDENTIFIER INTEGER "::=" pos_neg_num
+                        {$$=_asn1_add_node(TYPE_INTEGER|CONST_ASSIGN);
+                         _asn1_set_name($$,$1);  
+                         _asn1_set_value($$,$4,strlen($4)+1);}
+;
+
+type_constant:   type_def     {$$=$1;}
+               | constant_def {$$=$1;}
+;
+
+type_constant_list :   type_constant    {$$=$1;}
+                     | type_constant_list type_constant  {$$=$1;
+                                                          _asn1_set_right(_asn1_get_last_right($1),$2);}
+;
+
+definitions_id  :  IDENTIFIER  '{' obj_constant_list '}' {$$=_asn1_add_node(TYPE_OBJECT_ID);
+                                                          _asn1_set_down($$,$3);
+                                                          _asn1_set_name($$,$1);}
+                 | IDENTIFIER  '{' '}'                   {$$=_asn1_add_node(TYPE_OBJECT_ID);
+                                                          _asn1_set_name($$,$1);}
+;
+
+/*
+identifier_list  :  IDENTIFIER  {$$=_asn1_add_node(TYPE_IDENTIFIER);
+                                 _asn1_set_name($$,$1);}
+                  | identifier_list IDENTIFIER  
+                                {$$=$1;
+                                 _asn1_set_right(_asn1_get_last_right($$),_asn1_add_node(TYPE_IDENTIFIER));
+                                 _asn1_set_name(_asn1_get_last_right($$),$2);}
+; 
+
+
+imports_def :    empty   {$$=NULL;}
+              | IMPORTS identifier_list FROM IDENTIFIER obj_constant_list 
+                        {$$=_asn1_add_node(TYPE_IMPORTS);
+                         _asn1_set_down($$,_asn1_add_node(TYPE_OBJECT_ID));
+                         _asn1_set_name(_asn1_get_down($$),$4);  
+                         _asn1_set_down(_asn1_get_down($$),$5);
+                         _asn1_set_right($$,$2);}
+; 
+*/
+
+explicit_implicit :  EXPLICIT  {$$=CONST_EXPLICIT;}
+                   | IMPLICIT  {$$=CONST_IMPLICIT;}
+;
+
+
+%%
+
+
+
+const char *key_word[]={"::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING"
+                       ,"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL"
+                       ,"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER"
+                       ,"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED"
+                       ,"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS"
+                       ,"BEGIN","END","UTCTime","GeneralizedTime","FROM"
+                       ,"IMPORTS","NULL","ENUMERATED"};
+const int key_word_token[]={ASSIG,OPTIONAL,INTEGER,SIZE,OCTET,STRING
+                       ,SEQUENCE,BIT,UNIVERSAL,PRIVATE,OPTIONAL
+                       ,DEFAULT,CHOICE,OF,OBJECT,STR_IDENTIFIER
+                       ,BOOLEAN,TRUE,FALSE,APPLICATION,ANY,DEFINED
+                       ,SET,BY,EXPLICIT,IMPLICIT,DEFINITIONS,TAGS
+                       ,BEGIN,END,UTCTime,GeneralizedTime,FROM
+                       ,IMPORTS,TOKEN_NULL,ENUMERATED};
+
+/*************************************************************/
+/*  Function: yylex                                          */
+/*  Description: looks for tokens in file_asn1 pointer file. */
+/*  Return: int                                              */
+/*    Token identifier or ASCII code or 0(zero: End Of File) */
+/*************************************************************/
+int 
+yylex() 
+{
+  int c,counter=0,k;
+  char string[MAX_NAME_SIZE+1]; /* will contain the next token */  
+
+  while(1)
+    {
+    while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n')
+      if(c=='\n') lineNumber++;
+
+    if(c==EOF){
+      strcpy(lastToken,"End Of File");
+      return 0;
+    }
+
+    if(c=='(' || c==')' || c=='[' || c==']' || 
+       c=='{' || c=='}' || c==',' || c=='.' ||
+       c=='+'){
+      lastToken[0]=c;lastToken[1]=0;
+      return c;
+    }
+    if(c=='-'){  /* Maybe the first '-' of a comment */
+      if((c=fgetc(file_asn1))!='-'){
+       ungetc(c,file_asn1);
+       lastToken[0]='-';lastToken[1]=0;
+       return '-';
+      }
+      else{ /* Comments */
+       counter=0;
+       /* A comment finishes at the end of line */
+       while((c=fgetc(file_asn1))!=EOF && c!='\n');
+       if(c==EOF){
+         strcpy(lastToken,"End Of File");
+         return 0;
+       }
+       else{
+         lineNumber++;
+         continue; /* next char, please! (repeat the search) */
+       }
+      }
+    }
+    string[counter++]=c;
+    /* Till the end of the token */
+    while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' || 
+            c=='(' || c==')' || c=='[' || c==']' || 
+            c=='{' || c=='}' || c==',' || c=='.'))
+      {
+       if(counter>=MAX_NAME_SIZE){
+         result_parse=ASN1_NAME_TOO_LONG;
+         return 0;
+       }
+       string[counter++]=c;
+      }
+    ungetc(c,file_asn1);
+    string[counter]=0;
+    strcpy(lastToken,string);
+
+    /* Is STRING a number? */
+    for(k=0;k<counter;k++) 
+      if(!isdigit(string[k])) break;
+    if(k>=counter)
+      {
+      strcpy(yylval.str,string);  
+      return NUM; /* return the number */
+      }
+    /* Is STRING a keyword? */
+    for(k=0;k<(sizeof(key_word)/sizeof(char*));k++)  
+      if(!strcmp(string,key_word[k])) return key_word_token[k]; 
+    /* STRING is an IDENTIFIER */
+    strcpy(yylval.str,string);
+    return IDENTIFIER;
+    }
+}
+
+
+/*************************************************************/
+/*  Function: _asn1_create_errorDescription                  */
+/*  Description: creates a string with the description of the*/
+/*    error.                                                 */
+/*  Parameters:                                              */
+/*    error : error to describe.                             */
+/*    errorDescription: string that will contain the         */
+/*                      description.                         */
+/*************************************************************/
+void
+_asn1_create_errorDescription(int error,char *errorDescription)
+{
+  switch(error){
+  case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND: 
+    errorDescription[0]=0;
+    break;
+  case ASN1_SYNTAX_ERROR:
+    strcpy(errorDescription,fileName);
+    strcat(errorDescription,":");
+    _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+    strcat(errorDescription,": parse error near '");
+    strcat(errorDescription,lastToken);
+    strcat(errorDescription,"'");
+    break;
+  case ASN1_NAME_TOO_LONG:
+    strcpy(errorDescription,fileName);
+    strcat(errorDescription,":");
+    _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+    strcat(errorDescription,": name too long (more than ");
+    _asn1_ltostr(MAX_NAME_SIZE,errorDescription+strlen(errorDescription));
+    strcat(errorDescription," characters)");
+    break;
+  case ASN1_IDENTIFIER_NOT_FOUND:
+    strcpy(errorDescription,fileName);
+    strcat(errorDescription,":");
+    strcat(errorDescription,": identifier '");
+    strcat(errorDescription,identifierMissing);
+    strcat(errorDescription,"' not found");
+    break;
+  default:
+    errorDescription[0]=0;
+    break;
+  }
+
+}
+
+
+/**
+  * asn1_parser2tree - function used to start the parse algorithm.
+  * @file_name: specify the path and the name of file that contains ASN.1 declarations.
+  * @definitions: return the pointer to the structure created from 
+  *   "file_name" ASN.1 declarations.  
+  * @errorDescription : return the error description or an empty string if success.
+  * Description:
+  *
+  * Creates the structures needed to manage the definitions included in *FILE_NAME file.
+  *
+  * Returns:
+  *
+  * ASN1_SUCCESS\: the file has a correct syntax and every identifier is known.
+  *
+  * ASN1_ELEMENT_NOT_EMPTY\: *POINTER not ASN1_TYPE_EMPTY.
+  *
+  * ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  * ASN1_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  * ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters.
+  **/
+asn1_retCode
+asn1_parser2tree(char *file_name,ASN1_TYPE *definitions,char *errorDescription){
+
+  p_tree=ASN1_TYPE_EMPTY;
+
+  if(*definitions != ASN1_TYPE_EMPTY)
+    return ASN1_ELEMENT_NOT_EMPTY;
+
+  *definitions=ASN1_TYPE_EMPTY;
+
+  fileName = file_name;
+
+  /* open the file to parse */
+  file_asn1=fopen(file_name,"r");
+
+  if(file_asn1==NULL){
+    result_parse=ASN1_FILE_NOT_FOUND;
+  }
+  else{
+    result_parse=ASN1_SUCCESS;
+
+    lineNumber=1;
+    yyparse();
+
+    fclose(file_asn1);
+    
+    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+      /* set IMPLICIT or EXPLICIT property */
+      _asn1_set_default_tag(p_tree);
+      /* set CONST_SET and CONST_NOT_USED */
+      _asn1_type_set_config(p_tree);
+      /* check the identifier definitions */
+      result_parse=_asn1_check_identifier(p_tree);
+      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+       /* Delete the list and keep the ASN1 structure */
+       _asn1_delete_list();
+       /* Convert into DER coding the value assign to INTEGER constants */
+       _asn1_change_integer_value(p_tree);
+       /* Expand the IDs of OBJECT IDENTIFIER constants */
+       _asn1_expand_object_id(p_tree);
+
+       *definitions=p_tree;
+      }
+      else /* some identifiers not defined */ 
+       /* Delete the list and the ASN1 structure */
+       _asn1_delete_list_and_nodes();
+    }
+    else  /* syntax error */
+      /* Delete the list and the ASN1 structure */
+      _asn1_delete_list_and_nodes();
+  }
+
+  _asn1_create_errorDescription(result_parse,errorDescription);
+
+  return result_parse;
+}
+
+
+/**
+  * asn1_parser2array - function that generates a C structure from an ASN1 file
+  * @inputFileName: specify the path and the name of file that contains ASN.1 declarations.
+  * @outputFileName: specify the path and the name of file that will contain the C vector definition.
+  * @vectorName: specify the name of the C vector.
+  * @errorDescription : return the error description or an empty string if success.
+  * Description:
+  *
+  * Creates a file containing a C vector to use to manage the definitions included in
+  * *INPUTFILENAME file. If *INPUTFILENAME is "/aa/bb/xx.yy" and OUTPUTFILENAME is NULL, the file created is "/aa/bb/xx_asn1_tab.c".
+  * If VECTORNAME is NULL the vector name will be "xx_asn1_tab".
+  *
+  * Returns:
+  *
+  *  ASN1_SUCCESS\: the file has a correct syntax and every identifier is known. 
+  *
+  *  ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  *  ASN1_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  *  ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  *  ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters.
+  **/
+int asn1_parser2array(char *inputFileName,char *outputFileName,char *vectorName,char *errorDescription){
+  char *file_out_name=NULL;
+  char *vector_name=NULL;
+  char *char_p,*slash_p,*dot_p;
+
+  p_tree=NULL;
+
+  fileName = inputFileName;
+    
+  /* open the file to parse */
+  file_asn1=fopen(inputFileName,"r");
+
+  if(file_asn1==NULL)
+    result_parse=ASN1_FILE_NOT_FOUND;
+  else{
+    result_parse=ASN1_SUCCESS;
+
+    lineNumber=1;
+    yyparse();
+
+    fclose(file_asn1);
+
+    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+      /* set IMPLICIT or EXPLICIT property */
+      _asn1_set_default_tag(p_tree);
+      /* set CONST_SET and CONST_NOT_USED */
+      _asn1_type_set_config(p_tree);
+      /* check the identifier definitions */
+      result_parse=_asn1_check_identifier(p_tree);
+
+      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+
+       /* searching the last '/' and '.' in inputFileName */
+       char_p=inputFileName;
+       slash_p=inputFileName;
+       while((char_p=strchr(char_p,'/'))){
+         char_p++;
+         slash_p=char_p;
+       }
+
+       char_p=slash_p;
+       dot_p=inputFileName+strlen(inputFileName);
+       
+       while((char_p=strchr(char_p,'.'))){
+         dot_p=char_p;
+         char_p++;
+       }
+
+       if(outputFileName == NULL){ 
+         /* file_out_name = inputFileName + _asn1_tab.c */
+         file_out_name=(char *)malloc(dot_p-inputFileName+1+
+                                       strlen("_asn1_tab.c"));
+         memcpy(file_out_name,inputFileName,dot_p-inputFileName);
+         file_out_name[dot_p-inputFileName]=0;
+         strcat(file_out_name,"_asn1_tab.c");
+       }
+       else{
+         /* file_out_name = inputFileName */
+         file_out_name=(char *)malloc(strlen(outputFileName)+1);
+         strcpy(file_out_name,outputFileName);
+       }
+
+       if(vectorName == NULL){ 
+         /* vector_name = file name + _asn1_tab */
+         vector_name=(char *)malloc(dot_p-slash_p+1+
+                                       strlen("_asn1_tab"));
+         memcpy(vector_name,slash_p,dot_p-slash_p);
+         vector_name[dot_p-slash_p]=0;
+         strcat(vector_name,"_asn1_tab");
+       }
+       else{
+         /* vector_name = vectorName */
+         vector_name=(char *)malloc(strlen(vectorName)+1);
+         strcpy(vector_name,vectorName);
+       }
+
+       /* Save structure in a file */
+       _asn1_create_static_structure(p_tree,
+                  file_out_name,vector_name);
+
+       free(file_out_name);
+       free(vector_name);
+      } /* result == OK */
+    }   /* result == OK */
+     
+    /* Delete the list and the ASN1 structure */
+    _asn1_delete_list_and_nodes();    
+  } /* inputFile exist */
+
+  _asn1_create_errorDescription(result_parse,errorDescription);
+
+  return result_parse;
+}
+
+
+/*************************************************************/
+/*  Function: yyerror                                        */
+/*  Description: function called when there are syntax errors*/
+/*  Parameters:                                              */
+/*    char *s : error description                            */
+/*  Return: int                                              */
+/*                                                           */
+/*************************************************************/
+int yyerror (char *s)
+{
+  /* Sends the error description to the std_out */
+
+#ifdef DEBUG_PARSER
+  _libasn1_log("yyerror:%s:%d: %s (Last Token:'%s')\n",fileName,
+               lineNumber,s,lastToken); 
+#endif
+
+  if(result_parse!=ASN1_NAME_TOO_LONG) 
+    result_parse=ASN1_SYNTAX_ERROR;
+
+  return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/coding.c b/lib/coding.c
new file mode 100644 (file)
index 0000000..d67f394
--- /dev/null
@@ -0,0 +1,817 @@
+/*
+ *      Copyright (C) 2002  Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: coding.c                                    */
+/* Description: Functions to create a DER coding of  */
+/*   an ASN1 type.                                   */
+/*****************************************************/
+#include <int.h>
+#include <errors.h>
+#include "der.h"
+#include "parser_aux.h"
+#include <gstr.h>
+#include "element.h"
+
+/******************************************************/
+/* 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:                                            */
+/******************************************************/
+void
+_asn1_error_description_value_not_found(node_asn *node,char *ErrorDescription)
+{
+
+  strcpy(ErrorDescription,":: value of element '");
+  _asn1_hierarchical_name(node,ErrorDescription+strlen(ErrorDescription),
+                         MAX_ERROR_DESCRIPTION_SIZE-40);
+  strcat(ErrorDescription,"' not found");
+
+}
+
+/******************************************************/
+/* Function : _asn1_length_der                        */
+/* Description: creates the DER coding for the LEN    */
+/* parameter (only the length).                       */
+/* Parameters:                                        */
+/*   len: value to convert.                           */
+/*   ans: string returned.                            */
+/*   ans_len: number of meanful bytes of ANS          */
+/*            (ans[0]..ans[ans_len-1]).               */
+/* Return:                                            */
+/******************************************************/
+void
+_asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len)
+{
+  int k;
+  unsigned char temp[SIZEOF_UNSIGNED_LONG_INT];
+
+  if(len<128){
+    /* short form */
+    if(ans!=NULL) ans[0]=(unsigned char)len;
+    *ans_len=1;
+  }
+  else{
+    /* Long form */
+    k=0;
+    while(len){
+      temp[k++]=len&0xFF;
+      len=len>>8;
+    }
+    *ans_len=k+1;
+    if(ans!=NULL){
+      ans[0]=((unsigned char)k&0x7F)+128;
+      while(k--) ans[*ans_len-1-k]=temp[k];  
+    }
+  }
+}
+
+/******************************************************/
+/* Function : _asn1_tag_der                           */
+/* Description: creates the DER coding for the CLASS  */
+/* and TAG parameters.                                */
+/* Parameters:                                        */
+/*   class: value to convert.                         */
+/*   tag_value: value to convert.                     */
+/*   ans: string returned.                            */
+/*   ans_len: number of meanful bytes of ANS          */
+/*            (ans[0]..ans[ans_len-1]).               */
+/* Return:                                            */
+/******************************************************/
+void
+_asn1_tag_der(unsigned char class,unsigned int tag_value,unsigned char *ans,int *ans_len)
+{
+  int k;
+  unsigned char temp[SIZEOF_UNSIGNED_INT];
+
+  if(tag_value<30){
+    /* 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){
+      temp[k++]=tag_value&0x7F;
+      tag_value=tag_value>>7;
+    }
+    *ans_len=k+1;
+    while(k--) ans[*ans_len-1-k]=temp[k]+128;
+    ans[*ans_len-1]-=128;  
+  }
+}
+
+/******************************************************/
+/* Function : _asn1_octect_der                        */
+/* Description: creates the DER coding for an         */
+/* OCTET type (length included).                      */
+/* Parameters:                                        */
+/*   str: OCTET string.                               */
+/*   str_len: STR length (str[0]..str[str_len-1]).    */
+/*   der: string returned.                            */
+/*   der_len: number of meanful bytes of DER          */
+/*            (der[0]..der[ans_len-1]).               */
+/* Return:                                            */
+/******************************************************/
+void
+_asn1_octet_der(unsigned char *str,int str_len,unsigned char *der,int *der_len)
+{
+  int len_len;
+
+  if(der==NULL) return;
+  _asn1_length_der(str_len,der,&len_len);
+  memcpy(der+len_len,str,str_len);
+  *der_len=str_len+len_len;
+}
+
+/******************************************************/
+/* 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 meanful bytes of DER          */
+/*            (der[0]..der[ans_len-1]).               */
+/* Return:                                            */
+/******************************************************/
+void
+_asn1_time_der(unsigned char *str,unsigned char *der,int *der_len)
+{
+  int len_len;
+
+  if(der==NULL) return;
+  _asn1_length_der(strlen(str),der,&len_len);
+  memcpy(der+len_len,str,strlen(str));
+  *der_len=len_len+strlen(str);
+}
+
+
+/*
+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,&len_len);
+  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);
+}
+*/
+
+/******************************************************/
+/* Function : _asn1_objectid_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 meanful bytes of DER          */
+/*            (der[0]..der[ans_len-1]).               */
+/* Return:                                            */
+/******************************************************/
+void
+_asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len)
+{
+  int len_len,counter,k,first;
+  char *temp,*n_end,*n_start;
+  unsigned char bit7;
+  unsigned long val,val1=0;
+
+  if(der==NULL) return;
+
+  temp=(char *) malloc(strlen(str)+2);
+
+  strcpy(temp, str);
+  strcat(temp, " ");
+
+  counter=0;
+  n_start=temp;
+  while((n_end=strchr(n_start,' '))){
+    *n_end=0;
+    val=strtoul(n_start,NULL,10);
+    counter++;
+
+    if(counter==1) val1=val;
+    else if(counter==2){
+      der[0]=40*val1+val;
+      *der_len=1;
+    }
+    else{
+      first=0;
+      for(k=4;k>=0;k--){
+       bit7=(val>>(k*7))&0x7F;
+       if(bit7 || first || !k){
+         if(k) bit7|=0x80;
+         der[*der_len]=bit7;
+         (*der_len)++;
+         first=1;
+       }
+      }
+
+    }
+    n_start=n_end+1;
+  }
+
+  _asn1_length_der(*der_len,NULL,&len_len);
+  memmove(der+len_len,der,*der_len);
+  _asn1_length_der(*der_len,der,&len_len);
+  *der_len+=len_len;
+
+  free(temp);
+}
+
+
+char bit_mask[]={0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
+
+/******************************************************/
+/* Function : _asn1_bit_der                           */
+/* Description: creates the DER coding for a BIT      */
+/* STRING  type (length and pad included).            */
+/* Parameters:                                        */
+/*   str: BIT string.                                 */
+/*   bit_len: number of meanful bits in STR.          */
+/*   der: string returned.                            */
+/*   der_len: number of meanful bytes of DER          */
+/*            (der[0]..der[ans_len-1]).               */
+/* Return:                                            */
+/******************************************************/
+void
+_asn1_bit_der(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;
+  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 meanful bytes of DER          */
+/*            (der[0]..der[*counter-1]).              */
+/* Return:                                            */
+/******************************************************/
+void
+_asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter)
+{
+  node_asn *p;
+  int is_tag_implicit,len2,len3;
+  unsigned char temp[SIZEOF_UNSIGNED_INT];
+  
+  is_tag_implicit=0;
+
+  if(node->type&CONST_TAG){
+    p=node->down;
+    while(p){
+      if(type_field(p->type)==TYPE_TAG){
+       if(p->type&CONST_EXPLICIT){
+         len2=strtol(p->name,NULL,10);
+         _asn1_set_name(p,NULL);
+         _asn1_length_der(*counter-len2,temp,&len3);
+         memmove(der+len2+len3,der+len2,*counter-len2);
+         memcpy(der+len2,temp,len3);
+         *counter+=len3;         
+         is_tag_implicit=0;
+       }
+       else{  /* CONST_IMPLICIT */
+         if(!is_tag_implicit){
+           is_tag_implicit=1;
+         }
+       }
+      }
+      p=p->right;
+    }
+  }
+}
+
+
+/******************************************************/
+/* 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 meanful bytes of DER          */
+/*            (counter[0]..der[*counter-1]).          */
+/* Return:                                            */
+/*   ASN1_GENERIC_ERROR if the type is unknown,       */
+/*   otherwise ASN1_SUCCESS.                          */
+/******************************************************/
+int
+_asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter)
+{
+  node_asn *p;
+  int tag_len,is_tag_implicit;
+  unsigned char class,class_implicit=0,temp[SIZEOF_UNSIGNED_INT*3+1];
+  unsigned long tag_implicit=0;
+   
+  is_tag_implicit=0;
+
+  if(node->type&CONST_TAG){
+    p=node->down;
+    while(p){
+      if(type_field(p->type)==TYPE_TAG){
+       if(p->type&CONST_APPLICATION) class=APPLICATION;
+       else if(p->type&CONST_UNIVERSAL) class=UNIVERSAL;
+       else if(p->type&CONST_PRIVATE) class=PRIVATE;
+       else class=CONTEXT_SPECIFIC;
+       
+       if(p->type&CONST_EXPLICIT){
+         if(is_tag_implicit)
+           _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len);
+         else
+           _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),der+*counter,&tag_len);
+         *counter+=tag_len;
+         _asn1_ltostr(*counter,temp);
+         _asn1_set_name(p,temp);
+
+         is_tag_implicit=0;
+       }
+       else{  /* CONST_IMPLICIT */
+         if(!is_tag_implicit){
+           if((type_field(node->type)==TYPE_SEQUENCE) || 
+              (type_field(node->type)==TYPE_SEQUENCE_OF) ||
+              (type_field(node->type)==TYPE_SET) ||
+              (type_field(node->type)==TYPE_SET_OF)) class|=STRUCTURED;
+           class_implicit=class;
+           tag_implicit=strtoul(p->value,NULL,10);
+           is_tag_implicit=1;
+         }
+       }
+      }
+      p=p->right;
+    }
+  }
+  
+  if(is_tag_implicit){
+    _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len);
+  }
+  else{
+    switch(type_field(node->type)){
+    case TYPE_NULL:
+      _asn1_tag_der(UNIVERSAL,TAG_NULL,der+*counter,&tag_len);
+      break;
+    case TYPE_BOOLEAN:
+      _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,der+*counter,&tag_len);
+      break;
+    case TYPE_INTEGER:
+      _asn1_tag_der(UNIVERSAL,TAG_INTEGER,der+*counter,&tag_len);
+      break;
+    case TYPE_ENUMERATED:
+      _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,der+*counter,&tag_len);
+      break;
+    case TYPE_OBJECT_ID:
+      _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,der+*counter,&tag_len);
+      break;
+    case TYPE_TIME:
+      if(node->type&CONST_UTC){
+       _asn1_tag_der(UNIVERSAL,TAG_UTCTime,der+*counter,&tag_len);
+      }
+      else _asn1_tag_der(UNIVERSAL,TAG_GENERALIZEDTime,der+*counter,&tag_len);
+      break;
+    case TYPE_OCTET_STRING:
+      _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,der+*counter,&tag_len);
+      break;
+    case TYPE_BIT_STRING:
+      _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,der+*counter,&tag_len);
+      break;
+    case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF:
+      _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,der+*counter,&tag_len);
+      break;
+    case TYPE_SET: case TYPE_SET_OF:
+      _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,der+*counter,&tag_len);
+      break;
+    case TYPE_TAG:
+      tag_len=0;
+      break;
+    case TYPE_CHOICE:
+      tag_len=0;
+      break;
+    case TYPE_ANY:
+      tag_len=0;
+      break;
+    default:
+      return ASN1_GENERIC_ERROR;
+    }
+  }
+  
+  *counter+=tag_len;
+
+  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:                                            */
+/******************************************************/
+void
+_asn1_ordering_set(unsigned char *der,node_asn *node)
+{
+  struct vet{
+    int end;
+    unsigned long value;
+    struct vet *next,*prev;
+  };
+
+  int counter,len,len2;
+  struct vet *first,*last,*p_vet,*p2_vet;
+  node_asn *p;
+  unsigned char class,*temp;
+  unsigned long tag;
+
+  counter=0;
+
+  if(type_field(node->type)!=TYPE_SET) return;
+
+  p=node->down;
+  while((type_field(p->type)==TYPE_TAG)  || (type_field(p->type)==TYPE_SIZE)) p=p->right;
+
+  if((p==NULL) || (p->right==NULL)) return;
+
+  first=last=NULL;
+  while(p){
+    p_vet=(struct vet *)_asn1_alloca( sizeof(struct vet));
+    if (p_vet==NULL) return;
+    
+    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 */
+    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    p_vet->value=(class<<24)|tag;
+    counter+=len2;
+
+    /* extraction  and length */
+    len2=_asn1_get_length_der(der+counter,&len);
+    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=(unsigned char *)_asn1_alloca( p_vet->end-counter);
+       if (temp==NULL) return;
+       
+       memcpy(temp,der+counter,p_vet->end-counter);
+       memmove(der+counter,der+p_vet->end,p2_vet->end-p_vet->end);
+       memcpy(der+p_vet->end,temp,p_vet->end-counter);
+       _asn1_afree(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;
+    _asn1_afree(p_vet);
+    p_vet=first;
+  }
+}
+
+/******************************************************/
+/* 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:                                            */
+/******************************************************/
+void
+_asn1_ordering_set_of(unsigned char *der,node_asn *node)
+{
+  struct vet{
+    int end;
+    struct vet *next,*prev;
+  };
+
+  int counter,len,len2,change;
+  struct vet *first,*last,*p_vet,*p2_vet;
+  node_asn *p;
+  unsigned char *temp,class;
+  unsigned long k,max;
+
+  counter=0;
+
+  if(type_field(node->type)!=TYPE_SET_OF) return;
+
+  p=node->down;
+  while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
+  p=p->right;
+
+  if((p==NULL) || (p->right==NULL)) return;
+
+  first=last=NULL;
+  while(p){
+    p_vet=(struct vet *)_asn1_alloca(sizeof(struct vet));
+    if (p_vet==NULL) return;
+    
+    p_vet->next=NULL;
+    p_vet->prev=last;
+    if(first==NULL) first=p_vet;
+    else last->next=p_vet;
+    last=p_vet;
+
+    /* extraction of tag and length */
+    _asn1_get_tag_der(der+counter,&class,&len);
+    counter+=len;
+    len2=_asn1_get_length_der(der+counter,&len);
+    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->end-counter)>(p2_vet->end-p_vet->end))
+       max=p_vet->end-counter;
+      else
+       max=p2_vet->end-p_vet->end;
+
+      change=-1;
+      for(k=0;k<max;k++) 
+       if(der[counter+k]>der[p_vet->end+k]){change=1;break;}
+       else if(der[counter+k]<der[p_vet->end+k]){change=0;break;}
+
+      if((change==-1) && ((p_vet->end-counter)>(p2_vet->end-p_vet->end)))
+       change=1;
+
+      if(change==1){
+       /* change position */
+       temp=(unsigned char *)_asn1_alloca(p_vet->end-counter);
+       if (temp==NULL) return;
+       
+       memcpy(temp,der+counter,p_vet->end-counter);
+       memmove(der+counter,der+p_vet->end,p2_vet->end-p_vet->end);
+       memcpy(der+p_vet->end,temp,p_vet->end-counter);
+       _asn1_afree(temp);
+       
+       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;
+    _asn1_afree(p_vet);
+    p_vet=first;
+  }
+}
+
+/**
+  * asn1_der_coding - Creates the DER encoding for the NAME structure
+  * @element: pointer to an ASN1 element
+  * @name: the name of the structure you want to encode (it must be inside *POINTER).
+  * @der: vector that will contain the DER encoding. DER must be a pointer to memory cells already allocated.
+  * @len: number of bytes of *der: der[0]..der[len-1]
+  * @errorDescription : return the error description or an empty string if success.
+  * Description:
+  *
+  * Creates the DER encoding for the NAME structure (inside *POINTER structure).
+  * 
+  * Returns:
+  *
+  *   ASN1_SUCCESS\: DER encoding OK
+  *
+  *   ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element.
+  *
+  *   ASN1_VALUE_NOT_FOUND\: there is an element without a value.
+  **/
+asn1_retCode 
+asn1_der_coding(ASN1_TYPE element,char *name,unsigned char *der,int *len,
+                char *ErrorDescription)
+{
+  node_asn *node,*p;
+  char temp[SIZEOF_UNSIGNED_LONG_INT*3+1];
+  int counter,counter_old,len2,len3,move,ris;
+
+  node=_asn1_find_node(element,name);
+  if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
+
+  counter=0;
+  move=DOWN;
+  p=node;
+  while(1){
+    
+    counter_old=counter;
+    if(move!=UP) ris=_asn1_insert_tag_der(p,der,&counter);
+
+    switch(type_field(p->type)){
+    case TYPE_NULL:
+      der[counter]=0;
+      counter++;
+      move=RIGHT;
+      break;
+    case TYPE_BOOLEAN:
+      if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old;
+      else{
+       der[counter++]=1;
+       if(p->value[0]=='F') der[counter++]=0;
+       else der[counter++]=0xFF;
+      }
+      move=RIGHT;
+      break;
+    case TYPE_INTEGER: case TYPE_ENUMERATED:
+      if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old;
+      else{
+       if(p->value==NULL){
+         _asn1_error_description_value_not_found(p,ErrorDescription);
+         return ASN1_VALUE_NOT_FOUND;
+       }
+       len2=_asn1_get_length_der(p->value,&len3);
+       memcpy(der+counter,p->value,len3+len2);
+       counter+=len3+len2;
+      }
+      move=RIGHT;
+      break;
+    case TYPE_OBJECT_ID:
+      _asn1_objectid_der(p->value,der+counter,&len2);
+      counter+=len2;
+      move=RIGHT;
+      break;
+    case TYPE_TIME:
+      _asn1_time_der(p->value,der+counter,&len2);
+      counter+=len2;
+      move=RIGHT;
+      break;
+    case TYPE_OCTET_STRING:
+      len2=_asn1_get_length_der(p->value,&len3);
+      memcpy(der+counter,p->value,len3+len2);
+      counter+=len3+len2;
+      move=RIGHT;
+      break;
+    case TYPE_BIT_STRING:
+      len2=_asn1_get_length_der(p->value,&len3);
+      memcpy(der+counter,p->value,len3+len2);
+      counter+=len3+len2;
+      move=RIGHT;
+      break;
+    case TYPE_SEQUENCE: case TYPE_SET: 
+      if(move!=UP){
+       _asn1_ltostr(counter,temp);
+       _asn1_set_value(p,temp,strlen(temp)+1);
+       move=DOWN;
+      }
+      else{   /* move==UP */
+       len2=strtol(p->value,NULL,10);
+       _asn1_set_value(p,NULL,0);
+       if(type_field(p->type)==TYPE_SET) _asn1_ordering_set(der+len2,p);
+       _asn1_length_der(counter-len2,temp,&len3);
+       memmove(der+len2+len3,der+len2,counter-len2);
+       memcpy(der+len2,temp,len3);
+       counter+=len3;
+       move=RIGHT;
+      }
+      break;
+    case TYPE_SEQUENCE_OF: case TYPE_SET_OF: 
+      if(move!=UP){
+       _asn1_ltostr(counter,temp);
+       _asn1_set_value(p,temp,strlen(temp)+1);
+       p=p->down;
+       while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_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=strtol(p->value,NULL,10);
+       _asn1_set_value(p,NULL,0);
+       if(type_field(p->type)==TYPE_SET_OF) _asn1_ordering_set_of(der+len2,p);
+       _asn1_length_der(counter-len2,temp,&len3);
+       memmove(der+len2+len3,der+len2,counter-len2);
+       memcpy(der+len2,temp,len3);
+       counter+=len3;
+       move=RIGHT;
+      }
+      break;
+    case TYPE_ANY:
+      len2=_asn1_get_length_der(p->value,&len3);
+      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))
+      _asn1_complete_explicit_tag(p,der,&counter);
+
+    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;
+  return ASN1_SUCCESS;
+}
+
+
diff --git a/lib/decoding.c b/lib/decoding.c
new file mode 100644 (file)
index 0000000..266d823
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ *      Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: decoding.c                                  */
+/* Description: Functions to manage DER decoding     */
+/*****************************************************/
+#include <int.h>
+#include <errors.h>
+#include "der.h"
+#include "parser_aux.h"
+#include <gstr.h>
+#include "structure.h"
+#include "element.h"
+
+
+void
+_asn1_error_description_tag_error(node_asn *node,char *ErrorDescription)
+{
+
+  strcpy(ErrorDescription,":: tag error near element '");
+  _asn1_hierarchical_name(node,ErrorDescription+strlen(ErrorDescription),
+                         MAX_ERROR_DESCRIPTION_SIZE-40);
+  strcat(ErrorDescription,"'");
+
+}
+
+  
+unsigned long
+_asn1_get_length_der(unsigned char *der,int  *len)
+{
+  unsigned long ans;
+  int k,punt;
+
+  if(!(der[0]&128)){
+    /* short form */
+    *len=1;
+    return der[0];
+  }
+  else{
+    /* Long form */
+    k=der[0]&0x7F;
+    punt=1;
+    ans=0;
+    while(punt<=k) ans=ans*256+der[punt++];
+    
+    *len=punt;
+    return ans;
+  }
+}
+
+
+
+
+unsigned int
+_asn1_get_tag_der(unsigned char *der,unsigned char *class,int  *len)
+{
+  int punt,ris;
+
+  *class=der[0]&0xE0;
+  if((der[0]&0x1F)!=0x1F){
+    /* short form */
+    *len=1;
+    ris=der[0]&0x1F;
+  }
+  else{
+    /* Long form */
+    punt=1;
+    ris=0;
+    while(der[punt]&128) ris=ris*128+(der[punt++]&0x7F);
+    ris=ris*128+(der[punt++]&0x7F);   
+    *len=punt;
+  }
+  return ris;
+}
+
+
+
+
+int
+_asn1_get_octet_der(unsigned char *der,int *der_len,unsigned char *str,int str_size, int *str_len)
+{
+  int len_len;
+
+  if(str==NULL) return ASN1_SUCCESS;
+  *str_len=_asn1_get_length_der(der,&len_len);
+  if ( str_size >= *str_len)
+         memcpy(str,der+len_len,*str_len);
+  else {
+       return ASN1_MEM_ERROR;
+  }
+  *der_len=*str_len+len_len;
+  
+  return ASN1_SUCCESS;
+}
+
+
+
+
+void
+_asn1_get_time_der(unsigned char *der,int *der_len,unsigned char *str)
+{
+  int len_len,str_len;
+
+  if(str==NULL) return;
+  str_len=_asn1_get_length_der(der,&len_len);
+  memcpy(str,der+len_len,str_len);
+  str[str_len]=0;
+  *der_len=str_len+len_len;
+}
+
+
+
+void
+_asn1_get_objectid_der(unsigned char *der,int *der_len,unsigned char *str, int str_size)
+{
+  int len_len,len,k;
+  char temp[20];
+  unsigned long val,val1;
+
+  if(str==NULL) return;
+  len=_asn1_get_length_der(der,&len_len);
+  
+  val1=der[len_len]/40;
+  val=der[len_len]-val1*40;
+
+  _asn1_str_cpy(str, str_size, _asn1_ltostr(val1,temp));
+  _asn1_str_cat(str, str_size, " ");
+  _asn1_str_cat(str, str_size, _asn1_ltostr(val,temp));
+
+  val=0;
+  for(k=1;k<len;k++){
+    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;
+    }
+  }
+  *der_len=len+len_len;
+}
+
+
+
+
+int
+_asn1_get_bit_der(unsigned char *der,int *der_len,unsigned char *str, int str_size, int *bit_len)
+{
+  int len_len,len_byte;
+
+  if(str==NULL) return ASN1_SUCCESS;
+  len_byte=_asn1_get_length_der(der,&len_len)-1;
+  
+  if (str_size >= len_byte)
+       memcpy(str,der+len_len+1,len_byte);
+  else {
+       return ASN1_MEM_ERROR;
+  }
+  *bit_len=len_byte*8-der[len_len];
+  *der_len=len_byte+len_len+1;
+
+  return ASN1_SUCCESS;
+}
+
+
+
+
+int
+_asn1_extract_tag_der(node_asn *node,unsigned char *der,int *der_len)
+{
+  node_asn *p;
+  int counter,len2,len3,is_tag_implicit;
+  unsigned long tag,tag_implicit=0;
+  unsigned char class,class2,class_implicit=0;
+
+  counter=is_tag_implicit=0;
+  if(node->type&CONST_TAG){
+    p=node->down;
+    while(p){
+      if(type_field(p->type)==TYPE_TAG){
+       if(p->type&CONST_APPLICATION) class2=APPLICATION;
+       else if(p->type&CONST_UNIVERSAL) class2=UNIVERSAL;
+       else if(p->type&CONST_PRIVATE) class2=PRIVATE;
+       else class2=CONTEXT_SPECIFIC;
+       
+       if(p->type&CONST_EXPLICIT){
+         tag=_asn1_get_tag_der(der+counter,&class,&len2);
+         counter+=len2;
+         len3=_asn1_get_length_der(der+counter,&len2);
+         counter+=len2;
+         if(!is_tag_implicit){
+           if((class!=(class2|STRUCTURED)) || (tag!=strtoul(p->value,NULL,10)))
+             return ASN1_TAG_ERROR;
+         }
+         else{    /* TAG_IMPLICIT */
+           if((class!=class_implicit) || (tag!=tag_implicit))
+             return ASN1_TAG_ERROR;
+         }
+
+         is_tag_implicit=0;
+       }
+       else{    /* TAG_IMPLICIT */
+         if(!is_tag_implicit){
+           if((type_field(node->type)==TYPE_SEQUENCE) ||
+              (type_field(node->type)==TYPE_SEQUENCE_OF) ||
+              (type_field(node->type)==TYPE_SET) ||
+              (type_field(node->type)==TYPE_SET_OF))  class2|=STRUCTURED;
+           class_implicit=class2;
+           tag_implicit=strtoul(p->value,NULL,10);
+           is_tag_implicit=1;
+         }
+       }
+      }
+      p=p->right;
+    }
+  }
+
+  if(is_tag_implicit){
+    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    if((class!=class_implicit) || (tag!=tag_implicit)) return ASN1_TAG_ERROR;
+  }
+  else{
+    if(type_field(node->type)==TYPE_TAG){
+      counter=0;
+      *der_len=counter;
+      return ASN1_SUCCESS;
+    }
+
+    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    switch(type_field(node->type)){
+    case TYPE_NULL:
+      if((class!=UNIVERSAL) || (tag!=TAG_NULL)) return ASN1_DER_ERROR;
+       break;
+    case TYPE_BOOLEAN:
+      if((class!=UNIVERSAL) || (tag!=TAG_BOOLEAN)) return ASN1_DER_ERROR;
+       break;
+    case TYPE_INTEGER:
+      if((class!=UNIVERSAL) || (tag!=TAG_INTEGER)) return ASN1_DER_ERROR;
+       break;
+    case TYPE_ENUMERATED:
+      if((class!=UNIVERSAL) || (tag!=TAG_ENUMERATED)) return ASN1_DER_ERROR;
+       break;
+    case TYPE_OBJECT_ID:
+      if((class!=UNIVERSAL) || (tag!=TAG_OBJECT_ID)) return ASN1_DER_ERROR;
+       break;
+    case TYPE_TIME:
+      if(node->type&CONST_UTC){
+         if((class!=UNIVERSAL) || (tag!=TAG_UTCTime)) return ASN1_DER_ERROR;
+      }
+      else{
+       if((class!=UNIVERSAL) || (tag!=TAG_GENERALIZEDTime)) 
+         return ASN1_DER_ERROR;
+      }
+      break;
+    case TYPE_OCTET_STRING:
+      if((class!=UNIVERSAL) || (tag!=TAG_OCTET_STRING)) return ASN1_DER_ERROR;
+      break;
+    case TYPE_BIT_STRING:
+      if((class!=UNIVERSAL) || (tag!=TAG_BIT_STRING)) return ASN1_DER_ERROR;
+      break;
+    case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF:
+      if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SEQUENCE)) 
+       return ASN1_DER_ERROR;
+      break;
+    case TYPE_SET: case TYPE_SET_OF:
+      if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SET)) 
+       return ASN1_DER_ERROR;
+      break;
+    case TYPE_ANY:
+      counter-=len2;
+      break;
+    default:
+      return ASN1_DER_ERROR;
+      break;
+    }
+  }
+
+  counter+=len2;
+  *der_len=counter;
+  return ASN1_SUCCESS;
+}
+
+
+int 
+_asn1_delete_not_used(node_asn *node)
+{
+  node_asn *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;
+}
+
+
+
+/**
+  * asn1_der_decoding - Fill the structure *ELEMENT with values of a DER encoding string.
+  * @element: pointer to an ASN1 structure
+  * @der: vector that contains the DER encoding. 
+  * @len: number of bytes of *der: der[0]..der[len-1]
+  * Description:
+  *
+  * Fill the structure *ELEMENT with values of a DER encoding string. The sructure must just be
+  * created with function 'create_stucture'.
+  * If an error accurs during de decoding procedure, the *ELEMENT is deleted
+  * and set equal to ASN1_TYPE_EMPTY.
+  *
+  * Returns:
+  *
+  *   ASN1_SUCCESS\: DER encoding OK
+  *
+  *   ASN1_ELEMENT_NOT_FOUND\: ELEMENT is ASN1_TYPE_EMPTY.
+  *
+  *   ASN1_TAG_ERROR,ASN1_DER_ERROR\: the der encoding doesn't match the structure NAME. *ELEMENT deleted. 
+  **/
+
+asn1_retCode
+asn1_der_decoding(ASN1_TYPE *element,unsigned char *der,int len,char *errorDescription)
+{
+  node_asn *node,*p,*p2,*p3;
+  char temp[128];
+  int counter,len2,len3,len4,move,ris;
+  unsigned char class,*temp2;
+  unsigned int tag;
+
+  node=*element;
+
+  if(node==ASN1_TYPE_EMPTY) return ASN1_ELEMENT_NOT_FOUND;
+
+  if(node->type&CONST_OPTION){
+    asn1_delete_structure(element);
+    return ASN1_GENERIC_ERROR;
+  }
+
+  counter=0;
+  move=DOWN;
+  p=node;
+  while(1){
+    ris=ASN1_SUCCESS;
+
+    if(move!=UP){
+      if(p->type&CONST_SET){
+       p2=_asn1_find_up(p);
+       len2=strtol(p2->value,NULL,10);
+       if(counter==len2){
+         p=p2;
+         move=UP;
+         continue;
+       }
+       else if(counter>len2){
+         asn1_delete_structure(element);
+         return ASN1_DER_ERROR;
+       }
+       p2=p2->down;
+       while(p2){
+         if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){
+           if(type_field(p2->type)!=TYPE_CHOICE)
+             ris=_asn1_extract_tag_der(p2,der+counter,&len2);
+           else{
+             p3=p2->down;
+             while(p3){
+               ris=_asn1_extract_tag_der(p3,der+counter,&len2);
+               if(ris==ASN1_SUCCESS) break;
+               //if(ris==ASN1_ERROR_TYPE_ANY) return ASN1_ERROR_TYPE_ANY;
+               p3=p3->right;
+             }
+           }
+           if(ris==ASN1_SUCCESS){
+             p2->type&=~CONST_NOT_USED;
+             p=p2;
+             break;
+           }
+           //else if(ris==ASN1_ERROR_TYPE_ANY) return ASN1_ERROR_TYPE_ANY;
+         }
+         p2=p2->right;
+       }
+       if(p2==NULL){
+         asn1_delete_structure(element);
+         return ASN1_DER_ERROR;
+       }
+      }
+
+      if(type_field(p->type)==TYPE_CHOICE){
+       while(p->down){
+         ris=_asn1_extract_tag_der(p->down,der+counter,&len2);
+         if(ris==ASN1_SUCCESS){
+           while(p->down->right){
+             p2=p->down->right;
+             asn1_delete_structure(&p2);
+           }
+           break;
+         }
+         else if(ris==ASN1_ERROR_TYPE_ANY){
+           asn1_delete_structure(element);
+           return ASN1_ERROR_TYPE_ANY;
+         }
+         else{
+           p2=p->down;
+           asn1_delete_structure(&p2);
+         }
+       }
+       if(p->down==NULL){
+         asn1_delete_structure(element);
+         return ASN1_DER_ERROR;
+       }
+       p=p->down;
+      }
+
+      if((p->type&CONST_OPTION) || (p->type&CONST_DEFAULT)){
+       p2=_asn1_find_up(p);
+       len2=strtol(p2->value,NULL,10);
+       if(counter>=len2) ris=ASN1_TAG_ERROR;
+      }
+
+      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,&len2);
+      if(ris!=ASN1_SUCCESS){
+       //if(ris==ASN1_ERROR_TYPE_ANY) return ASN1_ERROR_TYPE_ANY;
+       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 {
+         //return (type_field(p->type)!=TYPE_ANY)?ASN1_TAG_ERROR:ASN1_ERROR_TYPE_ANY;
+         _asn1_error_description_tag_error(p,errorDescription);
+         
+         asn1_delete_structure(element);
+         return ASN1_TAG_ERROR;
+       }
+      } 
+      else counter+=len2;
+    }
+
+    if(ris==ASN1_SUCCESS){
+      switch(type_field(p->type)){
+      case TYPE_NULL:
+       if(der[counter]){
+         asn1_delete_structure(element);
+         return ASN1_DER_ERROR;
+       }
+       counter++;
+       move=RIGHT;
+       break;
+      case TYPE_BOOLEAN:
+       if(der[counter++]!=1){
+         asn1_delete_structure(element);
+         return ASN1_DER_ERROR;
+       }
+       if(der[counter++]==0) _asn1_set_value(p,"F",1);
+       else _asn1_set_value(p,"T",1);
+       move=RIGHT;
+       break;
+      case TYPE_INTEGER: case TYPE_ENUMERATED:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       _asn1_set_value(p,der+counter,len3+len2);
+       counter+=len3+len2;
+       move=RIGHT;
+       break;
+      case TYPE_OBJECT_ID:
+       _asn1_get_objectid_der(der+counter,&len2, temp, sizeof(temp));
+       _asn1_set_value(p,temp,strlen(temp)+1);
+       counter+=len2;
+       move=RIGHT;
+      break;
+      case TYPE_TIME:
+       _asn1_get_time_der(der+counter,&len2,temp);
+       _asn1_set_value(p,temp,strlen(temp)+1);
+       counter+=len2;
+       move=RIGHT;
+       break;
+      case TYPE_OCTET_STRING:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       _asn1_set_value(p,der+counter,len3+len2);
+       counter+=len3+len2;
+       move=RIGHT;
+       break;
+      case TYPE_BIT_STRING:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       _asn1_set_value(p,der+counter,len3+len2);
+       counter+=len3+len2;
+       move=RIGHT;
+       break;
+      case TYPE_SEQUENCE:  case TYPE_SET:;
+       if(move==UP){
+         len2=strtol(p->value,NULL,10);
+         _asn1_set_value(p,NULL,0);
+         if(len2!=counter){
+           asn1_delete_structure(element);
+           return ASN1_DER_ERROR;
+         }
+         move=RIGHT;
+       }
+       else{   /* move==DOWN || move==RIGHT */
+         len3=_asn1_get_length_der(der+counter,&len2);
+         counter+=len2;
+         _asn1_ltostr(counter+len3,temp);
+         _asn1_set_value(p,temp,strlen(temp)+1);
+         move=DOWN; 
+       }
+       break;
+      case TYPE_SEQUENCE_OF: case TYPE_SET_OF:
+       if(move==UP){
+         len2=strtol(p->value,NULL,10);
+         if(len2>counter){
+           _asn1_append_sequence_set(p);
+           p=p->down;
+           while(p->right) p=p->right;
+           move=RIGHT;
+           continue;
+         }
+         _asn1_set_value(p,NULL,0);
+         if(len2!=counter){
+           asn1_delete_structure(element);
+           return ASN1_DER_ERROR;
+         }
+       }
+       else{   /* move==DOWN || move==RIGHT */
+         len3=_asn1_get_length_der(der+counter,&len2);
+         counter+=len2;
+         if(len3){
+           _asn1_ltostr(counter+len3,temp);
+           _asn1_set_value(p,temp,strlen(temp)+1);
+           p2=p->down;
+           while((type_field(p2->type)==TYPE_TAG) || (type_field(p2->type)==TYPE_SIZE)) p2=p2->right;
+           if(p2->right==NULL) _asn1_append_sequence_set(p);
+           p=p2;
+         }
+       }
+       move=RIGHT;
+       break;
+      case TYPE_ANY:
+       tag=_asn1_get_tag_der(der+counter,&class,&len2);
+       len2+=_asn1_get_length_der(der+counter+len2,&len3);
+       _asn1_length_der(len2+len3,NULL,&len4);
+       temp2=(unsigned char *)_asn1_alloca(len2+len3+len4);
+        if (temp2==NULL){
+         asn1_delete_structure(element);
+         return ASN1_MEM_ERROR;
+       }
+        
+       _asn1_octet_der(der+counter,len2+len3,temp2,&len4);
+       _asn1_set_value(p,temp2,len4);
+       _asn1_afree(temp2);
+       counter+=len2+len3;
+       move=RIGHT;
+       break;
+      default:
+       move=(move==UP)?RIGHT:DOWN;
+       break;
+      }
+    }
+
+    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(counter != len){
+    asn1_delete_structure(element);
+    return ASN1_DER_ERROR;
+  }
+
+  return ASN1_SUCCESS;
+}
+
+
+/**
+  * asn1_der_decoding_startEnd - Find the start and end point of an element in a DER encoding string.
+  * @element: pointer to an ASN1 element
+  * @der: vector that contains the DER encoding. 
+  * @len: number of bytes of *der: der[0]..der[len-1]
+  * @name_element: an element of NAME structure.
+  * @start: the position of the first byte of NAME_ELEMENT decoding (der[*start]) 
+  * @end: the position of the last byte of NAME_ELEMENT decoding (der[*end])
+  * Description:
+  * 
+  * 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.
+  * 
+  * Example: the sequence "tbsCertificate" inside an X509 certificate.
+  *
+  * Returns:
+  *
+  *   ASN1_SUCCESS\: DER encoding OK
+  *
+  *   ASN1_ELEMENT_NOT_FOUND\: ELEMENT is ASN1_TYPE EMPTY  or NAME_ELEMENT is not a valid element.
+  *
+  *   ASN1_TAG_ERROR,ASN1_DER_ERROR\: the der encoding doesn't match the structure ELEMENT.
+  *
+  **/
+asn1_retCode
+asn1_der_decoding_startEnd(ASN1_TYPE element,unsigned char *der,int len,char *name_element,int *start, int *end)
+{
+  node_asn *node,*node_to_find,*p,*p2,*p3;
+  int counter,len2,len3,move,ris;
+  unsigned char class;
+  unsigned int tag;
+
+  node=element;
+
+  if(node==ASN1_TYPE_EMPTY) return ASN1_ELEMENT_NOT_FOUND;
+
+  node_to_find=_asn1_find_node(node,name_element);
+
+  if(node_to_find==NULL) return ASN1_ELEMENT_NOT_FOUND;
+
+  if(node_to_find==node){
+    *start=0;
+    *end=len-1;
+    return ASN1_SUCCESS;
+  }
+
+  if(node->type&CONST_OPTION) return ASN1_GENERIC_ERROR;
+
+  counter=0;
+  move=DOWN;
+  p=node;
+  while(1){
+    ris=ASN1_SUCCESS;
+    
+    if(move!=UP){
+      if(p->type&CONST_SET){
+       p2=_asn1_find_up(p);
+       len2=strtol(p2->value,NULL,10);
+       if(counter==len2){
+         p=p2;
+         move=UP;
+         continue;
+       }
+       else if(counter>len2) return ASN1_DER_ERROR;
+       p2=p2->down;
+       while(p2){
+         if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){  /* CONTROLLARE */
+           if(type_field(p2->type)!=TYPE_CHOICE)
+             ris=_asn1_extract_tag_der(p2,der+counter,&len2);
+           else{
+             p3=p2->down;
+             ris=_asn1_extract_tag_der(p3,der+counter,&len2);
+           }
+           if(ris==ASN1_SUCCESS){
+             p2->type&=~CONST_NOT_USED;
+             p=p2;
+             break;
+           }
+         }
+         p2=p2->right;
+       }
+       if(p2==NULL) return ASN1_DER_ERROR;
+      }
+
+      if(p==node_to_find) *start=counter;
+
+      if(type_field(p->type)==TYPE_CHOICE){
+       p=p->down;
+       ris=_asn1_extract_tag_der(p,der+counter,&len2);
+       if(p==node_to_find) *start=counter;
+      }
+
+      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,&len2);
+      if(ris!=ASN1_SUCCESS){
+       if(p->type&CONST_OPTION){
+         p->type|=CONST_NOT_USED;
+         move=RIGHT;
+       }
+       else if(p->type&CONST_DEFAULT) {
+         move=RIGHT;
+       }
+       else {
+         return ASN1_TAG_ERROR;
+       }
+      } 
+      else counter+=len2;
+    }
+
+    if(ris==ASN1_SUCCESS){
+      switch(type_field(p->type)){
+      case TYPE_NULL:
+       if(der[counter]) return ASN1_DER_ERROR;
+       counter++;
+       move=RIGHT;
+       break;
+      case TYPE_BOOLEAN:
+       if(der[counter++]!=1) return ASN1_DER_ERROR;
+       counter++;
+       move=RIGHT;
+       break;
+      case TYPE_INTEGER: case TYPE_ENUMERATED:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       counter+=len3+len2;
+       move=RIGHT;
+       break;
+      case TYPE_OBJECT_ID:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       counter+=len2+len3;
+       move=RIGHT;
+      break;
+      case TYPE_TIME:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       counter+=len2+len3;
+       move=RIGHT;
+       break;
+      case TYPE_OCTET_STRING:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       counter+=len3+len2;
+       move=RIGHT;
+       break;
+      case TYPE_BIT_STRING:
+       len2=_asn1_get_length_der(der+counter,&len3);
+       counter+=len3+len2;
+       move=RIGHT;
+       break;
+      case TYPE_SEQUENCE:  case TYPE_SET:
+       if(move!=UP){
+         len3=_asn1_get_length_der(der+counter,&len2);
+         counter+=len2;
+         move=DOWN; 
+       }
+       else move=RIGHT;
+       break;
+      case TYPE_SEQUENCE_OF: case TYPE_SET_OF:
+       if(move!=UP){
+         len3=_asn1_get_length_der(der+counter,&len2);
+         counter+=len2;
+         if(len3){
+           p2=p->down;
+           while((type_field(p2->type)==TYPE_TAG) || 
+                 (type_field(p2->type)==TYPE_SIZE)) p2=p2->right;
+           p=p2;
+         }
+       }
+       move=RIGHT;
+       break;
+      case TYPE_ANY:
+       tag=_asn1_get_tag_der(der+counter,&class,&len2);
+       len2+=_asn1_get_length_der(der+counter+len2,&len3);
+       counter+=len3+len2;
+       move=RIGHT;
+       break;
+      default:
+       move=(move==UP)?RIGHT:DOWN;
+       break;
+      }
+    }
+
+    if((p==node_to_find) && (move==RIGHT)){
+      *end=counter-1;
+      return ASN1_SUCCESS;
+    }
+
+    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);
+  }
+
+  return ASN1_ELEMENT_NOT_FOUND;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/element.c b/lib/element.c
new file mode 100644 (file)
index 0000000..d12330b
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*****************************************************/
+/* File: element.c                                   */
+/* Description: Functions with the read and write    */
+/*   functions.                                      */
+/*****************************************************/
+
+
+#include <int.h>
+#include <errors.h>
+#include "parser_aux.h"
+#include "der.h"
+#include <gstr.h>
+#include "structure.h"
+
+void
+_asn1_hierarchical_name(node_asn *node,char *name,int name_size)
+{
+  char *aux;
+  node_asn *p;
+  
+  p=node;
+
+  name[0]=0;
+
+  while(p != NULL){
+    if(p->name != NULL){
+      aux=(char*)malloc(strlen(name)+1);
+      strcpy(aux,name);
+      _asn1_str_cpy(name,name_size,p->name);
+      _asn1_str_cat(name,name_size,".");
+      _asn1_str_cat(name,name_size,aux);
+      free(aux);
+    }
+    p=_asn1_find_up(p);
+  }
+  name[strlen(name)-1]=0;
+}
+
+
+/******************************************************************/
+/* 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                                */
+/******************************************************************/
+asn1_retCode
+_asn1_convert_integer(char *value,unsigned char *value_out,int value_out_size, int *len)
+{
+  char negative;
+  unsigned char val[SIZEOF_UNSIGNED_LONG_INT],temp;
+  int k,k2;
+
+  *((long*)val)=strtol(value,NULL,10);
+
+#ifndef WORDS_BIGENDIAN
+  /* change to big-endian byte ordering */
+  for(k=0;k<SIZEOF_UNSIGNED_LONG_INT/2;k++){
+    temp=val[k];
+    val[k]=val[SIZEOF_UNSIGNED_LONG_INT-k-1];
+    val[SIZEOF_UNSIGNED_LONG_INT-k-1]=temp;
+  }
+#endif
+
+  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--; 
+
+  if (SIZEOF_UNSIGNED_LONG_INT-k> value_out_size)
+    /* VALUE_OUT is too short to contain the value convertion */
+    return ASN1_MEM_ERROR;
+
+  for(k2=k;k2<SIZEOF_UNSIGNED_LONG_INT;k2++)
+    value_out[k2-k]=val[k2];
+
+  *len=SIZEOF_UNSIGNED_LONG_INT-k;
+
+
+#ifdef DEBUG_INTEGER
+  _libasn1_log("_asn1_convert_integer: valueIn=%s, lenOut=%d",value,*len);
+  for(k=0;k<SIZEOF_UNSIGNED_LONG_INT;k++)
+    _libasn1_log(", vOut[%d]=%d",k,value_out[k]);
+  _libasn1_log("\n");
+#endif
+
+
+  return ASN1_SUCCESS;
+}
+
+
+int 
+_asn1_append_sequence_set(node_asn *node)
+{
+  node_asn *p,*p2;
+  char temp[10];
+  long n;
+
+  if(!node || !(node->down)) return ASN1_GENERIC_ERROR;
+
+  p=node->down;
+  while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
+  p2=_asn1_copy_structure3(p);
+  while(p->right) p=p->right;
+  _asn1_set_right(p,p2);
+  
+  if(p->name==NULL) _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);
+
+  return ASN1_SUCCESS;
+}
+
+
+/**
+  * asn1_write_value - Set the value of one element inside a structure.
+  * @node_root: pointer to a structure
+  * @name: the name of the element inside the structure that you want to set.
+  * @value: 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
+  * Description:
+  *
+  * Set the value of one element inside a structure.
+  * 
+  * Returns:
+  * 
+  *   ASN1_SUCCESS\: set value OK
+  *
+  *   ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element.
+  *
+  *   ASN1_VALUE_NOT_VALID\: VALUE has a wrong format.
+  * 
+  * Examples:  
+  *   description for each type
+  *
+  *\begin{itemize}
+  * \item 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
+  *
+  * \item ENUMERATED\: as INTEGER (but only with not negative numbers)
+  *
+  * \item 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
+  *
+  * \item OBJECT IDENTIFIER\: VALUE must be a null terminated string with each number separated by
+  *                      a blank (e.g. "1 2 3 543 1"). 
+  *                      LEN != 0
+  *            value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha
+  *
+  * \item UTCTime\: VALUE must be a null terminated string in one of these formats\:
+  *            "YYMMDDhhmmssZ" "YYMMDDhhmmssZ" "YYMMDDhhmmss+hh'mm'" "YYMMDDhhmmss-hh'mm'"
+  *            "YYMMDDhhmm+hh'mm'" "YYMMDDhhmm-hh'mm'".  
+  *            LEN != 0
+  *            value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 at 12h 00m  Greenwich Mean Time
+  *
+  * \item GeneralizedTime\: VALUE must be in one of this format\:
+  *                    "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.s+hh'mm'" 
+  *                    "YYYYMMDDhhmmss.s-hh'mm'" "YYYYMMDDhhmm+hh'mm'" "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
+  *
+  * \item OCTET STRING\: VALUE contains the octet string and LEN is the number of octet.
+  *            value="$\backslash$x01$\backslash$x02$\backslash$x03" , len=3  -> three bytes octet string
+  *
+  * \item 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)
+  *
+  * \item 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);
+  *
+  * \item ANY\: VALUE indicates the der encoding of a structure.
+  *        LEN != 0 
+  *
+  * \item 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);
+  *
+  * \item SET OF\: the same as SEQUENCE OF. 
+  *           Using "pkix.asn":
+  *
+  *           result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
+  *\end{itemize}
+  *
+  * 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,"certificate1.tbsCertificate.issuerUniqueID",NULL,0);
+  * 
+  **/
+asn1_retCode 
+asn1_write_value(node_asn *node_root,char *name,unsigned char *value,int len)
+{
+  node_asn *node,*p,*p2;
+  unsigned char *temp,*value_temp=NULL,*default_temp=NULL;
+  int len2,k,k2,negative;
+
+  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;
+  }
+
+  switch(type_field(node->type)){
+  case TYPE_BOOLEAN:
+    if(!strcmp(value,"TRUE")){
+      if(node->type&CONST_DEFAULT){
+       p=node->down;
+       while(type_field(p->type)!=TYPE_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(!strcmp(value,"FALSE")){
+      if(node->type&CONST_DEFAULT){
+       p=node->down;
+       while(type_field(p->type)!=TYPE_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 TYPE_INTEGER: case TYPE_ENUMERATED:
+    if(len==0){
+      if((isdigit(value[0])) || (value[0]=='-')){
+       value_temp=(unsigned char *)_asn1_alloca(SIZEOF_UNSIGNED_LONG_INT);
+       if (value_temp==NULL) return ASN1_MEM_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)==TYPE_CONSTANT){
+           if((p->name) && (!strcmp(p->name,value))){
+             value_temp=(unsigned char *)_asn1_alloca(SIZEOF_UNSIGNED_LONG_INT);
+             if (value_temp==NULL) return ASN1_MEM_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=(unsigned char *)_asn1_alloca(len);
+      if (value_temp==NULL) return ASN1_MEM_ERROR;
+      memcpy(value_temp,value,len);
+    }
+
+
+    if(value_temp[0]&0x80) negative=1;
+    else negative=0;
+
+    if(negative && (type_field(node->type)==TYPE_ENUMERATED)) 
+      {_asn1_afree(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_length_der(len-k,NULL,&len2);
+    temp=(unsigned char *)_asn1_alloca(len-k+len2);
+    if (temp==NULL) return ASN1_MEM_ERROR;
+
+    _asn1_octet_der(value_temp+k,len-k,temp,&len2);
+    _asn1_set_value(node,temp,len2);
+
+    _asn1_afree(temp);
+
+
+    if(node->type&CONST_DEFAULT){
+      p=node->down;
+      while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
+      if((isdigit(p->value[0])) || (p->value[0]=='-')){
+       default_temp=(unsigned char *)_asn1_alloca(SIZEOF_UNSIGNED_LONG_INT);
+        if (default_temp==NULL) return ASN1_MEM_ERROR;
+
+       _asn1_convert_integer(p->value,default_temp,SIZEOF_UNSIGNED_LONG_INT,&len2);
+      }
+      else{ /* is an identifier like v1 */
+       if(!(node->type&CONST_LIST)) return ASN1_VALUE_NOT_VALID;
+       p2=node->down;
+       while(p2){
+         if(type_field(p2->type)==TYPE_CONSTANT){
+           if((p2->name) && (!strcmp(p2->name,p->value))){
+             default_temp=(unsigned char *)_asn1_alloca(SIZEOF_UNSIGNED_LONG_INT);
+             if (default_temp==NULL) return ASN1_MEM_ERROR;
+
+             _asn1_convert_integer(p2->value,default_temp,SIZEOF_UNSIGNED_LONG_INT,&len2);
+             break;
+           }
+         }
+         p2=p2->right;
+       }
+       if(p2==NULL) 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);
+      }
+      _asn1_afree(default_temp);
+    }
+    _asn1_afree(value_temp);
+    break;
+  case TYPE_OBJECT_ID:
+    for(k=0;k<strlen(value);k++)
+      if((!isdigit(value[k])) && (value[k]!=' ') && (value[k]!='+')) 
+       return ASN1_VALUE_NOT_VALID; 
+    _asn1_set_value(node,value,strlen(value)+1);
+    break;
+  case TYPE_TIME:
+    if(node->type&CONST_UTC){
+      if(strlen(value)<11) return ASN1_VALUE_NOT_VALID;
+      for(k=0;k<10;k++) 
+       if(!isdigit(value[k])) return ASN1_VALUE_NOT_VALID;
+      switch(strlen(value)){
+      case 11:
+      if(value[10]!='Z') return ASN1_VALUE_NOT_VALID;
+      break;
+      case 13:
+       if((!isdigit(value[10])) || (!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(!isdigit(value[k])) return ASN1_VALUE_NOT_VALID;
+       break;
+      case 17:
+       if((!isdigit(value[10])) || (!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(!isdigit(value[k])) return ASN1_VALUE_NOT_VALID;
+       break; 
+      default:
+       return ASN1_VALUE_NOT_FOUND;
+      }
+      _asn1_set_value(node,value,strlen(value)+1);
+    }
+    else{  /* GENERALIZED TIME */
+      if(value) _asn1_set_value(node,value,strlen(value)+1);
+    }
+    break;
+  case  TYPE_OCTET_STRING:
+    _asn1_length_der(len,NULL,&len2);
+    temp=(unsigned char *)_asn1_alloca(len+len2);
+    if (temp==NULL) return ASN1_MEM_ERROR;
+
+    _asn1_octet_der(value,len,temp,&len2);
+    _asn1_set_value(node,temp,len2);
+    _asn1_afree(temp);
+    break;
+  case  TYPE_BIT_STRING:
+    _asn1_length_der((len>>3)+2,NULL,&len2);
+    temp=(unsigned char *)_asn1_alloca((len>>3)+2+len2);
+    if (temp==NULL) return ASN1_MEM_ERROR;
+
+    _asn1_bit_der(value,len,temp,&len2);
+    _asn1_set_value(node,temp,len2);
+    _asn1_afree(temp);
+    break;
+  case  TYPE_CHOICE:
+    p=node->down;
+    while(p){
+      if(!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 TYPE_ANY:
+    _asn1_length_der(len,NULL,&len2);
+    temp=(unsigned char *)_asn1_alloca(len+len2);
+    if (temp==NULL) return ASN1_MEM_ERROR;
+
+    _asn1_octet_der(value,len,temp,&len2);
+    _asn1_set_value(node,temp,len2);
+    _asn1_afree(temp);
+    break;
+  case TYPE_SEQUENCE_OF: case TYPE_SET_OF:
+    if(strcmp(value,"NEW")) return ASN1_VALUE_NOT_VALID;    
+    _asn1_append_sequence_set(node);
+    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 { \
+               memcpy( ptr, data, data_size); \
+       }
+
+#define PUT_STR_VALUE( ptr, ptr_size, data) \
+       *len = strlen(data) + 1; \
+       if (ptr_size < *len) { \
+               return ASN1_MEM_ERROR; \
+       } else { \
+               /* this strcpy is checked */ \
+               strcpy(ptr, data); \
+       }
+               
+#define ADD_STR_VALUE( ptr, ptr_size, data) \
+       *len = strlen(data) + 1; \
+       if (ptr_size < strlen(ptr)+(*len)) { \
+               return ASN1_MEM_ERROR; \
+       } else { \
+               /* this strcat is checked */ \
+               strcat(ptr, data); \
+       }
+
+/**
+  * asn1_read_value - Returns the value of one element inside a structure
+  * @root: pointer to a structure
+  * @name: the name of the element inside a structure that you want to read.
+  * @value: vector that will contain the element's content. 
+  * VALUE must be a pointer to memory cells already allocated.
+  * @len: number of bytes of *value: value[0]..value[len-1]. Initialy holds the sizeof value.
+  *
+  * Description:
+  *
+  * Returns the value of one element inside a structure.
+  * 
+  * Returns:
+  *
+  *   ASN1_SUCCESS\: set value OK
+  *
+  *   ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element.
+  *
+  *   ASN1_VALUE_NOT_FOUND\: there isn't any value for the element selected.
+  * 
+  * Examples: 
+  *   a description for each type
+  *
+  *\begin{itemize}
+  * \item INTEGER\: VALUE will contain a two's complement form integer.
+  *            integer=-1  -> value[0]=0xFF , len=1
+  *            integer=1   -> value[0]=0x01 , len=1
+  *
+  * \item ENUMERATED\: as INTEGER (but only with not negative numbers)
+  *
+  * \item BOOLEAN\: VALUE will be the null terminated string "TRUE" or "FALSE" and LEN=5 or LEN=6
+  *
+  * \item OBJECT IDENTIFIER\: VALUE will be a null terminated string with each number separated by
+  *                      a blank (i.e. "1 2 3 543 1"). 
+  *                      LEN = strlen(VALUE)+1
+  *
+  * \item UTCTime\: VALUE will be a null terminated string in one of these formats\: 
+  *            "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'"
+  *            LEN=strlen(VALUE)+1
+  *
+  * \item GeneralizedTime\: VALUE will be a null terminated string in the same format used to set
+  *                    the value
+  *
+  * \item OCTET STRING\: VALUE will contain the octet string and LEN will be the number of octet.
+  *
+  * \item BIT STRING\: VALUE will contain the bit string organized by bytes and LEN will be the 
+  *               number of bits.
+  *
+  * \item CHOICE\: if NAME indicates a choice type, VALUE will specify the alternative selected
+  *
+  * \item ANY\: if NAME indicates an any type, VALUE will indicate the DER encoding of the structure 
+  *        actually used.
+  *\end{itemize}
+  * 
+  * If an element is OPTIONAL and the function "read_value" 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.
+  * 
+  **/
+asn1_retCode 
+asn1_read_value(node_asn *root,char *name,unsigned char *value, int *len)
+{
+  node_asn *node,*p;
+  int len2,len3;
+  int value_size = *len;
+
+  node=_asn1_find_node(root,name);
+  if(node==NULL) return  ASN1_ELEMENT_NOT_FOUND;
+
+  if((type_field(node->type)!=TYPE_NULL) && 
+     (type_field(node->type)!=TYPE_CHOICE) &&  
+     !(node->type&CONST_DEFAULT) && !(node->type&CONST_ASSIGN) &&
+     (node->value==NULL)) 
+    return ASN1_VALUE_NOT_FOUND;
+
+  switch(type_field(node->type)){
+  case TYPE_NULL:
+    PUT_STR_VALUE( value, value_size, "NULL");
+    break;
+  case TYPE_BOOLEAN:
+    if((node->type&CONST_DEFAULT) && (node->value==NULL)){
+      p=node->down;
+      while(type_field(p->type)!=TYPE_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 TYPE_INTEGER: case TYPE_ENUMERATED:
+    if((node->type&CONST_DEFAULT) && (node->value==NULL)){
+      p=node->down;
+      while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
+      if (_asn1_convert_integer(p->value,value,value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+    }
+    else{
+      len2=-1;
+      if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+    }
+    break;
+  case TYPE_OBJECT_ID:
+    if(node->type&CONST_ASSIGN){
+      _asn1_str_cpy(value, *len, "");
+      p=node->down;
+      while(p){
+       if(type_field(p->type)==TYPE_CONSTANT){
+         ADD_STR_VALUE( value, value_size, p->value);
+         if(p->right) {
+               ADD_STR_VALUE( value, value_size, " ");
+         }
+       }
+       p=p->right;
+      }
+    } else {
+      PUT_STR_VALUE(value, value_size, node->value);
+    }
+    break;
+  case TYPE_TIME:
+    PUT_STR_VALUE( value, value_size, node->value);
+    break;
+  case TYPE_OCTET_STRING:
+    len2=-1;
+    if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+    break;
+  case TYPE_BIT_STRING:
+    len2=-1;
+    if (_asn1_get_bit_der(node->value,&len2,value,value_size,len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+    break;
+  case TYPE_CHOICE:
+    PUT_STR_VALUE( value, value_size, node->down->name);
+    break; 
+  case TYPE_ANY:
+    len3=-1;
+    len2=_asn1_get_length_der(node->value,&len3);
+    PUT_VALUE( value, value_size, node->value+len3, len2);
+    break;
+  default:
+    return  ASN1_ELEMENT_NOT_FOUND;
+    break;
+  }
+  return ASN1_SUCCESS;
+}
diff --git a/lib/element.h b/lib/element.h
new file mode 100644 (file)
index 0000000..9fff601
--- /dev/null
@@ -0,0 +1,13 @@
+
+#ifndef _ELEMENT_H
+#define _ELEMENT_H
+
+
+asn1_retCode _asn1_append_sequence_set(node_asn *node);
+
+asn1_retCode _asn1_convert_integer(char *value,unsigned char *value_out,
+                         int value_out_size, int *len);
+
+void _asn1_hierarchical_name(node_asn *node,char *name,int name_size);
+
+#endif
diff --git a/lib/errors.c b/lib/errors.c
new file mode 100644 (file)
index 0000000..1008171
--- /dev/null
@@ -0,0 +1,144 @@
+/*              Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <int.h>
+#include "errors.h"
+#ifdef STDC_HEADERS
+# include <stdarg.h>
+#endif
+
+
+#define LIBASN1_ERROR_ENTRY(name) \
+       { #name, name }
+
+struct libasn1_error_entry {
+       char *name;
+       int  number;
+};
+typedef struct libasn1_error_entry libasn1_error_entry;
+
+static libasn1_error_entry error_algorithms[] = {
+       LIBASN1_ERROR_ENTRY( ASN1_SUCCESS ),
+       LIBASN1_ERROR_ENTRY( ASN1_FILE_NOT_FOUND ),
+       LIBASN1_ERROR_ENTRY( ASN1_ELEMENT_NOT_FOUND ),
+       LIBASN1_ERROR_ENTRY( ASN1_IDENTIFIER_NOT_FOUND ),
+       LIBASN1_ERROR_ENTRY( ASN1_DER_ERROR ),
+       LIBASN1_ERROR_ENTRY( ASN1_VALUE_NOT_FOUND ),
+       LIBASN1_ERROR_ENTRY( ASN1_GENERIC_ERROR ),
+       LIBASN1_ERROR_ENTRY( ASN1_VALUE_NOT_VALID ),
+       LIBASN1_ERROR_ENTRY( ASN1_TAG_ERROR ),
+       LIBASN1_ERROR_ENTRY( ASN1_TAG_IMPLICIT ),
+       LIBASN1_ERROR_ENTRY( ASN1_ERROR_TYPE_ANY ),
+       LIBASN1_ERROR_ENTRY( ASN1_SYNTAX_ERROR ),
+       LIBASN1_ERROR_ENTRY( ASN1_MEM_ERROR ),
+       LIBASN1_ERROR_ENTRY( ASN1_DER_OVERFLOW ),
+       LIBASN1_ERROR_ENTRY( ASN1_NAME_TOO_LONG ),
+       LIBASN1_ERROR_ENTRY( ASN1_ARRAY_ERROR ),
+       LIBASN1_ERROR_ENTRY( ASN1_ELEMENT_NOT_EMPTY ),
+       {0}
+};
+
+#define LIBASN1_ERROR_LOOP(b) \
+        libasn1_error_entry *p; \
+                for(p = error_algorithms; p->name != NULL; p++) { b ; }
+
+#define LIBASN1_ERROR_ALG_LOOP(a) \
+                        LIBASN1_ERROR_LOOP( if(p->number == error) { a; break; } )
+
+
+
+/**
+  * libasn1_perror - prints a string to stderr with a description of an error
+  * @error: is an error returned by a libasn1 function. 
+  *
+  * This function is like perror(). The only difference is that it accepts an 
+  * error returned by a libasn1 function. 
+  **/
+void libasn1_perror(asn1_retCode error)
+{
+       char *ret = NULL;
+
+       /* avoid prefix */
+       LIBASN1_ERROR_ALG_LOOP(ret =
+                             _asn1_strdup(p->name + sizeof("ASN1_") - 1));
+
+       _libasn1_log( "LIBASN1 ERROR: %s\n", ret);
+       
+       _asn1_free( ret);
+}
+
+
+/**
+  * libasn1_strerror - Returns a string with a description of an error
+  * @error: is an error returned by a libasn1 function.
+  *
+  * This function is similar to strerror(). The only difference is that it 
+  * accepts an error (number) returned by a libasn1 function. 
+  **/
+const char* libasn1_strerror(asn1_retCode error)
+{
+       char *ret = NULL;
+
+       /* avoid prefix */
+       LIBASN1_ERROR_ALG_LOOP(ret =
+                             p->name + sizeof("ASN1_") - 1);
+
+       return ret;
+}
+
+/* this function will output a message.
+ */
+#ifdef DEBUG
+void _libasn1_log( const char *fmt, ...) {
+ va_list args;
+ char str[MAX_LOG_SIZE];
+
+ va_start(args,fmt);
+ vsprintf( str,fmt,args); /* Flawfinder: ignore */
+ va_end(args);   
+
+ fprintf(stderr, str);
+
+ return;
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/errors.h b/lib/errors.h
new file mode 100644 (file)
index 0000000..1e09211
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *      Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef ERRORS_H
+#define ERRORS_H
+
+
+#include "int.h"
+#include "errors_int.h"
+
+#ifdef DEBUG
+# ifdef __FILE__
+#  ifdef __LINE__
+#   define _libasn1_assert() fprintf(stderr, "LIBASN1_ASSERT: %s:%d\n", __FILE__,__LINE__);
+#  else
+#   define _libasn1_assert() 
+#  endif
+# else /* __FILE__ defined */
+#  define _libasn1_assert() 
+# endif
+#else /* no debug */
+# define _libasn1_assert() 
+#endif
+
+const char* libasn1_strerror(int error);
+void libasn1_perror(int error);
+
+#ifdef DEBUG
+ void _libasn1_log( const char *fmt, ...);
+#else
+# define _libasn1_log ( ...)
+#endif
+
+#endif /* ERRORS_H */
+
+
+
+
+
+
diff --git a/lib/errors_int.h b/lib/errors_int.h
new file mode 100644 (file)
index 0000000..351dd26
--- /dev/null
@@ -0,0 +1,23 @@
+/* libasn1 error codes. The mapping to a TLS alert is also shown in
+ * comments.
+ */
+
+#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_DER_OVERFLOW          13
+#define ASN1_NAME_TOO_LONG         14
+#define ASN1_ARRAY_ERROR           15
+#define ASN1_ELEMENT_NOT_EMPTY     16
+
+
diff --git a/lib/int.h b/lib/int.h
new file mode 100644 (file)
index 0000000..d2c5598
--- /dev/null
+++ b/lib/int.h
@@ -0,0 +1,166 @@
+/*
+ *      Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * GNUTLS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef INT_H
+
+#define INT_H
+
+#include <defines.h>
+
+
+#define DEBUG
+/*
+#define DEBUG_PARSER
+#define DEBUG_INTEGER
+*/
+
+
+#define MAX32 4294967295
+#define MAX24 16777215
+#define MAX16 65535
+
+#define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */
+#define MAX_NAME_SIZE 128 /* maximum number of characters of a name inside an ASN1 file definitons */
+#define MAX_ERROR_DESCRIPTION_SIZE 1024 /* maximum number of characters of a description message */
+
+
+/* define used for visiting trees */
+#define UP     1
+#define RIGHT  2
+#define DOWN   3
+
+
+typedef int asn1_retCode;  /* type returned by libasn1 functions */
+
+
+/******************************************************/
+/* Structure definition used for the node of the tree */
+/* that rappresent an ASN.1 DEFINITION.               */
+/******************************************************/
+typedef struct node_asn_struct{
+  char *name;                    /* Node name */
+  unsigned int type;             /* Node type */
+  unsigned char *value;          /* Node value */
+  struct node_asn_struct *down;  /* Pointer to the son node */
+  struct node_asn_struct *right; /* Pointer to the brother node */
+  struct node_asn_struct *left;  /* Pointer to the next list element */ 
+} node_asn;
+
+typedef node_asn* ASN1_TYPE;
+
+#define ASN1_TYPE_EMPTY  NULL
+
+struct static_struct_asn{
+  char *name;                    /* Node name */
+  unsigned int type;             /* Node type */
+  unsigned char *value;          /* Node value */
+};
+
+typedef struct static_struct_asn ASN1_ARRAY_TYPE;
+
+
+/****************************************/
+/* Returns the first 8 bits.            */
+/* Used with the field type of node_asn */
+/****************************************/
+#define type_field(x)     (x&0xFF) 
+
+
+/* List of constants for field type of typedef node_asn  */
+#define TYPE_CONSTANT     1
+#define TYPE_IDENTIFIER   2
+#define TYPE_INTEGER      3
+#define TYPE_BOOLEAN      4
+#define TYPE_SEQUENCE     5
+#define TYPE_BIT_STRING   6
+#define TYPE_OCTET_STRING 7
+#define TYPE_TAG          8
+#define TYPE_DEFAULT      9
+#define TYPE_SIZE        10
+#define TYPE_SEQUENCE_OF 11
+#define TYPE_OBJECT_ID   12
+#define TYPE_ANY         13
+#define TYPE_SET         14
+#define TYPE_SET_OF      15
+#define TYPE_DEFINITIONS 16
+#define TYPE_TIME        17
+#define TYPE_CHOICE      18
+#define TYPE_IMPORTS     19
+#define TYPE_NULL        20
+#define TYPE_ENUMERATED  21
+
+
+/***********************************************************************/
+/* List of constants for specify better the type of typedef node_asn.  */
+/***********************************************************************/
+/*  Used with TYPE_TAG  */
+#define CONST_UNIVERSAL   (1<<8)
+#define CONST_PRIVATE     (1<<9)
+#define CONST_APPLICATION (1<<10)
+#define CONST_EXPLICIT    (1<<11)
+#define CONST_IMPLICIT    (1<<12)
+
+#define CONST_TAG         (1<<13)  /*  Used in ASN.1 assignement  */
+#define CONST_OPTION      (1<<14)
+#define CONST_DEFAULT     (1<<15)
+#define CONST_TRUE        (1<<16)
+#define CONST_FALSE       (1<<17)
+
+#define CONST_LIST        (1<<18)  /*  Used with TYPE_INTEGER and TYPE_BIT_STRING  */
+#define CONST_MIN_MAX     (1<<19)
+
+#define CONST_1_PARAM     (1<<20)
+
+#define CONST_SIZE        (1<<21)
+
+#define CONST_DEFINED_BY  (1<<22)
+
+#define CONST_GENERALIZED (1<<23)
+#define CONST_UTC         (1<<24)
+
+// #define CONST_IMPORTS     (1<<25)
+
+#define CONST_NOT_USED    (1<<26)
+#define CONST_SET         (1<<27)
+#define CONST_ASSIGN      (1<<28)
+
+#define CONST_DOWN        (1<<29)
+#define CONST_RIGHT       (1<<30)
+
+
+/* functions */
+asn1_retCode asn1_delete_structure(ASN1_TYPE *structure);
+
+#endif /* INT_H */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/parser_aux.c b/lib/parser_aux.c
new file mode 100644 (file)
index 0000000..8f99bc4
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <int.h>
+#include <errors.h>
+#include "parser_aux.h"
+#include "der.h"
+#include "gstr.h"
+#include "structure.h"
+#include "element.h"
+
+extern char identifierMissing[];
+
+/***********************************************/
+/* Type: list_type                             */
+/* Description: type used in the list during   */
+/* the structure creation.                     */
+/***********************************************/
+typedef struct list_struct{
+  node_asn           *node;
+  struct list_struct *next;
+} list_type;
+
+
+/* Pointer to the first element of the list */
+list_type *firstElement=NULL;
+
+/******************************************************/
+/* Function : _asn1_add_node                          */
+/* Description: creates a new NODE_ASN element and    */
+/* puts it in the list pointed by firstElement.       */
+/* Parameters:                                        */
+/*   type: type of the new element (see TYPE_         */
+/*         and CONST_ constants).                     */
+/* Return: pointer to the new element.                */
+/******************************************************/
+node_asn *
+_asn1_add_node(unsigned int type)
+{
+  list_type *listElement;
+  node_asn *punt;
+
+  punt=(node_asn *) _asn1_malloc(sizeof(node_asn));
+  if (punt==NULL) return NULL;
+  
+  listElement=(list_type *) _asn1_malloc(sizeof(list_type));
+  if(listElement==NULL){
+    _asn1_free(punt);
+    return NULL;
+  }
+
+  listElement->node=punt;
+  listElement->next=firstElement;
+  firstElement=listElement;
+
+  punt->left=NULL;
+  punt->name=NULL;
+  punt->type=type; 
+  punt->value=NULL;
+  punt->down=NULL;
+  punt->right=NULL; 
+
+  return punt;
+}
+
+/******************************************************************/
+/* Function : _asn1_find_mode                                     */
+/* Description: searches an element called NAME starting from     */
+/*              POINTER. The name is composed by differents       */
+/*              identifiers separated by dot.The first identifier */
+/*              must be the name of *POINTER.                     */
+/* Parameters:                                                    */
+/*   pointer: NODE_ASN element pointer.                           */
+/*   name: null terminated string with the element's name to find.*/
+/* Return: the searching result. NULL if not find.                */
+/******************************************************************/
+node_asn *
+_asn1_find_node(node_asn *pointer,char *name)
+{
+  node_asn *p;
+  char *n_start,*n_end,n[128];
+
+  if((name==NULL) || (name[0]==0)) return NULL;
+
+  n_start=name;
+  n_end=strchr(n_start,'.');     /* search the first dot */
+  if(n_end){
+    memcpy(n,n_start,n_end-n_start);
+    n[n_end-n_start]=0;
+    n_start=n_end;
+    n_start++;
+  }
+  else{
+    _asn1_str_cpy(n,sizeof(n),n_start);
+    n_start=NULL;
+  }
+
+  p=pointer;
+  while(p){
+    if((p->name) && (!strcmp(p->name,n))) break;
+    else p=p->right;
+  } /* while */
+
+  if(p==NULL) return NULL;
+
+  while(n_start){   /* Has the end of NAME been reached? */
+    n_end=strchr(n_start,'.');    /* search the next dot */
+    if(n_end){
+      memcpy(n,n_start,n_end-n_start);
+      n[n_end-n_start]=0;
+      n_start=n_end;
+      n_start++;
+    }
+    else{
+      _asn1_str_cpy(n,sizeof(n),n_start);
+      n_start=NULL;
+    }
+
+    if(p->down==NULL) return NULL;
+
+    p=p->down;
+
+    /* The identifier "?LAST" indicates the last element 
+       in the right chain. */
+    if(!strcmp(n,"?LAST")){
+      if(p==NULL) return NULL;
+      while(p->right) p=p->right;
+    }
+    else{   /* no "?LAST" */
+      while(p){
+       if((p->name) && (!strcmp(p->name,n))) break;
+       else p=p->right;
+      }
+      if(p==NULL) return NULL;
+    }
+  } /* while */
+
+  return p;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_set_value                                     */
+/* Description: sets the field VALUE in a NODE_ASN element. The   */
+/*              previus 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.                       */
+/******************************************************************/
+node_asn *
+_asn1_set_value(node_asn *node,unsigned char *value,unsigned int len)
+{
+
+  if(node==NULL) return node;
+  if(node->value){
+    _asn1_free(node->value);
+    node->value=NULL;  
+  }
+  if(!len) return node;
+  node->value=(unsigned char *) _asn1_malloc(len);
+  if (node->value==NULL) return NULL;
+  
+  memcpy(node->value,value,len);
+  return node;
+}
+
+/******************************************************************/
+/* Function : _asn1_set_name                                      */
+/* Description: sets the field NAME in a NODE_ASN element. The    */
+/*              previus 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.                       */
+/******************************************************************/
+node_asn *
+_asn1_set_name(node_asn *node,char *name)
+{
+  if(node==NULL) return node;
+
+  if(node->name){
+    _asn1_free(node->name);
+    node->name=NULL;
+  }
+
+  if(name==NULL) return node;
+
+  if(strlen(name))
+       {
+       node->name=(char *) _asn1_strdup( name);
+       if (node->name==NULL) return NULL;
+      }
+  else node->name=NULL;
+  return node;
+}
+
+/******************************************************************/
+/* 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.                                      */
+/******************************************************************/
+node_asn *
+_asn1_set_right(node_asn *node,node_asn *right)
+{
+  if(node==NULL) return node;
+  node->right=right;
+  if(right) right->left=node;
+  return 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.                                   */
+/******************************************************************/
+node_asn *
+_asn1_get_right(node_asn *node)
+{
+  if(node==NULL) return NULL;
+  return node->right;
+}
+
+/******************************************************************/
+/* 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.     */
+/******************************************************************/
+node_asn *
+_asn1_get_last_right(node_asn *node)
+{
+  node_asn *p;
+
+  if(node==NULL) return NULL;
+  p=node;
+  while(p->right) p=p->right;
+  return p;
+}
+
+/******************************************************************/
+/* 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.                                      */
+/******************************************************************/
+node_asn *
+_asn1_set_down(node_asn *node,node_asn *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.                                    */
+/******************************************************************/
+node_asn *
+_asn1_get_down(node_asn *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.                              */
+/******************************************************************/
+char *
+_asn1_get_name(node_asn *node)
+{
+  if(node==NULL) return NULL;
+  return 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.                                          */
+/******************************************************************/
+node_asn *
+_asn1_mod_type(node_asn *node,unsigned int value)
+{
+  if(node==NULL) return node;
+  node->type|=value;
+  return node;
+}
+
+
+/******************************************************************/
+/* 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.                              */
+/******************************************************************/
+void
+_asn1_remove_node(node_asn *node)
+{
+  if(node==NULL) return;
+
+  if (node->name!=NULL)
+         _asn1_free(node->name);
+  if (node->value!=NULL)
+         _asn1_free(node->value);
+  _asn1_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.                                     */ 
+/******************************************************************/
+node_asn *
+_asn1_find_up(node_asn *node)
+{
+  node_asn *p;
+
+  if(node==NULL) return NULL;
+
+  p=node;
+
+  while((p->left!=NULL) && (p->left->right==p)) p=p->left;
+
+  return p->left;
+}
+
+/******************************************************************/
+/* Function : _asn1_delete_list                                   */
+/* Description: deletes the list elements (not the elements       */
+/*  pointed by them).                                             */
+/******************************************************************/
+void
+_asn1_delete_list(void)
+{
+  list_type *listElement;
+
+  while(firstElement){
+    listElement=firstElement;
+    firstElement=firstElement->next;
+    _asn1_free(listElement);
+  }
+}
+
+/******************************************************************/
+/* Function : _asn1_delete_list_and nodes                         */
+/* Description: deletes the list elements and the elements        */
+/*  pointed by them.                                              */
+/******************************************************************/
+void
+_asn1_delete_list_and_nodes(void)
+{
+  list_type *listElement;
+
+  while(firstElement){
+    listElement=firstElement;
+    firstElement=firstElement->next;
+    _asn1_remove_node(listElement->node);
+    _asn1_free(listElement);
+  }
+}
+
+
+char *
+_asn1_ltostr(long v,char *str)
+{
+  long d,r;
+  char temp[20];
+  int count,k,start;
+
+  if(v<0){
+    str[0]='-';
+    start=1;
+    v=-v;
+  }
+  else start=0;
+
+  count=0;
+  do{
+    d=v/10;
+    r=v-d*10;
+    temp[start+count]='0'+(char)r;
+    count++;
+    v=d;
+  }while(v);
+
+  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                                             */
+/******************************************************************/
+asn1_retCode 
+_asn1_change_integer_value(ASN1_TYPE node)
+{
+  node_asn *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)==TYPE_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->right){
+           p=p->right;
+           break;
+         }
+       }
+      }
+    }
+  }
+
+  return ASN1_SUCCESS;
+}
+
+
+/******************************************************************/
+/* Function : _asn1_expand_object_id                              */
+/* Description: expand the IDs of an OBJECT IDENTIFIER constant.  */
+/* Parameters:                                                    */
+/*   node: root of an ASN1 element.                               */
+/* Return:                                                        */
+/*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
+/*   otherwise ASN1_SUCCESS                                             */
+/******************************************************************/
+asn1_retCode
+_asn1_expand_object_id(ASN1_TYPE node)
+{
+  node_asn *p,*p2,*p3,*p4,*p5;
+  char name_root[129],name2[129];
+  int move;
+  if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
+
+  _asn1_str_cpy(name_root, sizeof(name_root), node->name);
+
+  p=node;
+  move=DOWN;
+
+  while(!((p==node) && (move==UP))){
+    if(move!=UP){
+      if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){
+       p2=p->down;
+        if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
+         if(p2->value && !isdigit(p2->value[0])){
+           _asn1_str_cpy(name2, sizeof(name2), name_root);
+           _asn1_str_cat(name2, sizeof(name2), ".");
+           _asn1_str_cat(name2, sizeof(name2), p2->value);
+           p3=_asn1_find_node(node,name2);
+           if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) ||
+              !(p3->type&CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND;
+           _asn1_set_down(p,p2->right);
+           _asn1_remove_node(p2);
+           p2=p;
+           p4=p3->down;
+           while(p4){
+             if(type_field(p4->type)==TYPE_CONSTANT){
+               p5=_asn1_add_node_only(TYPE_CONSTANT);
+               _asn1_set_name(p5,p4->name);
+               _asn1_set_value(p5,p4->value,strlen(p4->value)+1);
+               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;
+           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;
+}
+
+
+/******************************************************************/
+/* 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                                             */
+/******************************************************************/
+asn1_retCode 
+_asn1_type_set_config(ASN1_TYPE node)
+{
+  node_asn *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)==TYPE_SET){
+       p2=p->down;
+       while(p2){
+         if(type_field(p2->type)!=TYPE_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->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 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                                             */
+/******************************************************************/
+asn1_retCode 
+_asn1_check_identifier(ASN1_TYPE node)
+{
+  node_asn *p,*p2;
+  char name2[MAX_NAME_SIZE*2+2];
+
+  if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
+
+  p=node;
+  while(p){
+    if(type_field(p->type)==TYPE_IDENTIFIER){
+      _asn1_str_cpy(name2, sizeof(name2), node->name);
+      _asn1_str_cat(name2, sizeof(name2), ".");
+      _asn1_str_cat(name2, sizeof(name2), p->value);
+      p2=_asn1_find_node(node,name2);
+      if(p2==NULL){
+       strcpy(identifierMissing,p->value);
+       return ASN1_IDENTIFIER_NOT_FOUND;
+      } 
+    }
+    else if((type_field(p->type)==TYPE_OBJECT_ID) && 
+           (p->type&CONST_ASSIGN)){
+      p2=p->down;
+      if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
+       if(p2->value && !isdigit(p2->value[0])){
+         _asn1_str_cpy(name2, sizeof(name2), node->name);
+         _asn1_str_cat(name2, sizeof(name2), ".");
+         _asn1_str_cat(name2, sizeof(name2), p2->value);
+         strcpy(identifierMissing,p2->value);
+         p2=_asn1_find_node(node,name2);
+         if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) ||
+            !(p2->type&CONST_ASSIGN))
+           return ASN1_IDENTIFIER_NOT_FOUND;
+         else
+           identifierMissing[0]=0;
+       }
+      }
+    }
+    
+    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->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                                             */
+/******************************************************************/
+asn1_retCode 
+_asn1_set_default_tag(ASN1_TYPE node)
+{
+  node_asn *p;
+
+  if((node==NULL) || (type_field(node->type)!=TYPE_DEFINITIONS))
+    return ASN1_ELEMENT_NOT_FOUND; 
+
+  p=node;
+  while(p){
+    if((type_field(p->type)==TYPE_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->right){
+           p=p->right;
+           break;
+         }
+      }
+    }
+  }
+
+  return ASN1_SUCCESS;
+}
+
+
+
+
diff --git a/lib/parser_aux.h b/lib/parser_aux.h
new file mode 100644 (file)
index 0000000..937df66
--- /dev/null
@@ -0,0 +1,65 @@
+
+#ifndef _PARSER_AUX_H
+#define _PARSER_AUX_H
+
+
+/***************************************/
+/*  Functions used by ASN.1 parser     */
+/***************************************/
+node_asn *
+_asn1_add_node(unsigned int type);
+
+node_asn *
+_asn1_set_value(node_asn *node,unsigned char *value,unsigned int len);
+
+node_asn *
+_asn1_set_name(node_asn *node,char *name);
+
+node_asn *
+_asn1_set_right(node_asn *node,node_asn *right);
+
+node_asn *
+_asn1_get_right(node_asn *node);
+
+node_asn *
+_asn1_get_last_right(node_asn *node);
+
+node_asn *
+_asn1_set_down(node_asn *node,node_asn *down);
+
+char *
+_asn1_get_name(node_asn *node);
+
+node_asn *
+_asn1_get_down(node_asn *node);
+
+node_asn *
+_asn1_mod_type(node_asn *node,unsigned int value);
+
+void
+_asn1_remove_node(node_asn *node);
+
+void _asn1_delete_list(void);
+
+void _asn1_delete_list_and_nodes(void);
+
+char * _asn1_ltostr(long v,char *str);
+
+node_asn * _asn1_find_up(node_asn *node);
+
+node_asn * _asn1_find_node(node_asn *pointer,char *name);
+
+asn1_retCode _asn1_change_integer_value(ASN1_TYPE node);
+
+asn1_retCode _asn1_expand_object_id(ASN1_TYPE node);
+
+asn1_retCode _asn1_type_set_config(ASN1_TYPE node);
+
+asn1_retCode _asn1_check_identifier(ASN1_TYPE node);
+
+asn1_retCode _asn1_set_default_tag(ASN1_TYPE node);
+
+#endif
+
+
+
diff --git a/lib/structure.c b/lib/structure.c
new file mode 100644 (file)
index 0000000..1467f44
--- /dev/null
@@ -0,0 +1,855 @@
+/*
+ *      Copyright (C) 2002  Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: structure.c                                 */
+/* Description: Functions to create and delete an    */
+/*  ASN1 tree.                                       */
+/*****************************************************/
+
+
+#include <int.h>
+#include <errors.h>
+#include <structure.h>
+#include "parser_aux.h"
+#include "der.h"
+#include <gstr.h>
+
+
+extern char identifierMissing[];
+
+
+/******************************************************/
+/* Function : _asn1_add_node_only                     */
+/* Description: creates a new NODE_ASN element.       */ 
+/* Parameters:                                        */
+/*   type: type of the new element (see TYPE_         */
+/*         and CONST_ constants).                     */
+/* Return: pointer to the new element.                */
+/******************************************************/
+node_asn *
+_asn1_add_node_only(unsigned int type)
+{
+  node_asn *punt;
+
+  punt=(node_asn *) _asn1_malloc(sizeof(node_asn));
+  if (punt==NULL) return NULL;
+  
+  punt->left=NULL;
+  punt->name=NULL;
+  punt->type=type; 
+  punt->value=NULL;
+  punt->down=NULL;
+  punt->right=NULL; 
+
+  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.                                     */
+/******************************************************************/
+node_asn *
+_asn1_find_left(node_asn *node)
+{
+  if((node==NULL) || (node->left==NULL) || 
+     (node->left->down==node)) return NULL;
+
+  return node->left;  
+}
+
+
+asn1_retCode
+_asn1_create_static_structure(ASN1_TYPE pointer,char* output_file_name,char *vector_name)
+{
+  FILE *file;  
+  node_asn *p;
+  unsigned long t;
+
+  file=fopen( output_file_name,"w");
+  
+  if(file==NULL) return ASN1_FILE_NOT_FOUND;
+
+  fprintf(file,"\n#include \"libasn1.h\"\n\n");
+  fprintf(file,"const ASN1_ARRAY_TYPE %s[]={\n",vector_name);
+
+  p=pointer;
+
+  while(p){
+    fprintf(file,"  {");
+
+    if(p->name) fprintf(file,"\"%s\",",p->name);
+    else fprintf(file,"0,");
+    
+   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,"0},\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,"  {0,0,0}\n};\n");
+
+ fclose(file);
+
+ return ASN1_SUCCESS;
+}
+
+
+/**
+  * asn1_array2tree - Creates the structures needed to manage the ASN1 definitions.
+  * @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.
+  * Description:
+  *
+  * Creates the structures needed to manage the ASN1 definitions. ARRAY is a vector created by
+  * 'asn1_parser_asn1_file_c' function.
+  *
+  * Returns:
+  *
+  *  ASN1_SUCCESS\: structure created correctly. 
+  *
+  * ASN1_ELEMENT_NOT_EMPTY\: *DEFINITIONS not ASN1_TYPE_EMPTY
+  *
+  * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined (see ERRORDESCRIPTION for more information).
+  *
+  *  ASN1_ARRAY_ERROR\: the array pointed by ARRAY is wrong.  
+  **/
+asn1_retCode
+asn1_array2tree(const ASN1_ARRAY_TYPE *array,ASN1_TYPE *definitions,
+                 char *errorDescription)
+{
+  node_asn *p,*p_last=NULL;
+  unsigned long k;
+  int move;
+  asn1_retCode result;
+
+
+  if(*definitions != ASN1_TYPE_EMPTY)
+    return ASN1_ELEMENT_NOT_EMPTY;
+
+  move=UP;
+
+  k=0;
+  while(array[k].value || array[k].type || array[k].name){
+    p=_asn1_add_node(array[k].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) _asn1_set_down(p_last,p);
+    else if(move==RIGHT) _asn1_set_right(p_last,p);
+
+    p_last=p;
+
+    if(array[k].type&CONST_DOWN) move=DOWN;
+    else if(array[k].type&CONST_RIGHT) move=RIGHT;
+    else{
+      while(1){
+       if(p_last==*definitions) break;
+   
+       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 */
+    }
+    k++;
+  }  /* while */
+
+  if(p_last==*definitions){
+    result=_asn1_check_identifier(*definitions);
+    if(result==ASN1_SUCCESS){
+      _asn1_change_integer_value(*definitions);
+      _asn1_expand_object_id(*definitions);
+    }
+  }
+  else{
+    result=ASN1_ARRAY_ERROR;
+  }
+
+  if(result==ASN1_IDENTIFIER_NOT_FOUND){
+    strcpy(errorDescription,":: identifier '");
+    strcat(errorDescription,identifierMissing);
+    strcat(errorDescription,"' not found");
+  }
+  else
+    errorDescription[0]=0;
+
+  if(result != ASN1_SUCCESS){
+    _asn1_delete_list_and_nodes();
+    *definitions=ASN1_TYPE_EMPTY;
+  }
+  else
+    _asn1_delete_list();
+
+  return result;
+}
+
+
+/**
+  * asn1_delete_structure - Deletes the structure pointed by *ROOT. 
+  * @structure: pointer to the structure that you want to delete.
+  * Description:
+  * 
+  * Deletes the structure *ROOT. 
+  * At the end *ROOT is setted to ASN1_TYPE_EMPTY. 
+  * 
+  * Returns:
+  *
+  *   ASN1_SUCCESS\: everything OK
+  *
+  *   ASN1_ELEMENT_NOT_FOUND\: *root==ASN1_TYPE_EMPTY.
+  *
+  **/
+asn1_retCode
+asn1_delete_structure(ASN1_TYPE *structure)
+{
+  node_asn *p,*p2,*p3;
+
+  if(*structure==ASN1_TYPE_EMPTY) 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);
+       _asn1_remove_node(p);
+       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);
+       _asn1_remove_node(p);
+       p=NULL;
+      }
+    }
+  }
+
+  *structure=ASN1_TYPE_EMPTY;
+  return ASN1_SUCCESS;
+}
+
+
+
+node_asn *
+_asn1_copy_structure3(node_asn *source_node)
+{
+  node_asn *dest_node,*p_s,*p_d,*p_d_prev;
+  int len,len2,move;
+
+  if(source_node==NULL) return NULL;
+
+  dest_node=_asn1_add_node_only(source_node->type);
+
+  p_s=source_node;
+  p_d=dest_node;
+
+  move=DOWN;
+
+  do{
+    if(move!=UP){
+      if(p_s->name) _asn1_set_name(p_d,p_s->name);
+      if(p_s->value){
+       switch(type_field(p_s->type)){
+       case TYPE_OCTET_STRING: case TYPE_BIT_STRING: 
+       case TYPE_INTEGER:           // case TYPE_DEFAULT:
+         len2=-1;
+         len=_asn1_get_length_der(p_s->value,&len2);
+         _asn1_set_value(p_d,p_s->value,len+len2);
+         break;
+       default:
+         _asn1_set_value(p_d,p_s->value,strlen(p_s->value)+1);
+       }
+      }
+      move=DOWN;
+    }
+    else move=RIGHT;
+
+    if(move==DOWN){
+      if(p_s->down){
+       p_s=p_s->down;
+       p_d_prev=p_d;      
+       p_d=_asn1_add_node_only(p_s->type);
+       _asn1_set_down(p_d_prev,p_d);
+      }
+      else move=RIGHT;
+    }
+  
+    if(p_s==source_node) break;
+
+    if(move==RIGHT){
+      if(p_s->right){
+       p_s=p_s->right;
+       p_d_prev=p_d;
+       p_d=_asn1_add_node_only(p_s->type);
+       _asn1_set_right(p_d_prev,p_d);
+      }
+      else move=UP;
+    }
+    if(move==UP){
+      p_s=_asn1_find_up(p_s);
+      p_d=_asn1_find_up(p_d);
+    }
+  }while(p_s!=source_node);
+
+  return dest_node;
+}
+
+
+node_asn *
+_asn1_copy_structure2(node_asn *root,char *source_name)
+{
+  node_asn *source_node;
+
+  source_node=_asn1_find_node(root,source_name);
+  
+  return _asn1_copy_structure3(source_node);
+
+}
+
+
+asn1_retCode 
+_asn1_type_choice_config(node_asn *node)
+{
+  node_asn *p,*p2,*p3,*p4;
+  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)==TYPE_CHOICE) &&
+        (p->type&CONST_TAG)){
+       p2=p->down;
+       while(p2){
+         if(type_field(p2->type)!=TYPE_TAG){
+           p2->type|=CONST_TAG;
+           p3=_asn1_find_left(p2);
+           while(p3){
+             if(type_field(p3->type)==TYPE_TAG){
+               p4=_asn1_add_node_only(p3->type);
+               _asn1_set_value(p4,p3->value,strlen(p3->value)+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)==TYPE_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;
+}
+
+
+asn1_retCode 
+_asn1_expand_identifier(node_asn **node,node_asn *root)
+{
+  node_asn *p,*p2,*p3;
+  char name2[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)==TYPE_IDENTIFIER){
+       _asn1_str_cpy(name2, sizeof(name2), root->name);
+       _asn1_str_cat(name2, sizeof(name2), ".");
+       _asn1_str_cat(name2, sizeof(name2), p->value);
+       p2=_asn1_copy_structure2(root,name2);
+       if(p2==NULL){
+         return ASN1_IDENTIFIER_NOT_FOUND;
+       }
+       _asn1_set_name(p2,p->name);
+       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);
+       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 - Creates a structure called DEST_NAME of type SOURCE_NAME.
+  * @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. 
+  * @dest_name: the name of the new structure.
+  * Description:
+  *
+  * Creates a structure called DEST_NAME of type SOURCE_NAME.
+  *
+  * Returns:
+  *
+  *  ASN1_SUCCESS\: creation OK
+  *
+  *  ASN1_ELEMENT_NOT_EMPTY\: *POINTER not ASN1_TYPE_EMPTY
+  *
+  *  ASN1_ELEMENT_NOT_FOUND\: SOURCE_NAME isn't known
+  * 
+  * Example: using "pkix.asn"
+  *  result=asn1_create_structure(cert_def,"PKIX1.Certificate",&cert,"certificate1");
+  **/
+asn1_retCode
+asn1_create_element(ASN1_TYPE definitions,char *source_name,ASN1_TYPE *element,char *dest_name)
+{
+  node_asn *dest_node;
+  int res;
+
+  if(*element!=ASN1_TYPE_EMPTY)
+    return ASN1_ELEMENT_NOT_EMPTY;
+
+  dest_node=_asn1_copy_structure2(definitions,source_name);
+  if(dest_node==NULL) return ASN1_ELEMENT_NOT_FOUND;
+
+  _asn1_set_name(dest_node,dest_name);
+
+  res=_asn1_expand_identifier(&dest_node,definitions);
+  _asn1_type_choice_config(dest_node);
+
+  *element=dest_node;
+
+  return res;
+}
+
+
+/**
+  * asn1_print_structure - Prints on the standard output the structure's tree
+  * @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
+  * 
+  * Prints on the standard output the structure's tree starting from the NAME element inside
+  * the structure *POINTER. 
+  **/
+void
+asn1_print_structure(FILE *out,ASN1_TYPE structure,char *name,int mode)
+{
+  node_asn *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) fprintf(out,"%s  ",p->name);
+      else fprintf(out,"NULL  ");
+    }
+    else{
+      switch(type_field(p->type)){
+      case TYPE_CONSTANT:
+      case TYPE_TAG:
+      case TYPE_SIZE:
+       break;
+      default:
+       for(k=0;k<indent;k++)fprintf(out," ");
+       fprintf(out,"name:");
+       if(p->name) fprintf(out,"%s  ",p->name);
+       else fprintf(out,"NULL  ");
+      }
+    }
+
+    if(mode != ASN1_PRINT_NAME){
+      switch(type_field(p->type)){
+      case TYPE_CONSTANT:
+       if(mode == ASN1_PRINT_ALL)
+         fprintf(out,"type:CONST");break;
+      case TYPE_TAG:
+       if(mode == ASN1_PRINT_ALL)
+         fprintf(out,"type:TAG");break;
+      case TYPE_SIZE:
+       if(mode == ASN1_PRINT_ALL)
+         fprintf(out,"type:SIZE");break;
+      case TYPE_DEFAULT:
+       fprintf(out,"type:DEFAULT");break;
+      case TYPE_NULL:
+       fprintf(out,"type:NULL");break;
+      case TYPE_IDENTIFIER:
+       fprintf(out,"type:IDENTIFIER");break;
+      case TYPE_INTEGER:
+       fprintf(out,"type:INTEGER");break;
+      case TYPE_ENUMERATED:
+       fprintf(out,"type:ENUMERATED");break;
+      case TYPE_TIME:
+       fprintf(out,"type:TIME");break;
+      case TYPE_BOOLEAN:
+       fprintf(out,"type:BOOLEAN");break;
+      case TYPE_SEQUENCE:
+       fprintf(out,"type:SEQUENCE");break;
+      case TYPE_BIT_STRING:
+       fprintf(out,"type:BIT_STR");break;
+      case TYPE_OCTET_STRING:
+       fprintf(out,"type:OCT_STR");break;
+      case TYPE_SEQUENCE_OF:
+       fprintf(out,"type:SEQ_OF");break;
+      case TYPE_OBJECT_ID:
+       fprintf(out,"type:OBJ_ID");break;
+      case TYPE_ANY:
+       fprintf(out,"type:ANY");break;
+      case TYPE_SET:
+       fprintf(out,"type:SET");break;
+      case TYPE_SET_OF:
+       fprintf(out,"type:SET_OF");break;
+      case TYPE_CHOICE:
+       fprintf(out,"type:CHOICE");break;
+      case TYPE_DEFINITIONS:
+       fprintf(out,"type:DEFINITIONS");break;
+      default:
+       break;
+      }
+    }
+
+    if((mode == ASN1_PRINT_NAME_TYPE_VALUE) ||
+       (mode == ASN1_PRINT_ALL)){
+      switch(type_field(p->type)){
+      case TYPE_CONSTANT:
+       if(mode == ASN1_PRINT_ALL)
+         if(p->value) fprintf(out,"  value:%s",p->value);
+       break;
+      case TYPE_TAG:
+       if(mode == ASN1_PRINT_ALL)
+         fprintf(out,"  value:%s",p->value);
+       break;
+      case TYPE_SIZE:
+       if(mode == ASN1_PRINT_ALL)
+         if(p->value) fprintf(out,"  value:%s",p->value);
+       break;
+      case TYPE_DEFAULT:
+       if(p->value) fprintf(out,"  value:%s",p->value);
+       break;
+      case TYPE_IDENTIFIER:
+       if(p->value) fprintf(out,"  value:%s",p->value);
+       break;
+      case TYPE_INTEGER:
+       if(p->value){
+         len2=-1;
+         len=_asn1_get_length_der(p->value,&len2);
+         fprintf(out,"  value:0x");
+         for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+       }
+       break;
+      case TYPE_ENUMERATED:
+       if(p->value){
+         len2=-1;
+         len=_asn1_get_length_der(p->value,&len2);
+         fprintf(out,"  value:0x");
+         for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+       }
+       break;
+      case TYPE_TIME:
+       if(p->value) fprintf(out,"  value:%s",p->value);
+       break;
+      case TYPE_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 TYPE_BIT_STRING:
+       if(p->value){
+         len2=-1;
+         len=_asn1_get_length_der(p->value,&len2);
+         fprintf(out,"value(%i):",(len-1)*8-(p->value[len2]));
+         for(k=1;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+       }
+       break;
+      case TYPE_OCTET_STRING:
+       if(p->value){
+         len2=-1;
+         len=_asn1_get_length_der(p->value,&len2);
+         fprintf(out,"  value:");
+         for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+       }
+       break;
+      case TYPE_OBJECT_ID:
+       if(p->value) fprintf(out,"  value:%s",p->value);
+       break;
+      case TYPE_ANY:
+       if(p->value){
+         len3=-1;
+         len2=_asn1_get_length_der(p->value,&len3);
+         fprintf(out,"value:");
+         for(k=0;k<len2;k++) fprintf(out,"%02x",(p->value)[k+len3]);
+       }
+       break;
+      case TYPE_SET:
+      case TYPE_SET_OF:
+      case TYPE_CHOICE:
+      case TYPE_DEFINITIONS:
+      case TYPE_SEQUENCE_OF:
+      case TYPE_SEQUENCE:
+      case TYPE_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 TYPE_CONSTANT:
+      case TYPE_TAG:
+      case TYPE_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 - Counts the number of elements of a structure.
+  * @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 
+  * Description:
+  *
+  * Counts the number of elements of a sub-structure called NAME with names equal to "?1","?2", ...
+  *
+  * Returns:
+  *
+  *  ASN1_SUCCESS: creation OK
+  *  ASN1_ELEMENT_NOT_FOUND: NAME isn't known
+  *  ASN1_GENERIC_ERROR: pointer num equal to NULL
+  *
+  **/
+asn1_retCode 
+asn1_number_of_elements(ASN1_TYPE element,char *name,int *num)
+{
+  node_asn *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) && (p->name[0]=='?')) (*num)++; 
+    p=p->right;
+  }
+
+  return ASN1_SUCCESS;
+}
+
+
+
+
+
+
+
+
+
diff --git a/lib/structure.h b/lib/structure.h
new file mode 100644 (file)
index 0000000..8309761
--- /dev/null
@@ -0,0 +1,33 @@
+
+/*************************************************/
+/* File: structure.h                             */
+/* Description: list of exported object by       */
+/*   "structure.c"                               */
+/*************************************************/
+
+#ifndef _STRUCTURE_H
+#define _STRUCTURE_H
+
+
+/*************************************/
+/* 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
+
+
+asn1_retCode _asn1_create_static_structure(node_asn *pointer,
+       char* output_file_name,char *vector_name);
+
+node_asn* _asn1_copy_structure3(node_asn *source_node);
+
+node_asn* _asn1_copy_structure2(node_asn *root,char *source_name);
+
+node_asn * _asn1_add_node_only(unsigned int type);
+
+node_asn * _asn1_find_left(node_asn *node);
+
+#endif
+
diff --git a/src/asn1Coding.c b/src/asn1Coding.c
new file mode 100644 (file)
index 0000000..ab92f77
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ *      Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: asn1Coding.c                                */
+/* Description: program to generate a DER coding     */
+/*              of an ASN1 definition.               */   
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <libasn1.h>
+#include <malloc.h>
+#include <config.h>
+
+#ifdef HAVE_GETOPT_H
+  #include <getopt.h>
+#endif
+
+char version_man[] = "asn1Coding (GNU libasn1) " VERSION;
+
+char help_man[] = "asn1Coding generates a DER encoding from a file\n"
+                  "with ASN1 definitions and another one with assignments.\n"
+                  "\n"
+                  "Usage: asn1Coding [options] <file1> <file2>\n"
+                  " <file1> file with ASN1 definitions.\n"
+                  " <file2> file with assignments.\n"
+                  "\n"
+#ifdef HAVE_GETOPT_H
+                  "Operation modes:\n"
+                  "  -h, --help    shows this message and exit.\n"
+                  "  -v, --version shows version information and exit.\n"
+                  "  -c, --check   checks the syntax only.\n"
+                  "\n"
+                  "Output:\n"
+                  "  -o <file>, --output <file>  output file.\n";
+#else
+                  "Operation modes:\n"
+                  "  -h    shows this message and exit.\n"
+                  "  -v    shows version information and exit.\n"
+                  "  -c    checks the syntax only.\n"
+                  "\n"
+                  "Output:\n"
+                  "  -o <file>  output file.\n";
+#endif
+
+
+#define ASSIGNMENT_SUCCESS 1
+#define ASSIGNMENT_ERROR   2
+#define ASSIGNMENT_EOF     3
+
+int readAssignment(FILE *file,char *varName, char *value){
+
+  int ret;
+
+  ret=fscanf(file,"%s",varName);
+  if(ret==EOF) return ASSIGNMENT_EOF;
+
+  ret=fscanf(file,"%s",value);
+  if(ret==EOF) return ASSIGNMENT_ERROR;
+
+  return ASSIGNMENT_SUCCESS;
+}
+
+
+
+void createFileName(char *inputFileName, char **outputFileName)
+{
+ char *char_p,*slash_p,*dot_p;
+
+ /* searching the last '/' and '.' in inputFileAssignmentName */
+ char_p=inputFileName;
+ slash_p=inputFileName;
+ while((char_p=strchr(char_p,'/'))){
+   char_p++;
+     slash_p=char_p;
+ }
+ char_p=slash_p;
+ dot_p=inputFileName+strlen(inputFileName);
+ while((char_p=strchr(char_p,'.'))){
+   dot_p=char_p;
+   char_p++;
+ }
+ /* outputFileName= inputFileName + .out */
+ *outputFileName=(char *)malloc(dot_p-inputFileName+1+
+                              strlen(".out"));
+ memcpy(*outputFileName,inputFileName,
+          dot_p-inputFileName);
+ (*outputFileName)[dot_p-inputFileName]=0;
+ strcat(*outputFileName,".out");
+ return;
+}
+
+
+/********************************************************/
+/* Function : main                                      */
+/* Description:                                         */
+/********************************************************/
+int
+main(int argc,char *argv[])
+{
+
+#ifdef HAVE_GETOPT_H
+  static struct option long_options[] =
+  {
+    {"help",    no_argument,       0, 'h'},
+    {"version", no_argument,       0, 'v'},
+    {"check",   no_argument,       0, 'c'},
+    {"output",  required_argument, 0, 'o'},
+    {0, 0, 0, 0}
+  };
+#endif
+
+ int option_result;
+ int option_index = 0;
+ char *outputFileName=NULL;
+ char *inputFileAsnName=NULL;
+ char *inputFileAssignmentName=NULL;
+ int checkSyntaxOnly=0;
+ ASN1_TYPE definitions=ASN1_TYPE_EMPTY;
+ ASN1_TYPE structure=ASN1_TYPE_EMPTY;
+ char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
+ int asn1_result=ASN1_SUCCESS;
+ FILE *outputFile;
+ FILE *inputFile;
+ char varName[1024];
+ char value[1024];
+ char structureName[1024];
+ unsigned char der[1024];
+ int  der_len;
+ int  k;
+
+ opterr=0; /* disable error messages from getopt */
+
+ printf("\n");
+
+ while(1){
+
+#ifdef HAVE_GETOPT_H
+   option_result=getopt_long(argc,argv,"hvco:",long_options,&option_index);
+#else
+   option_result=getopt(argc,argv,"hvco:");
+#endif
+
+   if(option_result == -1) break;
+
+   switch(option_result){
+   case 'h':  /* HELP */
+     printf("%s\n",help_man);
+
+     if(outputFileName) free(outputFileName);
+     exit(0);
+     break;
+   case 'v':  /* VERSION */
+     printf("%s\n",version_man);
+
+     if(outputFileName) free(outputFileName);
+     exit(0);
+     break;
+   case 'c':  /* CHECK SYNTAX */
+     checkSyntaxOnly = 1;
+     break;
+   case 'o':  /* OUTPUT */
+     outputFileName=(char *)malloc(strlen(optarg)+1);
+     strcpy(outputFileName,optarg);
+     break;
+   case '?':  /* UNKNOW OPTION */
+     fprintf(stderr,"asn1Coding: option '%s' not recognized or without argument.\n\n",argv[optind-1]);
+     printf("%s\n",help_man);
+
+     if(outputFileName) free(outputFileName);
+     exit(1);
+     break;
+   default:
+     fprintf(stderr,"asn1Coding: ?? getopt returned character code Ox%x ??\n",option_result);
+   }
+ }
+
+ if(optind == argc){
+   fprintf(stderr,"asn1Coding: input file with ASN1 definitions missing.\n");
+   fprintf(stderr,"            input file with assignments missing.\n\n");
+   printf("%s\n",help_man);
+
+   if(outputFileName) free(outputFileName);
+   exit(1);
+ }
+
+ if(optind == argc-1){
+   fprintf(stderr,"asn1Coding: input file with assignments missing.\n\n");
+   printf("%s\n",help_man);
+
+   if(outputFileName) free(outputFileName);
+   exit(1);
+ }
+
+ inputFileAsnName=(char *)malloc(strlen(argv[optind])+1);
+ strcpy(inputFileAsnName,argv[optind]);
+
+ inputFileAssignmentName=(char *)malloc(strlen(argv[optind+1])+1);
+ strcpy(inputFileAssignmentName,argv[optind+1]);
+
+ asn1_result=asn1_parser2tree(inputFileAsnName,&definitions,errorDescription);
+
+ switch(asn1_result){
+ case ASN1_SUCCESS:
+   printf("Parse: done.\n");
+   break;
+ case ASN1_FILE_NOT_FOUND:
+   printf("asn1Coding: FILE %s NOT FOUND\n",inputFileAsnName);
+   break;
+ case ASN1_SYNTAX_ERROR: 
+ case ASN1_IDENTIFIER_NOT_FOUND: 
+ case ASN1_NAME_TOO_LONG:
+   printf("asn1Coding: %s\n",errorDescription);
+   break;
+ default:
+   printf("libasn1 ERROR: %s\n",libasn1_strerror(asn1_result));
+ }
+
+ if(asn1_result != ASN1_SUCCESS){
+   free(inputFileAsnName);
+   free(inputFileAssignmentName);
+   exit(1);
+ }
+
+
+ inputFile=fopen(inputFileAssignmentName,"r");
+ if(inputFile==NULL){
+   printf("asn1Coding: file '%s' not found\n",inputFileAssignmentName);
+   free(inputFileAsnName);
+   free(inputFileAssignmentName);
+   exit(1);
+ }
+
+
+ printf("\n");
+
+ while(readAssignment(inputFile,varName,value) == ASSIGNMENT_SUCCESS){
+   printf("var=%s, value=%s\n",varName,value);
+   if(structure==ASN1_TYPE_EMPTY){
+     asn1_result=asn1_create_element(definitions,value,&structure,varName);
+     strcpy(structureName,varName);
+   }
+   else
+     asn1_result=asn1_write_value(structure,varName,value,0); 
+
+   if(asn1_result != ASN1_SUCCESS){
+     printf("libasn1 ERROR: %s\n",libasn1_strerror(asn1_result));
+     
+     asn1_delete_structure(&definitions);
+     asn1_delete_structure(&structure);
+     
+     free(inputFileAsnName);
+     free(inputFileAssignmentName);
+     
+     fclose(inputFile);
+     exit(1);
+   }
+ }
+ fclose(inputFile);
+
+ printf("\n");
+ asn1_print_structure(stdout,structure,structureName,ASN1_PRINT_NAME_TYPE_VALUE);
+
+ asn1_result=asn1_der_coding(structure,structureName,der,&der_len,
+                             errorDescription);
+ printf("\nCoding: %s\n\n",libasn1_strerror(asn1_result));
+ if(asn1_result!=ASN1_SUCCESS){
+   printf("asn1Coding: %s\n",errorDescription);
+
+   asn1_delete_structure(&definitions);
+   asn1_delete_structure(&structure);
+   
+   free(inputFileAsnName);
+   free(inputFileAssignmentName);
+  
+   exit(1);
+ }
+
+ /* Print the 'Certificate1' DER encoding */ 
+ printf("-----------------\nNumber of bytes=%i\n",der_len);
+ for(k=0;k<der_len;k++) printf("%02x ",der[k]);  
+ printf("\n-----------------\n");
+
+ asn1_delete_structure(&definitions);
+ asn1_delete_structure(&structure);
+
+ if(outputFileName==NULL)
+   createFileName(inputFileAssignmentName,&outputFileName);
+
+ printf("\nOutputFile=%s\n",outputFileName);
+
+ outputFile=fopen(outputFileName,"w");
+ if(outputFile==NULL){
+   printf("asn1Coding: output file '%s' not available\n",outputFileName);
+   free(inputFileAsnName);
+   free(inputFileAssignmentName);
+   free(outputFileName);
+   exit(1);
+ }
+
+ for(k=0;k<der_len;k++) 
+   fprintf(outputFile,"%c",der[k]);  
+ fclose(outputFile);
+ printf("\nWriting: done.\n");
+
+
+ free(inputFileAsnName);
+ free(inputFileAssignmentName);
+ free(outputFileName);
+
+ exit(0);
+}
+
+
+
+
+
diff --git a/src/asn1Coding_test.asg b/src/asn1Coding_test.asg
new file mode 100644 (file)
index 0000000..6f594e0
--- /dev/null
@@ -0,0 +1,6 @@
+
+
+Sequence         Test.Sequence1
+
+Sequence.int1    10
+Sequence.int2    -10
diff --git a/src/asn1Coding_test.asn b/src/asn1Coding_test.asn
new file mode 100644 (file)
index 0000000..2189ee5
--- /dev/null
@@ -0,0 +1,12 @@
+Test { }
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+Sequence1 ::= SEQUENCE {
+  int1   INTEGER,
+  int2   INTEGER
+}
+
+END
diff --git a/src/asn1Decoding.c b/src/asn1Decoding.c
new file mode 100644 (file)
index 0000000..f5f2d52
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ *      Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: asn1Deoding.c                               */
+/* Description: program to generate an ASN1 type from*/
+/*              a DER coding.                        */   
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <libasn1.h>
+#include <malloc.h>
+#include <config.h>
+
+#ifdef HAVE_GETOPT_H
+  #include <getopt.h>
+#endif
+
+char version_man[] = "asn1Decoding (GNU libasn1) " VERSION;
+
+char help_man[] = "asn1Decoding generates an ASN1 type from a file\n"
+                  "with ASN1 definitions and another one with a DER encoding.\n"
+                  "\n"
+                  "Usage: asn1Decoding [options] <file1> <file2> <type>\n"
+                  " <file1> file with ASN1 definitions.\n"
+                  " <file2> file with a DER coding.\n"
+                  " <type>  ASN1 type name\n"
+                  "\n"
+#ifdef HAVE_GETOPT_H
+                  "Operation modes:\n"
+                  "  -h, --help    shows this message and exit.\n"
+                  "  -v, --version shows version information and exit.\n"
+                  "  -c, --check   checks the syntax only.\n";
+#else
+                  "Operation modes:\n"
+                  "  -h    shows this message and exit.\n"
+                  "  -v    shows version information and exit.\n"
+                  "  -c    checks the syntax only.\n";
+#endif
+
+
+
+/********************************************************/
+/* Function : main                                      */
+/* Description:                                         */
+/********************************************************/
+int
+main(int argc,char *argv[])
+{
+
+#ifdef HAVE_GETOPT_H
+  static struct option long_options[] =
+  {
+    {"help",    no_argument,       0, 'h'},
+    {"version", no_argument,       0, 'v'},
+    {"check",   no_argument,       0, 'c'},
+    {0, 0, 0, 0}
+  };
+#endif
+
+ int option_result;
+ int option_index = 0;
+ char *inputFileAsnName=NULL;
+ char *inputFileDerName=NULL; 
+ char *typeName=NULL;
+ char *varName=NULL;
+ int checkSyntaxOnly=0;
+ ASN1_TYPE definitions=ASN1_TYPE_EMPTY;
+ ASN1_TYPE structure=ASN1_TYPE_EMPTY;
+ char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
+ int asn1_result=ASN1_SUCCESS;
+ FILE *inputFile;
+ unsigned char der[1024];
+ int  der_len=0;
+ char *dot_p,*char_p;
+
+ opterr=0; /* disable error messages from getopt */
+
+ printf("\n");
+
+ while(1){
+
+#ifdef HAVE_GETOPT_H
+   option_result=getopt_long(argc,argv,"hvc",long_options,&option_index);
+#else
+   option_result=getopt(argc,argv,"hvc");
+#endif
+
+   if(option_result == -1) break;
+
+   switch(option_result){
+   case 'h':  /* HELP */
+     printf("%s\n",help_man);
+     exit(0);
+     break;
+   case 'v':  /* VERSION */
+     printf("%s\n",version_man);
+     exit(0);
+     break;
+   case 'c':  /* CHECK SYNTAX */
+     checkSyntaxOnly = 1;
+     break;
+   case '?':  /* UNKNOW OPTION */
+     fprintf(stderr,"asn1Decoding: option '%s' not recognized or without argument.\n\n",argv[optind-1]);
+     printf("%s\n",help_man);
+
+     exit(1);
+     break;
+   default:
+     fprintf(stderr,"asn1Decoding: ?? getopt returned character code Ox%x ??\n",option_result);
+   }
+ }
+
+ if(optind == argc){
+   fprintf(stderr,"asn1Decoding: input file with ASN1 definitions missing.\n");
+   fprintf(stderr,"              input file with DER coding missing.\n");
+   fprintf(stderr,"              ASN1 type name missing.\n\n");
+   printf("%s\n",help_man);
+
+   exit(1);
+ }
+
+ if(optind == argc-1){
+   fprintf(stderr,"asn1Decoding: input file with DER coding missing.\n\n");
+   fprintf(stderr,"              ASN1 type name missing.\n\n");
+   printf("%s\n",help_man);
+
+   exit(1);
+ }
+
+ if(optind == argc-2){
+   fprintf(stderr,"asn1Decoding: ASN1 type name missing.\n\n");
+   printf("%s\n",help_man);
+
+   exit(1);
+ }
+
+ inputFileAsnName=(char *)malloc(strlen(argv[optind])+1);
+ strcpy(inputFileAsnName,argv[optind]);
+ inputFileDerName=(char *)malloc(strlen(argv[optind+1])+1);
+ strcpy(inputFileDerName,argv[optind+1]);
+ typeName=(char *)malloc(strlen(argv[optind+2])+1);
+ strcpy(typeName,argv[optind+2]);
+
+ asn1_result=asn1_parser2tree(inputFileAsnName,&definitions,errorDescription);
+
+ switch(asn1_result){
+ case ASN1_SUCCESS:
+   printf("Parse: done.\n");
+   break;
+ case ASN1_FILE_NOT_FOUND:
+   printf("asn1Decoding: FILE %s NOT FOUND\n",inputFileAsnName);
+   break;
+ case ASN1_SYNTAX_ERROR: 
+ case ASN1_IDENTIFIER_NOT_FOUND: 
+ case ASN1_NAME_TOO_LONG:
+   printf("asn1Decoding: %s\n",errorDescription);
+   break;
+ default:
+   printf("libasn1 ERROR: %s\n",libasn1_strerror(asn1_result));
+ }
+
+ if(asn1_result != ASN1_SUCCESS){
+   free(inputFileAsnName);
+   free(inputFileDerName);
+   free(typeName);
+   exit(1);
+ }
+
+
+ inputFile=fopen(inputFileDerName,"r");
+ if(inputFile==NULL){
+   printf("asn1Decoding: file '%s' not found\n",inputFileDerName);
+   asn1_delete_structure(&definitions);
+
+   free(inputFileAsnName);
+   free(inputFileDerName);
+   free(typeName);
+   exit(1);
+ }
+
+ while(fscanf(inputFile,"%c",der+der_len) != EOF)
+   der_len++;
+
+ fclose(inputFile);
+
+ /* varName creation */
+ dot_p=typeName;
+ char_p=typeName;
+ while((char_p=strchr(char_p,'.'))){
+   char_p++;
+   dot_p=char_p;
+ }
+ /* varName= inputFileName after the last '.' */
+ varName=(char *)malloc(strlen(typeName)-(dot_p-typeName)+1);
+ strcpy(varName,dot_p);
+    
+ asn1_result=asn1_create_element(definitions,typeName,&structure,varName);
+ if(asn1_result != ASN1_SUCCESS){
+   printf("Structure creation: %s\n",libasn1_strerror(asn1_result));
+   asn1_delete_structure(&definitions);
+
+   free(inputFileAsnName);
+   free(inputFileDerName);
+   free(typeName);   
+   free(varName);   
+   exit(1);
+ }
+
+ asn1_result=asn1_der_decoding(&structure,der,der_len,errorDescription);
+ printf("\nDecoding: %s\n",libasn1_strerror(asn1_result));
+ if(asn1_result != ASN1_SUCCESS)
+   printf("asn1Decoding: %s\n",errorDescription);
+
+ printf("\nDECODING RESULT:\n");
+ asn1_print_structure(stdout,structure,varName,ASN1_PRINT_NAME_TYPE_VALUE);
+
+
+ asn1_delete_structure(&definitions);
+ asn1_delete_structure(&structure);
+
+ free(inputFileAsnName);
+ free(inputFileDerName);
+ free(typeName);
+ free(varName);   
+
+ if(asn1_result != ASN1_SUCCESS)
+   exit(1);
+
+ exit(0);
+}
+
+
+
+
+
diff --git a/src/asn1Parser.c b/src/asn1Parser.c
new file mode 100644 (file)
index 0000000..0cbb399
--- /dev/null
@@ -0,0 +1,207 @@
+/*\r
+ *      Copyright (C) 2002 Fabio Fiorina\r
+ *\r
+ * This file is part of LIBASN1.\r
+ *\r
+ * LIBASN1 is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * LIBASN1 is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\r
+ */\r
+\r
+\r
+/*****************************************************/\r
+/* File: asn1Parser.c                                */\r
+/* Description: program to parse a file with ASN1    */\r
+/*              definitions.                         */   \r
+/*****************************************************/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <libasn1.h>\r
+#include <malloc.h>\r
+#include <config.h>\r
+\r
+#ifdef HAVE_GETOPT_H\r
+  #include <getopt.h>\r
+#endif\r
+\r
+char version_man[] = "asn1Parser (GNU libasn1) " VERSION;\r
+\r
+char help_man[] = "asn1Parser reads files with ASN1 definitions and\n"\r
+                  "generates a C array to use with libasn1 functions.\n"\r
+                  "\n"\r
+                  "Usage: asn1Parser [options] file\n"\r
+                  "\n"\r
+#ifdef HAVE_GETOPT_H\r
+                  "Operation modes:\n"\r
+                  "  -h, --help    shows this message and exit\n"\r
+                  "  -v, --version shows version information and exit.\n"\r
+                  "  -c, --check   checks the syntax only.\n"\r
+                  "\n"\r
+                  "Output:\n"\r
+                  "  -o <file>, --output <file>  output file\n"\r
+                  "  -n <name>, --name <name>    array name\n";\r
+#else\r
+                  "Operation modes:\n"\r
+                  "  -h    shows this message and exit\n"\r
+                  "  -v    shows version information and exit.\n"\r
+                  "  -c    checks the syntax only.\n"\r
+                  "\n"\r
+                  "Output:\n"\r
+                  "  -o <file>  output file\n"\r
+                  "  -n <name>  array name\n";\r
+#endif\r
+\r
+/********************************************************/\r
+/* Function : main                                      */\r
+/* Description:                                         */\r
+/********************************************************/\r
+int\r
+main(int argc,char *argv[])\r
+{\r
+\r
+#ifdef HAVE_GETOPT_H\r
+  static struct option long_options[] =\r
+  {\r
+    {"help",    no_argument,       0, 'h'},\r
+    {"version", no_argument,       0, 'v'},\r
+    {"check",   no_argument,       0, 'c'},\r
+    {"output",  required_argument, 0, 'o'},\r
+    {"name",    required_argument, 0, 'n'},\r
+    {0, 0, 0, 0}\r
+  };\r
+#endif\r
+\r
+ int option_result;\r
+ int option_index = 0;\r
+ char *outputFileName=NULL;\r
+ char *inputFileName=NULL;\r
+ char *vectorName=NULL;\r
+ int checkSyntaxOnly=0;\r
+ ASN1_TYPE pointer=ASN1_TYPE_EMPTY;\r
+ char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];\r
+ int parse_result=ASN1_SUCCESS;\r
+\r
+ opterr=0; /* disable error messages from getopt */\r
+\r
+ printf("\n");\r
+\r
+ while(1){\r
+\r
+#ifdef HAVE_GETOPT_H\r
+   option_result=getopt_long(argc,argv,"hvco:n:",long_options,&option_index);\r
+#else\r
+   option_result=getopt(argc,argv,"hvco:n:");\r
+#endif\r
+\r
+   if(option_result == -1) break;\r
+\r
+   switch(option_result){\r
+   case 0:\r
+#ifdef HAVE_GETOPT_H\r
+     printf("option %s",long_options[option_index].name);\r
+     if(optarg) printf(" with arg %s",optarg);\r
+     printf("\n");\r
+#endif\r
+     break;\r
+   case 'h':  /* HELP */\r
+     printf("%s\n",help_man);\r
+\r
+     if(outputFileName) free(outputFileName);\r
+     if(vectorName) free(vectorName);\r
+     exit(0);\r
+     break;\r
+   case 'v':  /* VERSION */\r
+     printf("%s\n",version_man);\r
+\r
+     if(outputFileName) free(outputFileName);\r
+     if(vectorName) free(vectorName);\r
+     exit(0);\r
+     break;\r
+   case 'c':  /* CHECK SYNTAX */\r
+     checkSyntaxOnly = 1;\r
+     break;\r
+   case 'o':  /* OUTPUT */\r
+     outputFileName=(char *)malloc(strlen(optarg)+1);\r
+     strcpy(outputFileName,optarg);\r
+     break;\r
+   case 'n':  /* VECTOR NAME */\r
+     vectorName=(char *)malloc(strlen(optarg)+1);\r
+     strcpy(vectorName,optarg);\r
+     break;\r
+   case '?':  /* UNKNOW OPTION */\r
+     fprintf(stderr,"asn1Parser: option '%s' not recognized or without argument.\n\n",argv[optind-1]);\r
+     printf("%s\n",help_man);\r
+\r
+     if(outputFileName) free(outputFileName);\r
+     if(vectorName) free(vectorName);\r
+     exit(1);\r
+     break;\r
+   default:\r
+     fprintf(stderr,"asn1Parser: ?? getopt returned character code Ox%x ??\n",option_result);\r
+   }\r
+\r
+ }\r
+\r
+ if(optind == argc){\r
+   fprintf(stderr,"asn1Parser: input file name missing.\n\n");\r
+   printf("%s\n",help_man);\r
+\r
+   if(outputFileName) free(outputFileName);\r
+   if(vectorName) free(vectorName);\r
+   exit(1);\r
+ }\r
+ else{\r
+   inputFileName=(char *)malloc(strlen(argv[optind])+1);\r
+   strcpy(inputFileName,argv[optind]);\r
+ }\r
+\r
+ if(checkSyntaxOnly == 1){\r
+   parse_result=asn1_parser2tree(inputFileName,&pointer,errorDescription);\r
+   asn1_delete_structure(&pointer);\r
+ }\r
+ else /* C VECTOR CREATION */\r
+   parse_result=asn1_parser2array(inputFileName,\r
+                outputFileName,vectorName,errorDescription);\r
+\r
+ switch(parse_result){\r
+ case ASN1_SUCCESS:\r
+   printf("Done.\n");\r
+   break;\r
+ case ASN1_FILE_NOT_FOUND:\r
+   printf("asn1Parser: FILE %s NOT FOUND\n",inputFileName);\r
+   break;\r
+ case ASN1_SYNTAX_ERROR: \r
+ case ASN1_IDENTIFIER_NOT_FOUND: \r
+ case ASN1_NAME_TOO_LONG:\r
+   printf("asn1Parser: %s\n",errorDescription);\r
+   break;\r
+ default:\r
+   printf("libasn1 ERROR: %s\n",libasn1_strerror(parse_result));\r
+ }\r
+\r
+\r
+ free(inputFileName);\r
+ if(outputFileName) free(outputFileName);\r
+ if(vectorName) free(vectorName);\r
+\r
+ if(parse_result != ASN1_SUCCESS) exit(1);\r
+ exit(0);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/src/pkix_asn1_tab.c b/src/pkix_asn1_tab.c
new file mode 100644 (file)
index 0000000..eb88626
--- /dev/null
@@ -0,0 +1,874 @@
+
+#include "libasn1.h"
+
+const ASN1_ARRAY_TYPE pkix_asn1_tab[]={
+  {"PKIX1Implicit88",536875024,0},
+  {0,1610612748,0},
+  {"iso",1073741825,"1"},
+  {"identified-organization",1073741825,"3"},
+  {"dod",1073741825,"6"},
+  {"internet",1073741825,"1"},
+  {"security",1073741825,"5"},
+  {"mechanisms",1073741825,"5"},
+  {"pkix",1073741825,"7"},
+  {"id-mod",1073741825,"0"},
+  {"id-pkix1-implicit-88",1,"2"},
+  {"id-ce",1879048204,0},
+  {"joint-iso-ccitt",1073741825,"2"},
+  {"ds",1073741825,"5"},
+  {0,1,"29"},
+  {"id-ce-authorityKeyIdentifier",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"35"},
+  {"AuthorityKeyIdentifier",1610612741,0},
+  {"keyIdentifier",1610637314,"KeyIdentifier"},
+  {0,4104,"0"},
+  {"authorityCertIssuer",1610637314,"GeneralNames"},
+  {0,4104,"1"},
+  {"authorityCertSerialNumber",536895490,"CertificateSerialNumber"},
+  {0,4104,"2"},
+  {"KeyIdentifier",1073741831,0},
+  {"id-ce-subjectKeyIdentifier",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"14"},
+  {"SubjectKeyIdentifier",1073741826,"KeyIdentifier"},
+  {"id-ce-keyUsage",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"15"},
+  {"KeyUsage",1610874886,0},
+  {"digitalSignature",1073741825,"0"},
+  {"nonRepudiation",1073741825,"1"},
+  {"keyEncipherment",1073741825,"2"},
+  {"dataEncipherment",1073741825,"3"},
+  {"keyAgreement",1073741825,"4"},
+  {"keyCertSign",1073741825,"5"},
+  {"cRLSign",1073741825,"6"},
+  {"encipherOnly",1073741825,"7"},
+  {"decipherOnly",1,"8"},
+  {"id-ce-privateKeyUsagePeriod",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"16"},
+  {"PrivateKeyUsagePeriod",1610612741,0},
+  {"notBefore",1619025937,0},
+  {0,4104,"0"},
+  {"notAfter",545284113,0},
+  {0,4104,"1"},
+  {"id-ce-certificatePolicies",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"32"},
+  {"CertificatePolicies",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"PolicyInformation"},
+  {"PolicyInformation",1610612741,0},
+  {"policyIdentifier",1073741826,"CertPolicyId"},
+  {"policyQualifiers",538984459,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"PolicyQualifierInfo"},
+  {"CertPolicyId",1073741836,0},
+  {"PolicyQualifierInfo",1610612741,0},
+  {"policyQualifierId",1073741826,"PolicyQualifierId"},
+  {"qualifier",541065229,0},
+  {"policyQualifierId",1,0},
+  {"PolicyQualifierId",1073741836,0},
+  {"CPSuri",1073741826,"IA5String"},
+  {"UserNotice",1610612741,0},
+  {"noticeRef",1073758210,"NoticeReference"},
+  {"explicitText",16386,"DisplayText"},
+  {"NoticeReference",1610612741,0},
+  {"organization",1073741826,"DisplayText"},
+  {"noticeNumbers",536870923,0},
+  {0,3,0},
+  {"DisplayText",1610612754,0},
+  {"visibleString",1612709890,"VisibleString"},
+  {"200",524298,"1"},
+  {"bmpString",1612709890,"BMPString"},
+  {"200",524298,"1"},
+  {"utf8String",538968066,"UTF8String"},
+  {"200",524298,"1"},
+  {"id-ce-policyMappings",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"33"},
+  {"PolicyMappings",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,536870917,0},
+  {"issuerDomainPolicy",1073741826,"CertPolicyId"},
+  {"subjectDomainPolicy",2,"CertPolicyId"},
+  {"id-ce-subjectAltName",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"17"},
+  {"SubjectAltName",1073741826,"GeneralNames"},
+  {"GeneralNames",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"GeneralName"},
+  {"GeneralName",1610612754,0},
+  {"otherName",1610620930,"AnotherName"},
+  {0,4104,"0"},
+  {"rfc822Name",1610620930,"IA5String"},
+  {0,4104,"1"},
+  {"dNSName",1610620930,"IA5String"},
+  {0,4104,"2"},
+  {"x400Address",1610620930,"ORAddress"},
+  {0,4104,"3"},
+  {"directoryName",1610620930,"Name"},
+  {0,4104,"4"},
+  {"ediPartyName",1610620930,"EDIPartyName"},
+  {0,4104,"5"},
+  {"uniformResourceIdentifier",1610620930,"IA5String"},
+  {0,4104,"6"},
+  {"iPAddress",1610620935,0},
+  {0,4104,"7"},
+  {"registeredID",536879116,0},
+  {0,4104,"8"},
+  {"AnotherName",1610612741,0},
+  {"type-id",1073741836,0},
+  {"value",541073421,0},
+  {0,1073743880,"0"},
+  {"type-id",1,0},
+  {"EDIPartyName",1610612741,0},
+  {"nameAssigner",1610637314,"DirectoryString"},
+  {0,4104,"0"},
+  {"partyName",536879106,"DirectoryString"},
+  {0,4104,"1"},
+  {"id-ce-issuerAltName",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"18"},
+  {"IssuerAltName",1073741826,"GeneralNames"},
+  {"id-ce-subjectDirectoryAttributes",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"9"},
+  {"SubjectDirectoryAttributes",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"Attribute"},
+  {"id-ce-basicConstraints",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"19"},
+  {"BasicConstraints",1610612741,0},
+  {"cA",1610645508,0},
+  {0,131081,0},
+  {"pathLenConstraint",537411587,0},
+  {"0",10,"MAX"},
+  {"id-ce-nameConstraints",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"30"},
+  {"NameConstraints",1610612741,0},
+  {"permittedSubtrees",1610637314,"GeneralSubtrees"},
+  {0,4104,"0"},
+  {"excludedSubtrees",536895490,"GeneralSubtrees"},
+  {0,4104,"1"},
+  {"GeneralSubtrees",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"GeneralSubtree"},
+  {"GeneralSubtree",1610612741,0},
+  {"base",1073741826,"GeneralName"},
+  {"minimum",1610653698,"BaseDistance"},
+  {0,1073741833,"0"},
+  {0,4104,"0"},
+  {"maximum",536895490,"BaseDistance"},
+  {0,4104,"1"},
+  {"BaseDistance",1611137027,0},
+  {"0",10,"MAX"},
+  {"id-ce-policyConstraints",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"36"},
+  {"PolicyConstraints",1610612741,0},
+  {"requireExplicitPolicy",1610637314,"SkipCerts"},
+  {0,4104,"0"},
+  {"inhibitPolicyMapping",536895490,"SkipCerts"},
+  {0,4104,"1"},
+  {"SkipCerts",1611137027,0},
+  {"0",10,"MAX"},
+  {"id-ce-cRLDistributionPoints",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"31"},
+  {"CRLDistPointsSyntax",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"DistributionPoint"},
+  {"DistributionPoint",1610612741,0},
+  {"distributionPoint",1610637314,"DistributionPointName"},
+  {0,4104,"0"},
+  {"reasons",1610637314,"ReasonFlags"},
+  {0,4104,"1"},
+  {"cRLIssuer",536895490,"GeneralNames"},
+  {0,4104,"2"},
+  {"DistributionPointName",1610612754,0},
+  {"fullName",1610620930,"GeneralNames"},
+  {0,4104,"0"},
+  {"nameRelativeToCRLIssuer",536879106,"RelativeDistinguishedName"},
+  {0,4104,"1"},
+  {"ReasonFlags",1610874886,0},
+  {"unused",1073741825,"0"},
+  {"keyCompromise",1073741825,"1"},
+  {"cACompromise",1073741825,"2"},
+  {"affiliationChanged",1073741825,"3"},
+  {"superseded",1073741825,"4"},
+  {"cessationOfOperation",1073741825,"5"},
+  {"certificateHold",1,"6"},
+  {"id-ce-extKeyUsage",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"37"},
+  {"ExtKeyUsageSyntax",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"KeyPurposeId"},
+  {"KeyPurposeId",1073741836,0},
+  {"id-kp-serverAuth",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"1"},
+  {"id-kp-clientAuth",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"2"},
+  {"id-kp-codeSigning",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"3"},
+  {"id-kp-emailProtection",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"4"},
+  {"id-kp-ipsecEndSystem",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"5"},
+  {"id-kp-ipsecTunnel",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"6"},
+  {"id-kp-ipsecUser",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"7"},
+  {"id-kp-timeStamping",1879048204,0},
+  {0,1073741825,"id-kp"},
+  {0,1,"8"},
+  {"id-pe-authorityInfoAccess",1879048204,0},
+  {0,1073741825,"id-pe"},
+  {0,1,"1"},
+  {"AuthorityInfoAccessSyntax",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"AccessDescription"},
+  {"AccessDescription",1610612741,0},
+  {"accessMethod",1073741836,0},
+  {"accessLocation",2,"GeneralName"},
+  {"id-ce-cRLNumber",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"20"},
+  {"CRLNumber",1611137027,0},
+  {"0",10,"MAX"},
+  {"id-ce-issuingDistributionPoint",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"28"},
+  {"IssuingDistributionPoint",1610612741,0},
+  {"distributionPoint",1610637314,"DistributionPointName"},
+  {0,4104,"0"},
+  {"onlyContainsUserCerts",1610653700,0},
+  {0,1073872905,0},
+  {0,4104,"1"},
+  {"onlyContainsCACerts",1610653700,0},
+  {0,1073872905,0},
+  {0,4104,"2"},
+  {"onlySomeReasons",1610637314,"ReasonFlags"},
+  {0,4104,"3"},
+  {"indirectCRL",536911876,0},
+  {0,1073872905,0},
+  {0,4104,"4"},
+  {"id-ce-deltaCRLIndicator",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"27"},
+  {"BaseCRLNumber",1073741826,"CRLNumber"},
+  {"id-ce-cRLReasons",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"21"},
+  {"CRLReason",1610874901,0},
+  {"unspecified",1073741825,"0"},
+  {"keyCompromise",1073741825,"1"},
+  {"cACompromise",1073741825,"2"},
+  {"affiliationChanged",1073741825,"3"},
+  {"superseded",1073741825,"4"},
+  {"cessationOfOperation",1073741825,"5"},
+  {"certificateHold",1073741825,"6"},
+  {"removeFromCRL",1,"8"},
+  {"id-ce-certificateIssuer",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"29"},
+  {"CertificateIssuer",1073741826,"GeneralNames"},
+  {"id-ce-holdInstructionCode",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"23"},
+  {"HoldInstructionCode",1073741836,0},
+  {"holdInstruction",1879048204,0},
+  {"joint-iso-itu-t",1073741825,"2"},
+  {"member-body",1073741825,"2"},
+  {"us",1073741825,"840"},
+  {"x9cm",1073741825,"10040"},
+  {0,1,"2"},
+  {"id-holdinstruction-none",1879048204,0},
+  {0,1073741825,"holdInstruction"},
+  {0,1,"1"},
+  {"id-holdinstruction-callissuer",1879048204,0},
+  {0,1073741825,"holdInstruction"},
+  {0,1,"2"},
+  {"id-holdinstruction-reject",1879048204,0},
+  {0,1073741825,"holdInstruction"},
+  {0,1,"3"},
+  {"id-ce-invalidityDate",1879048204,0},
+  {0,1073741825,"id-ce"},
+  {0,1,"24"},
+  {"InvalidityDate",1082130449,0},
+  {"VisibleString",1610620935,0},
+  {0,4360,"26"},
+  {"NumericString",1610620935,0},
+  {0,4360,"18"},
+  {"IA5String",1610620935,0},
+  {0,4360,"22"},
+  {"TeletexString",1610620935,0},
+  {0,4360,"20"},
+  {"PrintableString",1610620935,0},
+  {0,4360,"19"},
+  {"UniversalString",1610620935,0},
+  {0,4360,"28"},
+  {"BMPString",1610620935,0},
+  {0,4360,"30"},
+  {"UTF8String",1610620935,0},
+  {0,4360,"12"},
+  {"id-pkix",1879048204,0},
+  {"iso",1073741825,"1"},
+  {"identified-organization",1073741825,"3"},
+  {"dod",1073741825,"6"},
+  {"internet",1073741825,"1"},
+  {"security",1073741825,"5"},
+  {"mechanisms",1073741825,"5"},
+  {"pkix",1,"7"},
+  {"id-pe",1879048204,0},
+  {0,1073741825,"id-pkix"},
+  {0,1,"1"},
+  {"id-qt",1879048204,0},
+  {0,1073741825,"id-pkix"},
+  {0,1,"2"},
+  {"id-kp",1879048204,0},
+  {0,1073741825,"id-pkix"},
+  {0,1,"3"},
+  {"id-ad",1879048204,0},
+  {0,1073741825,"id-pkix"},
+  {0,1,"48"},
+  {"id-qt-cps",1879048204,0},
+  {0,1073741825,"id-qt"},
+  {0,1,"1"},
+  {"id-qt-unotice",1879048204,0},
+  {0,1073741825,"id-qt"},
+  {0,1,"2"},
+  {"id-ad-ocsp",1879048204,0},
+  {0,1073741825,"id-ad"},
+  {0,1,"1"},
+  {"id-ad-caIssuers",1879048204,0},
+  {0,1073741825,"id-ad"},
+  {0,1,"2"},
+  {"Attribute",1610612741,0},
+  {"type",1073741826,"AttributeType"},
+  {"values",536870927,0},
+  {0,2,"AttributeValue"},
+  {"AttributeType",1073741836,0},
+  {"AttributeValue",1073741837,0},
+  {"AttributeTypeAndValue",1610612741,0},
+  {"type",1073741826,"AttributeType"},
+  {"value",2,"AttributeValue"},
+  {"id-at",1879048204,0},
+  {"joint-iso-ccitt",1073741825,"2"},
+  {"ds",1073741825,"5"},
+  {0,1,"4"},
+  {"id-at-name",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"41"},
+  {"id-at-surname",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"4"},
+  {"id-at-givenName",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"42"},
+  {"id-at-initials",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"43"},
+  {"id-at-generationQualifier",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"44"},
+  {"X520name",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"ub-name",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"ub-name",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"ub-name",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"ub-name",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"ub-name",524298,"1"},
+  {"id-at-commonName",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"3"},
+  {"X520CommonName",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"ub-common-name",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"ub-common-name",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"ub-common-name",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"ub-common-name",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"ub-common-name",524298,"1"},
+  {"id-at-localityName",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"7"},
+  {"X520LocalityName",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"ub-locality-name",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"ub-locality-name",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"ub-locality-name",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"ub-locality-name",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"ub-locality-name",524298,"1"},
+  {"id-at-stateOrProvinceName",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"8"},
+  {"X520StateOrProvinceName",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"ub-state-name",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"ub-state-name",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"ub-state-name",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"ub-state-name",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"ub-state-name",524298,"1"},
+  {"id-at-organizationName",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"10"},
+  {"X520OrganizationName",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"ub-organization-name",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"ub-organization-name",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"ub-organization-name",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"ub-organization-name",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"ub-organization-name",524298,"1"},
+  {"id-at-organizationalUnitName",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"11"},
+  {"X520OrganizationalUnitName",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"ub-organizational-unit-name",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"ub-organizational-unit-name",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"ub-organizational-unit-name",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"ub-organizational-unit-name",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"ub-organizational-unit-name",524298,"1"},
+  {"id-at-title",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"12"},
+  {"X520Title",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"ub-title",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"ub-title",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"ub-title",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"ub-title",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"ub-title",524298,"1"},
+  {"id-at-dnQualifier",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"46"},
+  {"X520dnQualifier",1073741826,"PrintableString"},
+  {"id-at-countryName",1880096780,"AttributeType"},
+  {0,1073741825,"id-at"},
+  {0,1,"6"},
+  {"X520countryName",1612709890,"PrintableString"},
+  {0,1048586,"2"},
+  {"pkcs-9",1879048204,0},
+  {"iso",1073741825,"1"},
+  {"member-body",1073741825,"2"},
+  {"us",1073741825,"840"},
+  {"rsadsi",1073741825,"113549"},
+  {"pkcs",1073741825,"1"},
+  {0,1,"9"},
+  {"emailAddress",1880096780,"AttributeType"},
+  {0,1073741825,"pkcs-9"},
+  {0,1,"1"},
+  {"Pkcs9email",1612709890,"IA5String"},
+  {"ub-emailaddress-length",524298,"1"},
+  {"Name",1610612754,0},
+  {"rdnSequence",2,"RDNSequence"},
+  {"RDNSequence",1610612747,0},
+  {0,2,"RelativeDistinguishedName"},
+  {"DistinguishedName",1073741826,"RDNSequence"},
+  {"RelativeDistinguishedName",1612709903,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"AttributeTypeAndValue"},
+  {"DirectoryString",1610612754,0},
+  {"teletexString",1612709890,"TeletexString"},
+  {"MAX",524298,"1"},
+  {"printableString",1612709890,"PrintableString"},
+  {"MAX",524298,"1"},
+  {"universalString",1612709890,"UniversalString"},
+  {"MAX",524298,"1"},
+  {"utf8String",1612709890,"UTF8String"},
+  {"MAX",524298,"1"},
+  {"bmpString",538968066,"BMPString"},
+  {"MAX",524298,"1"},
+  {"Certificate",1610612741,0},
+  {"tbsCertificate",1073741826,"TBSCertificate"},
+  {"signatureAlgorithm",1073741826,"AlgorithmIdentifier"},
+  {"signature",6,0},
+  {"TBSCertificate",1610612741,0},
+  {"version",1610653698,"Version"},
+  {0,1073741833,"v1"},
+  {0,2056,"0"},
+  {"serialNumber",1073741826,"CertificateSerialNumber"},
+  {"signature",1073741826,"AlgorithmIdentifier"},
+  {"issuer",1073741826,"Name"},
+  {"validity",1073741826,"Validity"},
+  {"subject",1073741826,"Name"},
+  {"subjectPublicKeyInfo",1073741826,"SubjectPublicKeyInfo"},
+  {"issuerUniqueID",1610637314,"UniqueIdentifier"},
+  {0,4104,"1"},
+  {"subjectUniqueID",1610637314,"UniqueIdentifier"},
+  {0,4104,"2"},
+  {"extensions",536895490,"Extensions"},
+  {0,2056,"3"},
+  {"Version",1610874883,0},
+  {"v1",1073741825,"0"},
+  {"v2",1073741825,"1"},
+  {"v3",1,"2"},
+  {"CertificateSerialNumber",1073741827,0},
+  {"Validity",1610612741,0},
+  {"notBefore",1073741826,"Time"},
+  {"notAfter",2,"Time"},
+  {"Time",1610612754,0},
+  {"utcTime",1090519057,0},
+  {"generalTime",8388625,0},
+  {"UniqueIdentifier",1073741830,0},
+  {"SubjectPublicKeyInfo",1610612741,0},
+  {"algorithm",1073741826,"AlgorithmIdentifier"},
+  {"subjectPublicKey",6,0},
+  {"Extensions",1612709899,0},
+  {"MAX",1074266122,"1"},
+  {0,2,"Extension"},
+  {"Extension",1610612741,0},
+  {"extnID",1073741836,0},
+  {"critical",1610645508,0},
+  {0,131081,0},
+  {"extnValue",7,0},
+  {"CertificateList",1610612741,0},
+  {"tbsCertList",1073741826,"TBSCertList"},
+  {"signatureAlgorithm",1073741826,"AlgorithmIdentifier"},
+  {"signature",6,0},
+  {"TBSCertList",1610612741,0},
+  {"version",1073758210,"Version"},
+  {"signature",1073741826,"AlgorithmIdentifier"},
+  {"issuer",1073741826,"Name"},
+  {"thisUpdate",1073741826,"Time"},
+  {"nextUpdate",1073758210,"Time"},
+  {"revokedCertificates",1610629131,0},
+  {0,536870917,0},
+  {"userCertificate",1073741826,"CertificateSerialNumber"},
+  {"revocationDate",1073741826,"Time"},
+  {"crlEntryExtensions",16386,"Extensions"},
+  {"crlExtensions",536895490,"Extensions"},
+  {0,2056,"0"},
+  {"AlgorithmIdentifier",1610612741,0},
+  {"algorithm",1073741836,0},
+  {"parameters",541081613,0},
+  {"algorithm",1,0},
+  {"pkcs-1",1879048204,0},
+  {"iso",1073741825,"1"},
+  {"member-body",1073741825,"2"},
+  {"us",1073741825,"840"},
+  {"rsadsi",1073741825,"113549"},
+  {"pkcs",1073741825,"1"},
+  {0,1,"1"},
+  {"rsaEncryption",1879048204,0},
+  {0,1073741825,"pkcs-1"},
+  {0,1,"1"},
+  {"md2WithRSAEncryption",1879048204,0},
+  {0,1073741825,"pkcs-1"},
+  {0,1,"2"},
+  {"md5WithRSAEncryption",1879048204,0},
+  {0,1073741825,"pkcs-1"},
+  {0,1,"4"},
+  {"sha1WithRSAEncryption",1879048204,0},
+  {0,1073741825,"pkcs-1"},
+  {0,1,"5"},
+  {"id-dsa-with-sha1",1879048204,0},
+  {"iso",1073741825,"1"},
+  {"member-body",1073741825,"2"},
+  {"us",1073741825,"840"},
+  {"x9-57",1073741825,"10040"},
+  {"x9algorithm",1073741825,"4"},
+  {0,1,"3"},
+  {"Dss-Sig-Value",1610612741,0},
+  {"r",1073741827,0},
+  {"s",3,0},
+  {"dhpublicnumber",1879048204,0},
+  {"iso",1073741825,"1"},
+  {"member-body",1073741825,"2"},
+  {"us",1073741825,"840"},
+  {"ansi-x942",1073741825,"10046"},
+  {"number-type",1073741825,"2"},
+  {0,1,"1"},
+  {"DomainParameters",1610612741,0},
+  {"p",1073741827,0},
+  {"g",1073741827,0},
+  {"q",1073741827,0},
+  {"j",1073758211,0},
+  {"validationParms",16386,"ValidationParms"},
+  {"ValidationParms",1610612741,0},
+  {"seed",1073741830,0},
+  {"pgenCounter",3,0},
+  {"id-dsa",1879048204,0},
+  {"iso",1073741825,"1"},
+  {"member-body",1073741825,"2"},
+  {"us",1073741825,"840"},
+  {"x9-57",1073741825,"10040"},
+  {"x9algorithm",1073741825,"4"},
+  {0,1,"1"},
+  {"Dss-Parms",1610612741,0},
+  {"p",1073741827,0},
+  {"q",1073741827,0},
+  {"g",3,0},
+  {"ORAddress",1610612741,0},
+  {"built-in-standard-attributes",1073741826,"BuiltInStandardAttributes"},
+  {"built-in-domain-defined-attributes",1073758210,"BuiltInDomainDefinedAttributes"},
+  {"extension-attributes",16386,"ExtensionAttributes"},
+  {"BuiltInStandardAttributes",1610612741,0},
+  {"country-name",1073758210,"CountryName"},
+  {"administration-domain-name",1073758210,"AdministrationDomainName"},
+  {"network-address",1610637314,"NetworkAddress"},
+  {0,2056,"0"},
+  {"terminal-identifier",1610637314,"TerminalIdentifier"},
+  {0,2056,"1"},
+  {"private-domain-name",1610637314,"PrivateDomainName"},
+  {0,2056,"2"},
+  {"organization-name",1610637314,"OrganizationName"},
+  {0,2056,"3"},
+  {"numeric-user-identifier",1610637314,"NumericUserIdentifier"},
+  {0,2056,"4"},
+  {"personal-name",1610637314,"PersonalName"},
+  {0,2056,"5"},
+  {"organizational-unit-names",536895490,"OrganizationalUnitNames"},
+  {0,2056,"6"},
+  {"CountryName",1610620946,0},
+  {0,1073746952,"1"},
+  {"x121-dcc-code",1612709890,"NumericString"},
+  {0,1048586,"ub-country-name-numeric-length"},
+  {"iso-3166-alpha2-code",538968066,"PrintableString"},
+  {0,1048586,"ub-country-name-alpha-length"},
+  {"AdministrationDomainName",1610620946,0},
+  {0,1073744904,"2"},
+  {"numeric",1612709890,"NumericString"},
+  {"ub-domain-name-length",524298,"0"},
+  {"printable",538968066,"PrintableString"},
+  {"ub-domain-name-length",524298,"0"},
+  {"NetworkAddress",1073741826,"X121Address"},
+  {"X121Address",1612709890,"NumericString"},
+  {"ub-x121-address-length",524298,"1"},
+  {"TerminalIdentifier",1612709890,"PrintableString"},
+  {"ub-terminal-id-length",524298,"1"},
+  {"PrivateDomainName",1610612754,0},
+  {"numeric",1612709890,"NumericString"},
+  {"ub-domain-name-length",524298,"1"},
+  {"printable",538968066,"PrintableString"},
+  {"ub-domain-name-length",524298,"1"},
+  {"OrganizationName",1612709890,"PrintableString"},
+  {"ub-organization-name-length",524298,"1"},
+  {"NumericUserIdentifier",1612709890,"NumericString"},
+  {"ub-numeric-user-id-length",524298,"1"},
+  {"PersonalName",1610612750,0},
+  {"surname",1814044674,"PrintableString"},
+  {0,1073745928,"0"},
+  {"ub-surname-length",524298,"1"},
+  {"given-name",1814061058,"PrintableString"},
+  {0,1073745928,"1"},
+  {"ub-given-name-length",524298,"1"},
+  {"initials",1814061058,"PrintableString"},
+  {0,1073745928,"2"},
+  {"ub-initials-length",524298,"1"},
+  {"generation-qualifier",740319234,"PrintableString"},
+  {0,1073745928,"3"},
+  {"ub-generation-qualifier-length",524298,"1"},
+  {"OrganizationalUnitNames",1612709899,0},
+  {"ub-organizational-units",1074266122,"1"},
+  {0,2,"OrganizationalUnitName"},
+  {"OrganizationalUnitName",1612709890,"PrintableString"},
+  {"ub-organizational-unit-name-length",524298,"1"},
+  {"BuiltInDomainDefinedAttributes",1612709899,0},
+  {"ub-domain-defined-attributes",1074266122,"1"},
+  {0,2,"BuiltInDomainDefinedAttribute"},
+  {"BuiltInDomainDefinedAttribute",1610612741,0},
+  {"type",1612709890,"PrintableString"},
+  {"ub-domain-defined-attribute-type-length",524298,"1"},
+  {"value",538968066,"PrintableString"},
+  {"ub-domain-defined-attribute-value-length",524298,"1"},
+  {"ExtensionAttributes",1612709903,0},
+  {"ub-extension-attributes",1074266122,"1"},
+  {0,2,"ExtensionAttribute"},
+  {"ExtensionAttribute",1610612741,0},
+  {"extension-attribute-type",1611145219,0},
+  {0,1073743880,"0"},
+  {"0",10,"ub-extension-attributes"},
+  {"extension-attribute-value",541073421,0},
+  {0,1073743880,"1"},
+  {"extension-attribute-type",1,0},
+  {"common-name",1342177283,"1"},
+  {"CommonName",1612709890,"PrintableString"},
+  {"ub-common-name-length",524298,"1"},
+  {"teletex-common-name",1342177283,"2"},
+  {"TeletexCommonName",1612709890,"TeletexString"},
+  {"ub-common-name-length",524298,"1"},
+  {"teletex-organization-name",1342177283,"3"},
+  {"TeletexOrganizationName",1612709890,"TeletexString"},
+  {"ub-organization-name-length",524298,"1"},
+  {"teletex-personal-name",1342177283,"4"},
+  {"TeletexPersonalName",1610612750,0},
+  {"surname",1814044674,"TeletexString"},
+  {0,1073743880,"0"},
+  {"ub-surname-length",524298,"1"},
+  {"given-name",1814061058,"TeletexString"},
+  {0,1073743880,"1"},
+  {"ub-given-name-length",524298,"1"},
+  {"initials",1814061058,"TeletexString"},
+  {0,1073743880,"2"},
+  {"ub-initials-length",524298,"1"},
+  {"generation-qualifier",740319234,"TeletexString"},
+  {0,1073743880,"3"},
+  {"ub-generation-qualifier-length",524298,"1"},
+  {"teletex-organizational-unit-names",1342177283,"5"},
+  {"TeletexOrganizationalUnitNames",1612709899,0},
+  {"ub-organizational-units",1074266122,"1"},
+  {0,2,"TeletexOrganizationalUnitName"},
+  {"TeletexOrganizationalUnitName",1612709890,"TeletexString"},
+  {"ub-organizational-unit-name-length",524298,"1"},
+  {"pds-name",1342177283,"7"},
+  {"PDSName",1612709890,"PrintableString"},
+  {"ub-pds-name-length",524298,"1"},
+  {"physical-delivery-country-name",1342177283,"8"},
+  {"PhysicalDeliveryCountryName",1610612754,0},
+  {"x121-dcc-code",1612709890,"NumericString"},
+  {0,1048586,"ub-country-name-numeric-length"},
+  {"iso-3166-alpha2-code",538968066,"PrintableString"},
+  {0,1048586,"ub-country-name-alpha-length"},
+  {"postal-code",1342177283,"9"},
+  {"PostalCode",1610612754,0},
+  {"numeric-code",1612709890,"NumericString"},
+  {"ub-postal-code-length",524298,"1"},
+  {"printable-code",538968066,"PrintableString"},
+  {"ub-postal-code-length",524298,"1"},
+  {"physical-delivery-office-name",1342177283,"10"},
+  {"PhysicalDeliveryOfficeName",1073741826,"PDSParameter"},
+  {"physical-delivery-office-number",1342177283,"11"},
+  {"PhysicalDeliveryOfficeNumber",1073741826,"PDSParameter"},
+  {"extension-OR-address-components",1342177283,"12"},
+  {"ExtensionORAddressComponents",1073741826,"PDSParameter"},
+  {"physical-delivery-personal-name",1342177283,"13"},
+  {"PhysicalDeliveryPersonalName",1073741826,"PDSParameter"},
+  {"physical-delivery-organization-name",1342177283,"14"},
+  {"PhysicalDeliveryOrganizationName",1073741826,"PDSParameter"},
+  {"extension-physical-delivery-address-components",1342177283,"15"},
+  {"ExtensionPhysicalDeliveryAddressComponents",1073741826,"PDSParameter"},
+  {"unformatted-postal-address",1342177283,"16"},
+  {"UnformattedPostalAddress",1610612750,0},
+  {"printable-address",1814052875,0},
+  {"ub-pds-physical-address-lines",1074266122,"1"},
+  {0,538968066,"PrintableString"},
+  {"ub-pds-parameter-length",524298,"1"},
+  {"teletex-string",740311042,"TeletexString"},
+  {"ub-unformatted-address-length",524298,"1"},
+  {"street-address",1342177283,"17"},
+  {"StreetAddress",1073741826,"PDSParameter"},
+  {"post-office-box-address",1342177283,"18"},
+  {"PostOfficeBoxAddress",1073741826,"PDSParameter"},
+  {"poste-restante-address",1342177283,"19"},
+  {"PosteRestanteAddress",1073741826,"PDSParameter"},
+  {"unique-postal-name",1342177283,"20"},
+  {"UniquePostalName",1073741826,"PDSParameter"},
+  {"local-postal-attributes",1342177283,"21"},
+  {"LocalPostalAttributes",1073741826,"PDSParameter"},
+  {"PDSParameter",1610612750,0},
+  {"printable-string",1814052866,"PrintableString"},
+  {"ub-pds-parameter-length",524298,"1"},
+  {"teletex-string",740311042,"TeletexString"},
+  {"ub-pds-parameter-length",524298,"1"},
+  {"extended-network-address",1342177283,"22"},
+  {"ExtendedNetworkAddress",1610612754,0},
+  {"e163-4-address",1610612741,0},
+  {"number",1612718082,"NumericString"},
+  {0,1073743880,"0"},
+  {"ub-e163-4-number-length",524298,"1"},
+  {"sub-address",538992642,"NumericString"},
+  {0,1073743880,"1"},
+  {"ub-e163-4-sub-address-length",524298,"1"},
+  {"psap-address",536879106,"PresentationAddress"},
+  {0,2056,"0"},
+  {"PresentationAddress",1610612741,0},
+  {"pSelector",1610637319,0},
+  {0,2056,"0"},
+  {"sSelector",1610637319,0},
+  {0,2056,"1"},
+  {"tSelector",1610637319,0},
+  {0,2056,"2"},
+  {"nAddresses",538976271,0},
+  {0,1073743880,"3"},
+  {"MAX",1074266122,"1"},
+  {0,7,0},
+  {"terminal-type",1342177283,"23"},
+  {"TerminalType",1611137027,0},
+  {"0",10,"ub-integer-options"},
+  {"teletex-domain-defined-attributes",1342177283,"6"},
+  {"TeletexDomainDefinedAttributes",1612709899,0},
+  {"ub-domain-defined-attributes",1074266122,"1"},
+  {0,2,"TeletexDomainDefinedAttribute"},
+  {"TeletexDomainDefinedAttribute",1610612741,0},
+  {"type",1612709890,"TeletexString"},
+  {"ub-domain-defined-attribute-type-length",524298,"1"},
+  {"value",538968066,"TeletexString"},
+  {"ub-domain-defined-attribute-value-length",524298,"1"},
+  {"ub-name",1342177283,"32768"},
+  {"ub-common-name",1342177283,"64"},
+  {"ub-locality-name",1342177283,"128"},
+  {"ub-state-name",1342177283,"128"},
+  {"ub-organization-name",1342177283,"64"},
+  {"ub-organizational-unit-name",1342177283,"64"},
+  {"ub-title",1342177283,"64"},
+  {"ub-match",1342177283,"128"},
+  {"ub-emailaddress-length",1342177283,"128"},
+  {"ub-common-name-length",1342177283,"64"},
+  {"ub-country-name-alpha-length",1342177283,"2"},
+  {"ub-country-name-numeric-length",1342177283,"3"},
+  {"ub-domain-defined-attributes",1342177283,"4"},
+  {"ub-domain-defined-attribute-type-length",1342177283,"8"},
+  {"ub-domain-defined-attribute-value-length",1342177283,"128"},
+  {"ub-domain-name-length",1342177283,"16"},
+  {"ub-extension-attributes",1342177283,"256"},
+  {"ub-e163-4-number-length",1342177283,"15"},
+  {"ub-e163-4-sub-address-length",1342177283,"40"},
+  {"ub-generation-qualifier-length",1342177283,"3"},
+  {"ub-given-name-length",1342177283,"16"},
+  {"ub-initials-length",1342177283,"5"},
+  {"ub-integer-options",1342177283,"256"},
+  {"ub-numeric-user-id-length",1342177283,"32"},
+  {"ub-organization-name-length",1342177283,"64"},
+  {"ub-organizational-unit-name-length",1342177283,"32"},
+  {"ub-organizational-units",1342177283,"4"},
+  {"ub-pds-name-length",1342177283,"16"},
+  {"ub-pds-parameter-length",1342177283,"30"},
+  {"ub-pds-physical-address-lines",1342177283,"6"},
+  {"ub-postal-code-length",1342177283,"16"},
+  {"ub-surname-length",1342177283,"40"},
+  {"ub-terminal-id-length",1342177283,"24"},
+  {"ub-unformatted-address-length",1342177283,"180"},
+  {"ub-x121-address-length",268435459,"16"},
+  {0,0,0}
+};
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644 (file)
index 0000000..709f4b3
--- /dev/null
@@ -0,0 +1,10 @@
+INCLUDES = -I../lib
+
+EXTRA_DIST = Test_parser.asn Test_tree.asn Test_tree_asn1_tab.c
+
+noinst_PROGRAMS = Test_parser Test_tree
+Test_parser_SOURCES = Test_parser.c  
+Test_parser_LDADD = ../lib/libasn1.la
+
+Test_tree_SOURCES = Test_tree.c  
+Test_tree_LDADD = ../lib/libasn1.la
diff --git a/tests/Test_parser.c b/tests/Test_parser.c
new file mode 100644 (file)
index 0000000..488ad36
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *      Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: Test_parser.c                               */
+/* Description: Test sequences for these functions:  */
+/*     asn1_parser_asn1,                             */   
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "libasn1.h"
+
+typedef struct{
+  int lineNumber;
+  char *line;
+  int  errorNumber;
+  char *errorDescription;
+} test_type;
+
+char fileCorrectName[]="Test_parser.asn";
+char fileErroredName[]="Test_parser_ERROR.asn";
+
+#define _FILE_ "Test_parser_ERROR.asn"
+
+test_type test_array[]={
+  /* Test DEFINITIONS syntax */
+  {5,"TEST_PARSER2 { } DEFINITIONS IMPLICIT TAGS ::= BEGIN int1 ::= INTEGER END",
+   ASN1_SYNTAX_ERROR,_FILE_":6: parse error near 'TEST_PARSER'"},
+  {6,"TEST_PARSER { }",ASN1_SUCCESS,""},
+
+  /* Test MAX_NAME_SIZE (128) */
+  {12,"a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 ::= INTEGER",
+   ASN1_SUCCESS,""},
+  {12,"a12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 ::= INTEGER",
+   ASN1_NAME_TOO_LONG,_FILE_":12: name too long (more than 128 characters)"},
+
+  /* Test 'check identifier' function */
+  {12,"ident1 ::= ident2   ident2 ::= INTEGER",
+   ASN1_SUCCESS,""},
+  {12,"ident1 ::= ident2",
+   ASN1_IDENTIFIER_NOT_FOUND,_FILE_":: identifier 'ident2' not found"},
+  {12,"obj1 OBJECT IDENTIFIER ::= {pkix 0 5 4}    "
+      "pkix OBJECT IDENTIFIER ::= {1 2}",
+   ASN1_SUCCESS,""},
+  {12,"obj1 OBJECT IDENTIFIER ::= {pkix 0 5 4}",
+   ASN1_IDENTIFIER_NOT_FOUND,_FILE_":: identifier 'pkix' not found"},
+
+  /* Test INTEGER */
+  {14,"int1 INTEGER OPTIONAL,",ASN1_SUCCESS,""},
+  {14,"int1 INTEGER DEFAULT 1,",ASN1_SUCCESS,""},
+  {14,"int1 INTEGER DEFAULT -1,",ASN1_SUCCESS,""},
+  {14,"int1 INTEGER DEFAULT v1,",ASN1_SUCCESS,""},
+  {14,"int1 [1] INTEGER,",ASN1_SUCCESS,""},
+  {14,"int1 [1] EXPLICIT INTEGER,",ASN1_SUCCESS,""},
+  {14,"int1 [1] IMPLICIT INTEGER,",ASN1_SUCCESS,""},
+  {12,"Integer ::= [1] EXPLICIT INTEGER {v1(-1), v2(1)}",ASN1_SUCCESS,""},
+  {12,"Integer ::= INTEGER {v1(0), v2}",
+   ASN1_SYNTAX_ERROR,_FILE_":12: parse error near '}'"},
+  {12,"Integer ::= INTEGER {v1(0), 1}",
+   ASN1_SYNTAX_ERROR,_FILE_":12: parse error near '1'"},
+  {12,"const1 INTEGER ::= -10",ASN1_SUCCESS,""},
+  {12,"const1 INTEGER ::= 10",ASN1_SUCCESS,""},
+  {12,"const1 INTEGER ::= v1",
+   ASN1_SYNTAX_ERROR,_FILE_":12: parse error near 'v1'"},
+  
+
+
+  /* end */
+  {0}
+};
+
+char
+readLine(FILE *file,char *line)
+{
+  char c;
+
+  while(((c=fgetc(file))!=EOF) && (c!='\n')){
+    *line=c;
+    line++;
+  }
+
+  *line=0;
+
+  return c;
+}
+
+
+void
+createFile(int lineNumber,char *line)
+{
+  FILE *fileIn,*fileOut;
+  char lineRead[1024];
+  int fileInLineNumber=0;
+
+  fileIn=fopen(fileCorrectName,"r");
+  fileOut=fopen(fileErroredName,"w");
+
+  while(readLine(fileIn,lineRead) != EOF){
+    fileInLineNumber++;
+    if(fileInLineNumber==lineNumber)
+      fprintf(fileOut,"%s\n",line);
+    else
+      fprintf(fileOut,"%s\n",lineRead);
+  }
+
+  fclose(fileOut);
+  fclose(fileIn);
+}
+
+
+int 
+main(int argc,char *argv[])
+{
+  asn1_retCode result;
+  ASN1_TYPE definitions=ASN1_TYPE_EMPTY;
+  char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
+  test_type *test;
+  int errorCounter=0,testCounter=0;
+
+  printf("\n\n/****************************************/\n");
+  printf(    "/*     Test sequence : Test_parser      */\n");
+  printf(    "/****************************************/\n\n");
+
+
+  result=asn1_parser2tree(fileCorrectName,&definitions,errorDescription);
+
+  if(result!=ASN1_SUCCESS){
+    printf("File '%s' not correct\n",fileCorrectName);
+    libasn1_perror(result);
+    printf("ErrorDescription = %s\n\n",errorDescription);
+    exit(1);
+  }
+
+  /* Only for Test */
+  //asn1_visit_tree(stdout,definitions,"TEST_PARSER",ASN1_PRINT_ALL);
+
+  /* Clear the definitions structures */
+  asn1_delete_structure(&definitions);
+
+
+  test=test_array;
+
+  while(test->lineNumber != 0){
+    testCounter++;
+
+    createFile(test->lineNumber,test->line);
+
+    result=asn1_parser2tree(fileErroredName,&definitions,errorDescription);
+    asn1_delete_structure(&definitions);
+
+    if((result != test->errorNumber) || 
+       (strcmp(errorDescription,test->errorDescription))){
+      errorCounter++;
+      printf("ERROR N. %d:\n",errorCounter);
+      printf("  Line %d - %s\n",test->lineNumber,test->line);
+      printf("  Error expected: %s - %s\n",libasn1_strerror(test->errorNumber),
+             test->errorDescription);
+      printf("  Error detected: %s - %s\n\n",libasn1_strerror(result),
+             errorDescription);
+    }
+    test++;
+  }
+
+
+  printf("Total tests : %d\n",testCounter);
+  printf("Total errors: %d\n",errorCounter);
+
+  exit(0);
+}
+
+
+
+
+
+
+
diff --git a/tests/Test_tree.asn b/tests/Test_tree.asn
new file mode 100644 (file)
index 0000000..b7a441c
--- /dev/null
@@ -0,0 +1,22 @@
+--
+--  File used in the test sequence Test_tree.
+--
+
+TEST_TREE {iso(1) identified-organization(3) dod(6) internet(1)
+  security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit-88(2)}
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+Sequence1 ::= SEQUENCE{
+    int1     INTEGER DEFAULT -5,
+    int2     INTEGER
+}
+
+END
+
+
+
+
+
diff --git a/tests/Test_tree.c b/tests/Test_tree.c
new file mode 100644 (file)
index 0000000..6b0ef69
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *      Copyright (C) 2002 Fabio Fiorina
+ *
+ * This file is part of LIBASN1.
+ *
+ * LIBASN1 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * LIBASN1 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/*****************************************************/
+/* File: Test_tree.c                                 */
+/* Description: Test sequences for these functions:  */
+/*     asn1_visit_tree,                              */   
+/*     asn1_create_structure,                        */   
+/*     asn1_delete_structure,                        */
+/*     asn1_write_value,                             */   
+/*     asn1_read_value,                              */   
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "libasn1.h"
+
+#include "Test_tree_asn1_tab.c"
+
+#define ACT_NULL   0
+#define ACT_CREATE 1
+#define ACT_DELETE 2
+#define ACT_WRITE  3
+#define ACT_READ   4
+#define ACT_VISIT  5
+
+typedef struct{
+  int action;
+  char *par1;
+  unsigned char *par2;
+  int par3;
+  int  errorNumber;
+} test_type;
+
+
+test_type test_array[]={
+  {ACT_DELETE,"","",0,ASN1_ELEMENT_NOT_FOUND},
+  {ACT_CREATE,"TEST_TREE.Sequence1","Seq",0,ASN1_SUCCESS},
+  {ACT_WRITE,"Seq.int1","1",0,ASN1_SUCCESS},
+  {ACT_READ,"Seq.int1","\x01",1,ASN1_SUCCESS},
+
+
+  {ACT_VISIT,"Seq","",ASN1_PRINT_NAME_TYPE_VALUE,ASN1_SUCCESS},
+  {ACT_DELETE,"","",0,ASN1_SUCCESS},
+
+  /* end */
+  {ACT_NULL}
+
+};
+
+
+int 
+main(int argc,char *argv[])
+{
+  asn1_retCode result;
+  ASN1_TYPE definitions=ASN1_TYPE_EMPTY;
+  ASN1_TYPE asn1_element=ASN1_TYPE_EMPTY;
+  char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
+  FILE *out;
+  test_type *test;
+  int errorCounter=0,testCounter=0;
+  unsigned char value[1024];
+  int valueLen;
+  int k;
+
+  printf("\n\n/****************************************/\n");
+  printf(    "/*     Test sequence : Test_tree        */\n");
+  printf(    "/****************************************/\n\n");
+
+  if(0)
+    result=asn1_parser2tree("Test_tree.asn",&definitions,errorDescription);
+  else
+    result=asn1_array2tree(Test_tree_asn1_tab,&definitions,errorDescription);
+
+  if(result!=ASN1_SUCCESS){
+    libasn1_perror(result);
+    printf("ErrorDescription = %s\n\n",errorDescription);
+    exit(1);
+  }
+
+  if(1)
+    out=stdout;
+  else
+    out=fopen("Test_tree.out","w");
+
+  if(out==NULL){
+    printf("Output file ERROR\n");
+    exit(1);
+  }
+
+
+  test=test_array;
+
+  while(test->action != ACT_NULL){
+    testCounter++;
+
+    switch(test->action){
+    case ACT_CREATE:
+      result=asn1_create_element(definitions,test->par1,&asn1_element,
+                test->par2);
+      break;
+    case ACT_DELETE:
+      result=asn1_delete_structure(&asn1_element);
+      break;
+    case ACT_WRITE:
+      result=asn1_write_value(asn1_element,test->par1,test->par2,test->par3);
+      break;
+    case ACT_READ:
+      result=asn1_read_value(asn1_element,test->par1,value,&valueLen);
+      break;
+    case ACT_VISIT:
+      asn1_print_structure(out,asn1_element,test->par1,test->par3);
+      fprintf(out,"\n");
+      result=ASN1_SUCCESS;
+      break;
+    default:
+      break;
+    }
+
+
+    switch(test->action){
+    case ACT_CREATE:
+    case ACT_DELETE:
+    case ACT_WRITE:
+    case ACT_VISIT:
+      if(result != test->errorNumber){
+       errorCounter++;
+       printf("ERROR N. %d:\n",errorCounter);
+       printf("  Action %d - %s - %s - %d\n",test->action,test->par1,
+              test->par2,test->par3);
+       printf("  Error expected: %s\n",libasn1_strerror(test->errorNumber));
+       printf("  Error detected: %s\n\n",libasn1_strerror(result));
+      }
+      break;
+
+    case ACT_READ:
+
+      for(k=0;k<valueLen;k++) 
+       if(test->par2[k] != value[k]){
+         k=-1;
+         break;
+       }
+
+      if((result != test->errorNumber) ||
+        (valueLen != test->par3) ||
+        (k == -1)){
+       errorCounter++;
+       printf("ERROR N. %d:\n",errorCounter);
+       printf("  Action %d - %s\n",test->action,test->par1);
+       printf("  Error expected: %s - %d - ",libasn1_strerror(test->errorNumber),
+                                             test->par3);
+       for(k=0;k<test->par3;k++)
+         printf("%02x",test->par2[k]); 
+       printf("\n  Error detected: %s - %d - ",libasn1_strerror(result),
+                                          valueLen);
+       for(k=0;k<valueLen;k++)
+         printf("%02x",value[k]);
+       printf("\n\n");
+
+      }
+
+      break;
+    default:
+      break;
+    }
+
+    test++;
+  }
+
+
+  printf("Total tests : %d\n",testCounter);
+  printf("Total errors: %d\n",errorCounter);
+
+
+  /* Clear the definition structures */
+  asn1_delete_structure(&definitions);
+
+
+  if(out != stdout) fclose(out);
+
+  exit(0);
+}
+
+
+
+
+
+
+
+
+
diff --git a/tests/Test_tree_asn1_tab.c b/tests/Test_tree_asn1_tab.c
new file mode 100644 (file)
index 0000000..5f6817c
--- /dev/null
@@ -0,0 +1,21 @@
+
+#include "libasn1.h"
+
+const ASN1_ARRAY_TYPE Test_tree_asn1_tab[]={
+  {"TEST_TREE",536875024,0},
+  {0,1610612748,0},
+  {"iso",1073741825,"1"},
+  {"identified-organization",1073741825,"3"},
+  {"dod",1073741825,"6"},
+  {"internet",1073741825,"1"},
+  {"security",1073741825,"5"},
+  {"mechanisms",1073741825,"5"},
+  {"pkix",1073741825,"7"},
+  {"id-mod",1073741825,"0"},
+  {"id-pkix1-implicit-88",1,"2"},
+  {"Sequence1",536870917,0},
+  {"int1",1610645507,0},
+  {0,9,"-5"},
+  {"int2",3,0},
+  {0,0,0}
+};