--- /dev/null
+/* 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;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/* 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;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * 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;
+}
+
+
--- /dev/null
+/*
+ * 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;
+}
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+
+#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
--- /dev/null
+/* 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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * 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 */
+
+
+
+
+
+
--- /dev/null
+/* 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
+
+
--- /dev/null
+/*
+ * 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 */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * 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;
+}
+
+
+
+
--- /dev/null
+
+#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
+
+
+
--- /dev/null
+/*
+ * 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;
+}
+
+
+
+
+
+
+
+
+
--- /dev/null
+
+/*************************************************/
+/* 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
+
--- /dev/null
+/*
+ * 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);
+}
+
+
+
+
+
--- /dev/null
+
+
+Sequence Test.Sequence1
+
+Sequence.int1 10
+Sequence.int2 -10
--- /dev/null
+Test { }
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+Sequence1 ::= SEQUENCE {
+ int1 INTEGER,
+ int2 INTEGER
+}
+
+END
--- /dev/null
+/*
+ * 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);
+}
+
+
+
+
+
--- /dev/null
+/*\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
--- /dev/null
+
+#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}
+};
--- /dev/null
+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
--- /dev/null
+/*
+ * 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);
+}
+
+
+
+
+
+
+
--- /dev/null
+--
+-- 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
+
+
+
+
+
--- /dev/null
+/*
+ * 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);
+}
+
+
+
+
+
+
+
+
+
--- /dev/null
+
+#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}
+};