From 76fad3cfc11685653d976b4b0c465e11055902b9 Mon Sep 17 00:00:00 2001 From: Fabio Fiorina Date: Wed, 15 May 2002 19:53:09 +0000 Subject: [PATCH] Start Up Version --- lib/ASN1.c | 2129 ++++++++++++++++++++++++++++++++++++++++++++ lib/ASN1.y | 763 ++++++++++++++++ lib/coding.c | 817 +++++++++++++++++ lib/decoding.c | 843 ++++++++++++++++++ lib/element.c | 646 ++++++++++++++ lib/element.h | 13 + lib/errors.c | 144 +++ lib/errors.h | 57 ++ lib/errors_int.h | 23 + lib/int.h | 166 ++++ lib/parser_aux.c | 758 ++++++++++++++++ lib/parser_aux.h | 65 ++ lib/structure.c | 855 ++++++++++++++++++ lib/structure.h | 33 + src/asn1Coding.c | 342 +++++++ src/asn1Coding_test.asg | 6 + src/asn1Coding_test.asn | 12 + src/asn1Decoding.c | 259 ++++++ src/asn1Parser.c | 207 +++++ src/pkix_asn1_tab.c | 874 ++++++++++++++++++ tests/Makefile.am | 10 + tests/Test_parser.c | 196 ++++ tests/Test_tree.asn | 22 + tests/Test_tree.c | 209 +++++ tests/Test_tree_asn1_tab.c | 21 + 25 files changed, 9470 insertions(+) create mode 100644 lib/ASN1.c create mode 100644 lib/ASN1.y create mode 100644 lib/coding.c create mode 100644 lib/decoding.c create mode 100644 lib/element.c create mode 100644 lib/element.h create mode 100644 lib/errors.c create mode 100644 lib/errors.h create mode 100644 lib/errors_int.h create mode 100644 lib/int.h create mode 100644 lib/parser_aux.c create mode 100644 lib/parser_aux.h create mode 100644 lib/structure.c create mode 100644 lib/structure.h create mode 100644 src/asn1Coding.c create mode 100644 src/asn1Coding_test.asg create mode 100644 src/asn1Coding_test.asn create mode 100644 src/asn1Decoding.c create mode 100644 src/asn1Parser.c create mode 100644 src/pkix_asn1_tab.c create mode 100644 tests/Makefile.am create mode 100644 tests/Test_parser.c create mode 100644 tests/Test_tree.asn create mode 100644 tests/Test_tree.c create mode 100644 tests/Test_tree_asn1_tab.c diff --git a/lib/ASN1.c b/lib/ASN1.c new file mode 100644 index 0000000..ad07843 --- /dev/null +++ b/lib/ASN1.c @@ -0,0 +1,2129 @@ +/* A Bison parser, made from ASN1.y + by GNU bison 1.33. */ + +#define YYBISON 1 /* Identify Bison output. */ + +# define ASSIG 257 +# define NUM 258 +# define IDENTIFIER 259 +# define OPTIONAL 260 +# define INTEGER 261 +# define SIZE 262 +# define OCTET 263 +# define STRING 264 +# define SEQUENCE 265 +# define BIT 266 +# define UNIVERSAL 267 +# define PRIVATE 268 +# define APPLICATION 269 +# define DEFAULT 270 +# define CHOICE 271 +# define OF 272 +# define OBJECT 273 +# define STR_IDENTIFIER 274 +# define BOOLEAN 275 +# define TRUE 276 +# define FALSE 277 +# define TOKEN_NULL 278 +# define ANY 279 +# define DEFINED 280 +# define BY 281 +# define SET 282 +# define EXPLICIT 283 +# define IMPLICIT 284 +# define DEFINITIONS 285 +# define TAGS 286 +# define BEGIN 287 +# define END 288 +# define UTCTime 289 +# define GeneralizedTime 290 +# define FROM 291 +# define IMPORTS 292 +# define ENUMERATED 293 + +#line 29 "ASN1.y" + +#include +#include +#include +#include + + +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 /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T std::size_t +# else +# ifdef __STDC__ +# include /* 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 /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T std::size_t +# else +# ifdef __STDC__ +# include /* 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 /* INFRINGES ON USER NAME SPACE */ +# else +# include /* 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 + +#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 + +#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" + + + 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) + { + strcpy(yylval.str,string); + return NUM; /* return the number */ + } + + /* Is STRING a keyword? */ + for(k=0;k<(sizeof(key_word)/sizeof(char*));k++) + if(!strcmp(string,key_word[k])) return key_word_token[k]; + + /* STRING is an IDENTIFIER */ + strcpy(yylval.str,string); + return IDENTIFIER; + } +} + + +/*************************************************************/ +/* Function: _asn1_create_errorDescription */ +/* Description: creates a string with the description of the*/ +/* error. */ +/* Parameters: */ +/* error : error to describe. */ +/* errorDescription: string that will contain the */ +/* description. */ +/*************************************************************/ +void +_asn1_create_errorDescription(int error,char *errorDescription) +{ + switch(error){ + case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND: + errorDescription[0]=0; + break; + case ASN1_SYNTAX_ERROR: + strcpy(errorDescription,fileName); + strcat(errorDescription,":"); + _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1); + strcat(errorDescription,": parse error near '"); + strcat(errorDescription,lastToken); + strcat(errorDescription,"'"); + break; + case ASN1_NAME_TOO_LONG: + strcpy(errorDescription,fileName); + strcat(errorDescription,":"); + _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1); + strcat(errorDescription,": name too long (more than "); + _asn1_ltostr(MAX_NAME_SIZE,errorDescription+strlen(errorDescription)); + strcat(errorDescription," characters)"); + break; + case ASN1_IDENTIFIER_NOT_FOUND: + strcpy(errorDescription,fileName); + strcat(errorDescription,":"); + strcat(errorDescription,": identifier '"); + strcat(errorDescription,identifierMissing); + strcat(errorDescription,"' not found"); + break; + default: + errorDescription[0]=0; + break; + } + +} + + +/** + * asn1_parser2tree - function used to start the parse algorithm. + * @file_name: specify the path and the name of file that contains ASN.1 declarations. + * @definitions: return the pointer to the structure created from + * "file_name" ASN.1 declarations. + * @errorDescription : return the error description or an empty string if success. + * Description: + * + * Creates the structures needed to manage the definitions included in *FILE_NAME file. + * + * Returns: + * + * ASN1_SUCCESS\: the file has a correct syntax and every identifier is known. + * + * ASN1_ELEMENT_NOT_EMPTY\: *POINTER not ASN1_TYPE_EMPTY. + * + * ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME. + * + * ASN1_SYNTAX_ERROR\: the syntax is not correct. + * + * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined. + * ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters. + **/ +asn1_retCode +asn1_parser2tree(char *file_name,ASN1_TYPE *definitions,char *errorDescription){ + + p_tree=ASN1_TYPE_EMPTY; + + if(*definitions != ASN1_TYPE_EMPTY) + return ASN1_ELEMENT_NOT_EMPTY; + + *definitions=ASN1_TYPE_EMPTY; + + fileName = file_name; + + /* open the file to parse */ + file_asn1=fopen(file_name,"r"); + + if(file_asn1==NULL){ + result_parse=ASN1_FILE_NOT_FOUND; + } + else{ + result_parse=ASN1_SUCCESS; + + lineNumber=1; + yyparse(); + + fclose(file_asn1); + + if(result_parse==ASN1_SUCCESS){ /* syntax OK */ + /* set IMPLICIT or EXPLICIT property */ + _asn1_set_default_tag(p_tree); + /* set CONST_SET and CONST_NOT_USED */ + _asn1_type_set_config(p_tree); + /* check the identifier definitions */ + result_parse=_asn1_check_identifier(p_tree); + if(result_parse==ASN1_SUCCESS){ /* all identifier defined */ + /* Delete the list and keep the ASN1 structure */ + _asn1_delete_list(); + /* Convert into DER coding the value assign to INTEGER constants */ + _asn1_change_integer_value(p_tree); + /* Expand the IDs of OBJECT IDENTIFIER constants */ + _asn1_expand_object_id(p_tree); + + *definitions=p_tree; + } + else /* some identifiers not defined */ + /* Delete the list and the ASN1 structure */ + _asn1_delete_list_and_nodes(); + } + else /* syntax error */ + /* Delete the list and the ASN1 structure */ + _asn1_delete_list_and_nodes(); + } + + _asn1_create_errorDescription(result_parse,errorDescription); + + return result_parse; +} + + +/** + * asn1_parser2array - function that generates a C structure from an ASN1 file + * @inputFileName: specify the path and the name of file that contains ASN.1 declarations. + * @outputFileName: specify the path and the name of file that will contain the C vector definition. + * @vectorName: specify the name of the C vector. + * @errorDescription : return the error description or an empty string if success. + * Description: + * + * Creates a file containing a C vector to use to manage the definitions included in + * *INPUTFILENAME file. If *INPUTFILENAME is "/aa/bb/xx.yy" and OUTPUTFILENAME is NULL, the file created is "/aa/bb/xx_asn1_tab.c". + * If VECTORNAME is NULL the vector name will be "xx_asn1_tab". + * + * Returns: + * + * ASN1_SUCCESS\: the file has a correct syntax and every identifier is known. + * + * ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME. + * + * ASN1_SYNTAX_ERROR\: the syntax is not correct. + * + * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined. + * ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters. + **/ +int asn1_parser2array(char *inputFileName,char *outputFileName,char *vectorName,char *errorDescription){ + char *file_out_name=NULL; + char *vector_name=NULL; + char *char_p,*slash_p,*dot_p; + + p_tree=NULL; + + fileName = inputFileName; + + /* open the file to parse */ + file_asn1=fopen(inputFileName,"r"); + + if(file_asn1==NULL) + result_parse=ASN1_FILE_NOT_FOUND; + else{ + result_parse=ASN1_SUCCESS; + + lineNumber=1; + yyparse(); + + fclose(file_asn1); + + if(result_parse==ASN1_SUCCESS){ /* syntax OK */ + /* set IMPLICIT or EXPLICIT property */ + _asn1_set_default_tag(p_tree); + /* set CONST_SET and CONST_NOT_USED */ + _asn1_type_set_config(p_tree); + /* check the identifier definitions */ + result_parse=_asn1_check_identifier(p_tree); + + if(result_parse==ASN1_SUCCESS){ /* all identifier defined */ + + /* searching the last '/' and '.' in inputFileName */ + char_p=inputFileName; + slash_p=inputFileName; + while((char_p=strchr(char_p,'/'))){ + char_p++; + slash_p=char_p; + } + + char_p=slash_p; + dot_p=inputFileName+strlen(inputFileName); + + while((char_p=strchr(char_p,'.'))){ + dot_p=char_p; + char_p++; + } + + if(outputFileName == NULL){ + /* file_out_name = inputFileName + _asn1_tab.c */ + file_out_name=(char *)malloc(dot_p-inputFileName+1+ + strlen("_asn1_tab.c")); + memcpy(file_out_name,inputFileName,dot_p-inputFileName); + file_out_name[dot_p-inputFileName]=0; + strcat(file_out_name,"_asn1_tab.c"); + } + else{ + /* file_out_name = inputFileName */ + file_out_name=(char *)malloc(strlen(outputFileName)+1); + strcpy(file_out_name,outputFileName); + } + + if(vectorName == NULL){ + /* vector_name = file name + _asn1_tab */ + vector_name=(char *)malloc(dot_p-slash_p+1+ + strlen("_asn1_tab")); + memcpy(vector_name,slash_p,dot_p-slash_p); + vector_name[dot_p-slash_p]=0; + strcat(vector_name,"_asn1_tab"); + } + else{ + /* vector_name = vectorName */ + vector_name=(char *)malloc(strlen(vectorName)+1); + strcpy(vector_name,vectorName); + } + + /* Save structure in a file */ + _asn1_create_static_structure(p_tree, + file_out_name,vector_name); + + free(file_out_name); + free(vector_name); + } /* result == OK */ + } /* result == OK */ + + /* Delete the list and the ASN1 structure */ + _asn1_delete_list_and_nodes(); + } /* inputFile exist */ + + _asn1_create_errorDescription(result_parse,errorDescription); + + return result_parse; +} + + +/*************************************************************/ +/* Function: yyerror */ +/* Description: function called when there are syntax errors*/ +/* Parameters: */ +/* char *s : error description */ +/* Return: int */ +/* */ +/*************************************************************/ +int yyerror (char *s) +{ + /* Sends the error description to the std_out */ + +#ifdef DEBUG_PARSER + _libasn1_log("yyerror:%s:%d: %s (Last Token:'%s')\n",fileName, + lineNumber,s,lastToken); +#endif + + if(result_parse!=ASN1_NAME_TOO_LONG) + result_parse=ASN1_SYNTAX_ERROR; + + return 0; +} + + + + + + + + + + + + + + + diff --git a/lib/ASN1.y b/lib/ASN1.y new file mode 100644 index 0000000..4f10868 --- /dev/null +++ b/lib/ASN1.y @@ -0,0 +1,763 @@ +/* Copyright (C) 2001, 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/*****************************************************/ +/* File: x509_ASN.y */ +/* Description: input file for 'bison' program. */ +/* The output file is a parser (in C language) for */ +/* ASN.1 syntax */ +/*****************************************************/ + + +%{ +#include +#include +#include +#include + + +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 NUM +%token 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 octet_string_def constant constant_list type_assig_right +%type integer_def type_assig type_assig_list sequence_def type_def +%type bit_string_def default size_def choise_def object_def +%type boolean_def any_def size_def2 obj_constant obj_constant_list +%type constant_def type_constant type_constant_list definitions +%type definitions_id Time bit_element bit_element_list set_def +%type tag_type tag type_assig_right_tag +%type type_assig_right_tag_default enumerated_def +%type pos_num neg_num pos_neg_num pos_neg_identifier num_identifier +%type 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) + { + strcpy(yylval.str,string); + return NUM; /* return the number */ + } + + /* Is STRING a keyword? */ + for(k=0;k<(sizeof(key_word)/sizeof(char*));k++) + if(!strcmp(string,key_word[k])) return key_word_token[k]; + + /* STRING is an IDENTIFIER */ + strcpy(yylval.str,string); + return IDENTIFIER; + } +} + + +/*************************************************************/ +/* Function: _asn1_create_errorDescription */ +/* Description: creates a string with the description of the*/ +/* error. */ +/* Parameters: */ +/* error : error to describe. */ +/* errorDescription: string that will contain the */ +/* description. */ +/*************************************************************/ +void +_asn1_create_errorDescription(int error,char *errorDescription) +{ + switch(error){ + case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND: + errorDescription[0]=0; + break; + case ASN1_SYNTAX_ERROR: + strcpy(errorDescription,fileName); + strcat(errorDescription,":"); + _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1); + strcat(errorDescription,": parse error near '"); + strcat(errorDescription,lastToken); + strcat(errorDescription,"'"); + break; + case ASN1_NAME_TOO_LONG: + strcpy(errorDescription,fileName); + strcat(errorDescription,":"); + _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1); + strcat(errorDescription,": name too long (more than "); + _asn1_ltostr(MAX_NAME_SIZE,errorDescription+strlen(errorDescription)); + strcat(errorDescription," characters)"); + break; + case ASN1_IDENTIFIER_NOT_FOUND: + strcpy(errorDescription,fileName); + strcat(errorDescription,":"); + strcat(errorDescription,": identifier '"); + strcat(errorDescription,identifierMissing); + strcat(errorDescription,"' not found"); + break; + default: + errorDescription[0]=0; + break; + } + +} + + +/** + * asn1_parser2tree - function used to start the parse algorithm. + * @file_name: specify the path and the name of file that contains ASN.1 declarations. + * @definitions: return the pointer to the structure created from + * "file_name" ASN.1 declarations. + * @errorDescription : return the error description or an empty string if success. + * Description: + * + * Creates the structures needed to manage the definitions included in *FILE_NAME file. + * + * Returns: + * + * ASN1_SUCCESS\: the file has a correct syntax and every identifier is known. + * + * ASN1_ELEMENT_NOT_EMPTY\: *POINTER not ASN1_TYPE_EMPTY. + * + * ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME. + * + * ASN1_SYNTAX_ERROR\: the syntax is not correct. + * + * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined. + * ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters. + **/ +asn1_retCode +asn1_parser2tree(char *file_name,ASN1_TYPE *definitions,char *errorDescription){ + + p_tree=ASN1_TYPE_EMPTY; + + if(*definitions != ASN1_TYPE_EMPTY) + return ASN1_ELEMENT_NOT_EMPTY; + + *definitions=ASN1_TYPE_EMPTY; + + fileName = file_name; + + /* open the file to parse */ + file_asn1=fopen(file_name,"r"); + + if(file_asn1==NULL){ + result_parse=ASN1_FILE_NOT_FOUND; + } + else{ + result_parse=ASN1_SUCCESS; + + lineNumber=1; + yyparse(); + + fclose(file_asn1); + + if(result_parse==ASN1_SUCCESS){ /* syntax OK */ + /* set IMPLICIT or EXPLICIT property */ + _asn1_set_default_tag(p_tree); + /* set CONST_SET and CONST_NOT_USED */ + _asn1_type_set_config(p_tree); + /* check the identifier definitions */ + result_parse=_asn1_check_identifier(p_tree); + if(result_parse==ASN1_SUCCESS){ /* all identifier defined */ + /* Delete the list and keep the ASN1 structure */ + _asn1_delete_list(); + /* Convert into DER coding the value assign to INTEGER constants */ + _asn1_change_integer_value(p_tree); + /* Expand the IDs of OBJECT IDENTIFIER constants */ + _asn1_expand_object_id(p_tree); + + *definitions=p_tree; + } + else /* some identifiers not defined */ + /* Delete the list and the ASN1 structure */ + _asn1_delete_list_and_nodes(); + } + else /* syntax error */ + /* Delete the list and the ASN1 structure */ + _asn1_delete_list_and_nodes(); + } + + _asn1_create_errorDescription(result_parse,errorDescription); + + return result_parse; +} + + +/** + * asn1_parser2array - function that generates a C structure from an ASN1 file + * @inputFileName: specify the path and the name of file that contains ASN.1 declarations. + * @outputFileName: specify the path and the name of file that will contain the C vector definition. + * @vectorName: specify the name of the C vector. + * @errorDescription : return the error description or an empty string if success. + * Description: + * + * Creates a file containing a C vector to use to manage the definitions included in + * *INPUTFILENAME file. If *INPUTFILENAME is "/aa/bb/xx.yy" and OUTPUTFILENAME is NULL, the file created is "/aa/bb/xx_asn1_tab.c". + * If VECTORNAME is NULL the vector name will be "xx_asn1_tab". + * + * Returns: + * + * ASN1_SUCCESS\: the file has a correct syntax and every identifier is known. + * + * ASN1_FILE_NOT_FOUND\: an error occured while opening FILE_NAME. + * + * ASN1_SYNTAX_ERROR\: the syntax is not correct. + * + * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined. + * ASN1_NAME_TOO_LONG\: in the file there is an identifier whith more than MAX_NAME_SIZE characters. + **/ +int asn1_parser2array(char *inputFileName,char *outputFileName,char *vectorName,char *errorDescription){ + char *file_out_name=NULL; + char *vector_name=NULL; + char *char_p,*slash_p,*dot_p; + + p_tree=NULL; + + fileName = inputFileName; + + /* open the file to parse */ + file_asn1=fopen(inputFileName,"r"); + + if(file_asn1==NULL) + result_parse=ASN1_FILE_NOT_FOUND; + else{ + result_parse=ASN1_SUCCESS; + + lineNumber=1; + yyparse(); + + fclose(file_asn1); + + if(result_parse==ASN1_SUCCESS){ /* syntax OK */ + /* set IMPLICIT or EXPLICIT property */ + _asn1_set_default_tag(p_tree); + /* set CONST_SET and CONST_NOT_USED */ + _asn1_type_set_config(p_tree); + /* check the identifier definitions */ + result_parse=_asn1_check_identifier(p_tree); + + if(result_parse==ASN1_SUCCESS){ /* all identifier defined */ + + /* searching the last '/' and '.' in inputFileName */ + char_p=inputFileName; + slash_p=inputFileName; + while((char_p=strchr(char_p,'/'))){ + char_p++; + slash_p=char_p; + } + + char_p=slash_p; + dot_p=inputFileName+strlen(inputFileName); + + while((char_p=strchr(char_p,'.'))){ + dot_p=char_p; + char_p++; + } + + if(outputFileName == NULL){ + /* file_out_name = inputFileName + _asn1_tab.c */ + file_out_name=(char *)malloc(dot_p-inputFileName+1+ + strlen("_asn1_tab.c")); + memcpy(file_out_name,inputFileName,dot_p-inputFileName); + file_out_name[dot_p-inputFileName]=0; + strcat(file_out_name,"_asn1_tab.c"); + } + else{ + /* file_out_name = inputFileName */ + file_out_name=(char *)malloc(strlen(outputFileName)+1); + strcpy(file_out_name,outputFileName); + } + + if(vectorName == NULL){ + /* vector_name = file name + _asn1_tab */ + vector_name=(char *)malloc(dot_p-slash_p+1+ + strlen("_asn1_tab")); + memcpy(vector_name,slash_p,dot_p-slash_p); + vector_name[dot_p-slash_p]=0; + strcat(vector_name,"_asn1_tab"); + } + else{ + /* vector_name = vectorName */ + vector_name=(char *)malloc(strlen(vectorName)+1); + strcpy(vector_name,vectorName); + } + + /* Save structure in a file */ + _asn1_create_static_structure(p_tree, + file_out_name,vector_name); + + free(file_out_name); + free(vector_name); + } /* result == OK */ + } /* result == OK */ + + /* Delete the list and the ASN1 structure */ + _asn1_delete_list_and_nodes(); + } /* inputFile exist */ + + _asn1_create_errorDescription(result_parse,errorDescription); + + return result_parse; +} + + +/*************************************************************/ +/* Function: yyerror */ +/* Description: function called when there are syntax errors*/ +/* Parameters: */ +/* char *s : error description */ +/* Return: int */ +/* */ +/*************************************************************/ +int yyerror (char *s) +{ + /* Sends the error description to the std_out */ + +#ifdef DEBUG_PARSER + _libasn1_log("yyerror:%s:%d: %s (Last Token:'%s')\n",fileName, + lineNumber,s,lastToken); +#endif + + if(result_parse!=ASN1_NAME_TOO_LONG) + result_parse=ASN1_SYNTAX_ERROR; + + return 0; +} + + + + + + + + + + + + + + + diff --git a/lib/coding.c b/lib/coding.c new file mode 100644 index 0000000..d67f394 --- /dev/null +++ b/lib/coding.c @@ -0,0 +1,817 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/*****************************************************/ +/* File: coding.c */ +/* Description: Functions to create a DER coding of */ +/* an ASN1 type. */ +/*****************************************************/ + +#include +#include +#include "der.h" +#include "parser_aux.h" +#include +#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;kder[p_vet->end+k]){change=1;break;} + else if(der[counter+k]end+k]){change=0;break;} + + if((change==-1) && ((p_vet->end-counter)>(p2_vet->end-p_vet->end))) + change=1; + + if(change==1){ + /* change position */ + temp=(unsigned char *)_asn1_alloca(p_vet->end-counter); + if (temp==NULL) return; + + memcpy(temp,der+counter,p_vet->end-counter); + memmove(der+counter,der+p_vet->end,p2_vet->end-p_vet->end); + memcpy(der+p_vet->end,temp,p_vet->end-counter); + _asn1_afree(temp); + + p_vet->end=counter+(p2_vet->end-p_vet->end); + } + counter=p_vet->end; + + p2_vet=p2_vet->next; + p_vet=p_vet->next; + } + + if(p_vet!=first) p_vet->prev->next=NULL; + else first=NULL; + _asn1_afree(p_vet); + p_vet=first; + } +} + +/** + * asn1_der_coding - Creates the DER encoding for the NAME structure + * @element: pointer to an ASN1 element + * @name: the name of the structure you want to encode (it must be inside *POINTER). + * @der: vector that will contain the DER encoding. DER must be a pointer to memory cells already allocated. + * @len: number of bytes of *der: der[0]..der[len-1] + * @errorDescription : return the error description or an empty string if success. + * Description: + * + * Creates the DER encoding for the NAME structure (inside *POINTER structure). + * + * Returns: + * + * ASN1_SUCCESS\: DER encoding OK + * + * ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element. + * + * ASN1_VALUE_NOT_FOUND\: there is an element without a value. + **/ +asn1_retCode +asn1_der_coding(ASN1_TYPE element,char *name,unsigned char *der,int *len, + char *ErrorDescription) +{ + node_asn *node,*p; + char temp[SIZEOF_UNSIGNED_LONG_INT*3+1]; + int counter,counter_old,len2,len3,move,ris; + + node=_asn1_find_node(element,name); + if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + + counter=0; + move=DOWN; + p=node; + while(1){ + + counter_old=counter; + if(move!=UP) ris=_asn1_insert_tag_der(p,der,&counter); + + switch(type_field(p->type)){ + case TYPE_NULL: + der[counter]=0; + counter++; + move=RIGHT; + break; + case TYPE_BOOLEAN: + if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old; + else{ + der[counter++]=1; + if(p->value[0]=='F') der[counter++]=0; + else der[counter++]=0xFF; + } + move=RIGHT; + break; + case TYPE_INTEGER: case TYPE_ENUMERATED: + if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old; + else{ + if(p->value==NULL){ + _asn1_error_description_value_not_found(p,ErrorDescription); + return ASN1_VALUE_NOT_FOUND; + } + len2=_asn1_get_length_der(p->value,&len3); + memcpy(der+counter,p->value,len3+len2); + counter+=len3+len2; + } + move=RIGHT; + break; + case TYPE_OBJECT_ID: + _asn1_objectid_der(p->value,der+counter,&len2); + counter+=len2; + move=RIGHT; + break; + case TYPE_TIME: + _asn1_time_der(p->value,der+counter,&len2); + counter+=len2; + move=RIGHT; + break; + case TYPE_OCTET_STRING: + len2=_asn1_get_length_der(p->value,&len3); + memcpy(der+counter,p->value,len3+len2); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_BIT_STRING: + len2=_asn1_get_length_der(p->value,&len3); + memcpy(der+counter,p->value,len3+len2); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_SEQUENCE: case TYPE_SET: + if(move!=UP){ + _asn1_ltostr(counter,temp); + _asn1_set_value(p,temp,strlen(temp)+1); + move=DOWN; + } + else{ /* move==UP */ + len2=strtol(p->value,NULL,10); + _asn1_set_value(p,NULL,0); + if(type_field(p->type)==TYPE_SET) _asn1_ordering_set(der+len2,p); + _asn1_length_der(counter-len2,temp,&len3); + memmove(der+len2+len3,der+len2,counter-len2); + memcpy(der+len2,temp,len3); + counter+=len3; + move=RIGHT; + } + break; + case TYPE_SEQUENCE_OF: case TYPE_SET_OF: + if(move!=UP){ + _asn1_ltostr(counter,temp); + _asn1_set_value(p,temp,strlen(temp)+1); + p=p->down; + while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right; + if(p->right){ + p=p->right; + move=RIGHT; + continue; + } + else p=_asn1_find_up(p); + move=UP; + } + if(move==UP){ + len2=strtol(p->value,NULL,10); + _asn1_set_value(p,NULL,0); + if(type_field(p->type)==TYPE_SET_OF) _asn1_ordering_set_of(der+len2,p); + _asn1_length_der(counter-len2,temp,&len3); + memmove(der+len2+len3,der+len2,counter-len2); + memcpy(der+len2,temp,len3); + counter+=len3; + move=RIGHT; + } + break; + case TYPE_ANY: + len2=_asn1_get_length_der(p->value,&len3); + memcpy(der+counter,p->value+len3,len2); + counter+=len2; + move=RIGHT; + break; + default: + move=(move==UP)?RIGHT:DOWN; + break; + } + + if((move!=DOWN) && (counter!=counter_old)) + _asn1_complete_explicit_tag(p,der,&counter); + + if(p==node && move!=DOWN) break; + + if(move==DOWN){ + if(p->down) p=p->down; + else move=RIGHT; + } + if(move==RIGHT){ + if(p->right) p=p->right; + else move=UP; + } + if(move==UP) p=_asn1_find_up(p); + } + + *len=counter; + return ASN1_SUCCESS; +} + + diff --git a/lib/decoding.c b/lib/decoding.c new file mode 100644 index 0000000..266d823 --- /dev/null +++ b/lib/decoding.c @@ -0,0 +1,843 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/*****************************************************/ +/* File: decoding.c */ +/* Description: Functions to manage DER decoding */ +/*****************************************************/ + +#include +#include +#include "der.h" +#include "parser_aux.h" +#include +#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_byte) + memcpy(str,der+len_len+1,len_byte); + else { + return ASN1_MEM_ERROR; + } + *bit_len=len_byte*8-der[len_len]; + *der_len=len_byte+len_len+1; + + return ASN1_SUCCESS; +} + + + + +int +_asn1_extract_tag_der(node_asn *node,unsigned char *der,int *der_len) +{ + node_asn *p; + int counter,len2,len3,is_tag_implicit; + unsigned long tag,tag_implicit=0; + unsigned char class,class2,class_implicit=0; + + counter=is_tag_implicit=0; + if(node->type&CONST_TAG){ + p=node->down; + while(p){ + if(type_field(p->type)==TYPE_TAG){ + if(p->type&CONST_APPLICATION) class2=APPLICATION; + else if(p->type&CONST_UNIVERSAL) class2=UNIVERSAL; + else if(p->type&CONST_PRIVATE) class2=PRIVATE; + else class2=CONTEXT_SPECIFIC; + + if(p->type&CONST_EXPLICIT){ + tag=_asn1_get_tag_der(der+counter,&class,&len2); + counter+=len2; + len3=_asn1_get_length_der(der+counter,&len2); + counter+=len2; + if(!is_tag_implicit){ + if((class!=(class2|STRUCTURED)) || (tag!=strtoul(p->value,NULL,10))) + return ASN1_TAG_ERROR; + } + else{ /* TAG_IMPLICIT */ + if((class!=class_implicit) || (tag!=tag_implicit)) + return ASN1_TAG_ERROR; + } + + is_tag_implicit=0; + } + else{ /* TAG_IMPLICIT */ + if(!is_tag_implicit){ + if((type_field(node->type)==TYPE_SEQUENCE) || + (type_field(node->type)==TYPE_SEQUENCE_OF) || + (type_field(node->type)==TYPE_SET) || + (type_field(node->type)==TYPE_SET_OF)) class2|=STRUCTURED; + class_implicit=class2; + tag_implicit=strtoul(p->value,NULL,10); + is_tag_implicit=1; + } + } + } + p=p->right; + } + } + + if(is_tag_implicit){ + tag=_asn1_get_tag_der(der+counter,&class,&len2); + if((class!=class_implicit) || (tag!=tag_implicit)) return ASN1_TAG_ERROR; + } + else{ + if(type_field(node->type)==TYPE_TAG){ + counter=0; + *der_len=counter; + return ASN1_SUCCESS; + } + + tag=_asn1_get_tag_der(der+counter,&class,&len2); + switch(type_field(node->type)){ + case TYPE_NULL: + if((class!=UNIVERSAL) || (tag!=TAG_NULL)) return ASN1_DER_ERROR; + break; + case TYPE_BOOLEAN: + if((class!=UNIVERSAL) || (tag!=TAG_BOOLEAN)) return ASN1_DER_ERROR; + break; + case TYPE_INTEGER: + if((class!=UNIVERSAL) || (tag!=TAG_INTEGER)) return ASN1_DER_ERROR; + break; + case TYPE_ENUMERATED: + if((class!=UNIVERSAL) || (tag!=TAG_ENUMERATED)) return ASN1_DER_ERROR; + break; + case TYPE_OBJECT_ID: + if((class!=UNIVERSAL) || (tag!=TAG_OBJECT_ID)) return ASN1_DER_ERROR; + break; + case TYPE_TIME: + if(node->type&CONST_UTC){ + if((class!=UNIVERSAL) || (tag!=TAG_UTCTime)) return ASN1_DER_ERROR; + } + else{ + if((class!=UNIVERSAL) || (tag!=TAG_GENERALIZEDTime)) + return ASN1_DER_ERROR; + } + break; + case TYPE_OCTET_STRING: + if((class!=UNIVERSAL) || (tag!=TAG_OCTET_STRING)) return ASN1_DER_ERROR; + break; + case TYPE_BIT_STRING: + if((class!=UNIVERSAL) || (tag!=TAG_BIT_STRING)) return ASN1_DER_ERROR; + break; + case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF: + if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SEQUENCE)) + return ASN1_DER_ERROR; + break; + case TYPE_SET: case TYPE_SET_OF: + if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SET)) + return ASN1_DER_ERROR; + break; + case TYPE_ANY: + counter-=len2; + break; + default: + return ASN1_DER_ERROR; + break; + } + } + + counter+=len2; + *der_len=counter; + return ASN1_SUCCESS; +} + + +int +_asn1_delete_not_used(node_asn *node) +{ + node_asn *p,*p2; + + if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + + p=node; + while(p){ + if(p->type&CONST_NOT_USED){ + p2=NULL; + if(p!=node){ + p2=_asn1_find_left(p); + if(!p2) p2=_asn1_find_up(p); + } + asn1_delete_structure(&p); + p=p2; + } + + if(!p) break; /* reach node */ + + if(p->down){ + p=p->down; + } + else{ + if(p==node) p=NULL; + else if(p->right) p=p->right; + else{ + while(1){ + p=_asn1_find_up(p); + if(p==node){ + p=NULL; + break; + } + if(p->right){ + p=p->right; + break; + } + } + } + } + } + return ASN1_SUCCESS; +} + + + +/** + * asn1_der_decoding - Fill the structure *ELEMENT with values of a DER encoding string. + * @element: pointer to an ASN1 structure + * @der: vector that contains the DER encoding. + * @len: number of bytes of *der: der[0]..der[len-1] + * Description: + * + * Fill the structure *ELEMENT with values of a DER encoding string. The sructure must just be + * created with function 'create_stucture'. + * If an error accurs during de decoding procedure, the *ELEMENT is deleted + * and set equal to ASN1_TYPE_EMPTY. + * + * Returns: + * + * ASN1_SUCCESS\: DER encoding OK + * + * ASN1_ELEMENT_NOT_FOUND\: ELEMENT is ASN1_TYPE_EMPTY. + * + * ASN1_TAG_ERROR,ASN1_DER_ERROR\: the der encoding doesn't match the structure NAME. *ELEMENT deleted. + **/ + +asn1_retCode +asn1_der_decoding(ASN1_TYPE *element,unsigned char *der,int len,char *errorDescription) +{ + node_asn *node,*p,*p2,*p3; + char temp[128]; + int counter,len2,len3,len4,move,ris; + unsigned char class,*temp2; + unsigned int tag; + + node=*element; + + if(node==ASN1_TYPE_EMPTY) return ASN1_ELEMENT_NOT_FOUND; + + if(node->type&CONST_OPTION){ + asn1_delete_structure(element); + return ASN1_GENERIC_ERROR; + } + + counter=0; + move=DOWN; + p=node; + while(1){ + ris=ASN1_SUCCESS; + + if(move!=UP){ + if(p->type&CONST_SET){ + p2=_asn1_find_up(p); + len2=strtol(p2->value,NULL,10); + if(counter==len2){ + p=p2; + move=UP; + continue; + } + else if(counter>len2){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + p2=p2->down; + while(p2){ + if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){ + if(type_field(p2->type)!=TYPE_CHOICE) + ris=_asn1_extract_tag_der(p2,der+counter,&len2); + else{ + p3=p2->down; + while(p3){ + ris=_asn1_extract_tag_der(p3,der+counter,&len2); + if(ris==ASN1_SUCCESS) break; + //if(ris==ASN1_ERROR_TYPE_ANY) return ASN1_ERROR_TYPE_ANY; + p3=p3->right; + } + } + if(ris==ASN1_SUCCESS){ + p2->type&=~CONST_NOT_USED; + p=p2; + break; + } + //else if(ris==ASN1_ERROR_TYPE_ANY) return ASN1_ERROR_TYPE_ANY; + } + p2=p2->right; + } + if(p2==NULL){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + } + + if(type_field(p->type)==TYPE_CHOICE){ + while(p->down){ + ris=_asn1_extract_tag_der(p->down,der+counter,&len2); + if(ris==ASN1_SUCCESS){ + while(p->down->right){ + p2=p->down->right; + asn1_delete_structure(&p2); + } + break; + } + else if(ris==ASN1_ERROR_TYPE_ANY){ + asn1_delete_structure(element); + return ASN1_ERROR_TYPE_ANY; + } + else{ + p2=p->down; + asn1_delete_structure(&p2); + } + } + if(p->down==NULL){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + p=p->down; + } + + if((p->type&CONST_OPTION) || (p->type&CONST_DEFAULT)){ + p2=_asn1_find_up(p); + len2=strtol(p2->value,NULL,10); + if(counter>=len2) ris=ASN1_TAG_ERROR; + } + + if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,&len2); + if(ris!=ASN1_SUCCESS){ + //if(ris==ASN1_ERROR_TYPE_ANY) return ASN1_ERROR_TYPE_ANY; + if(p->type&CONST_OPTION){ + p->type|=CONST_NOT_USED; + move=RIGHT; + } + else if(p->type&CONST_DEFAULT) { + _asn1_set_value(p,NULL,0); + move=RIGHT; + } + else { + //return (type_field(p->type)!=TYPE_ANY)?ASN1_TAG_ERROR:ASN1_ERROR_TYPE_ANY; + _asn1_error_description_tag_error(p,errorDescription); + + asn1_delete_structure(element); + return ASN1_TAG_ERROR; + } + } + else counter+=len2; + } + + if(ris==ASN1_SUCCESS){ + switch(type_field(p->type)){ + case TYPE_NULL: + if(der[counter]){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + counter++; + move=RIGHT; + break; + case TYPE_BOOLEAN: + if(der[counter++]!=1){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + if(der[counter++]==0) _asn1_set_value(p,"F",1); + else _asn1_set_value(p,"T",1); + move=RIGHT; + break; + case TYPE_INTEGER: case TYPE_ENUMERATED: + len2=_asn1_get_length_der(der+counter,&len3); + _asn1_set_value(p,der+counter,len3+len2); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_OBJECT_ID: + _asn1_get_objectid_der(der+counter,&len2, temp, sizeof(temp)); + _asn1_set_value(p,temp,strlen(temp)+1); + counter+=len2; + move=RIGHT; + break; + case TYPE_TIME: + _asn1_get_time_der(der+counter,&len2,temp); + _asn1_set_value(p,temp,strlen(temp)+1); + counter+=len2; + move=RIGHT; + break; + case TYPE_OCTET_STRING: + len2=_asn1_get_length_der(der+counter,&len3); + _asn1_set_value(p,der+counter,len3+len2); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_BIT_STRING: + len2=_asn1_get_length_der(der+counter,&len3); + _asn1_set_value(p,der+counter,len3+len2); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_SEQUENCE: case TYPE_SET:; + if(move==UP){ + len2=strtol(p->value,NULL,10); + _asn1_set_value(p,NULL,0); + if(len2!=counter){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + move=RIGHT; + } + else{ /* move==DOWN || move==RIGHT */ + len3=_asn1_get_length_der(der+counter,&len2); + counter+=len2; + _asn1_ltostr(counter+len3,temp); + _asn1_set_value(p,temp,strlen(temp)+1); + move=DOWN; + } + break; + case TYPE_SEQUENCE_OF: case TYPE_SET_OF: + if(move==UP){ + len2=strtol(p->value,NULL,10); + if(len2>counter){ + _asn1_append_sequence_set(p); + p=p->down; + while(p->right) p=p->right; + move=RIGHT; + continue; + } + _asn1_set_value(p,NULL,0); + if(len2!=counter){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + } + else{ /* move==DOWN || move==RIGHT */ + len3=_asn1_get_length_der(der+counter,&len2); + counter+=len2; + if(len3){ + _asn1_ltostr(counter+len3,temp); + _asn1_set_value(p,temp,strlen(temp)+1); + p2=p->down; + while((type_field(p2->type)==TYPE_TAG) || (type_field(p2->type)==TYPE_SIZE)) p2=p2->right; + if(p2->right==NULL) _asn1_append_sequence_set(p); + p=p2; + } + } + move=RIGHT; + break; + case TYPE_ANY: + tag=_asn1_get_tag_der(der+counter,&class,&len2); + len2+=_asn1_get_length_der(der+counter+len2,&len3); + _asn1_length_der(len2+len3,NULL,&len4); + temp2=(unsigned char *)_asn1_alloca(len2+len3+len4); + if (temp2==NULL){ + asn1_delete_structure(element); + return ASN1_MEM_ERROR; + } + + _asn1_octet_der(der+counter,len2+len3,temp2,&len4); + _asn1_set_value(p,temp2,len4); + _asn1_afree(temp2); + counter+=len2+len3; + move=RIGHT; + break; + default: + move=(move==UP)?RIGHT:DOWN; + break; + } + } + + if(p==node && move!=DOWN) break; + + if(move==DOWN){ + if(p->down) p=p->down; + else move=RIGHT; + } + if((move==RIGHT) && !(p->type&CONST_SET)){ + if(p->right) p=p->right; + else move=UP; + } + if(move==UP) p=_asn1_find_up(p); + } + + _asn1_delete_not_used(*element); + + if(counter != len){ + asn1_delete_structure(element); + return ASN1_DER_ERROR; + } + + return ASN1_SUCCESS; +} + + +/** + * asn1_der_decoding_startEnd - Find the start and end point of an element in a DER encoding string. + * @element: pointer to an ASN1 element + * @der: vector that contains the DER encoding. + * @len: number of bytes of *der: der[0]..der[len-1] + * @name_element: an element of NAME structure. + * @start: the position of the first byte of NAME_ELEMENT decoding (der[*start]) + * @end: the position of the last byte of NAME_ELEMENT decoding (der[*end]) + * Description: + * + * Find the start and end point of an element in a DER encoding string. I mean that if you + * have a der encoding and you have already used the function "asn1_der_decoding" to fill a structure, it may + * happen that you want to find the piece of string concerning an element of the structure. + * + * Example: the sequence "tbsCertificate" inside an X509 certificate. + * + * Returns: + * + * ASN1_SUCCESS\: DER encoding OK + * + * ASN1_ELEMENT_NOT_FOUND\: ELEMENT is ASN1_TYPE EMPTY or NAME_ELEMENT is not a valid element. + * + * ASN1_TAG_ERROR,ASN1_DER_ERROR\: the der encoding doesn't match the structure ELEMENT. + * + **/ +asn1_retCode +asn1_der_decoding_startEnd(ASN1_TYPE element,unsigned char *der,int len,char *name_element,int *start, int *end) +{ + node_asn *node,*node_to_find,*p,*p2,*p3; + int counter,len2,len3,move,ris; + unsigned char class; + unsigned int tag; + + node=element; + + if(node==ASN1_TYPE_EMPTY) return ASN1_ELEMENT_NOT_FOUND; + + node_to_find=_asn1_find_node(node,name_element); + + if(node_to_find==NULL) return ASN1_ELEMENT_NOT_FOUND; + + if(node_to_find==node){ + *start=0; + *end=len-1; + return ASN1_SUCCESS; + } + + if(node->type&CONST_OPTION) return ASN1_GENERIC_ERROR; + + counter=0; + move=DOWN; + p=node; + while(1){ + ris=ASN1_SUCCESS; + + if(move!=UP){ + if(p->type&CONST_SET){ + p2=_asn1_find_up(p); + len2=strtol(p2->value,NULL,10); + if(counter==len2){ + p=p2; + move=UP; + continue; + } + else if(counter>len2) return ASN1_DER_ERROR; + p2=p2->down; + while(p2){ + if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){ /* CONTROLLARE */ + if(type_field(p2->type)!=TYPE_CHOICE) + ris=_asn1_extract_tag_der(p2,der+counter,&len2); + else{ + p3=p2->down; + ris=_asn1_extract_tag_der(p3,der+counter,&len2); + } + if(ris==ASN1_SUCCESS){ + p2->type&=~CONST_NOT_USED; + p=p2; + break; + } + } + p2=p2->right; + } + if(p2==NULL) return ASN1_DER_ERROR; + } + + if(p==node_to_find) *start=counter; + + if(type_field(p->type)==TYPE_CHOICE){ + p=p->down; + ris=_asn1_extract_tag_der(p,der+counter,&len2); + if(p==node_to_find) *start=counter; + } + + if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,&len2); + if(ris!=ASN1_SUCCESS){ + if(p->type&CONST_OPTION){ + p->type|=CONST_NOT_USED; + move=RIGHT; + } + else if(p->type&CONST_DEFAULT) { + move=RIGHT; + } + else { + return ASN1_TAG_ERROR; + } + } + else counter+=len2; + } + + if(ris==ASN1_SUCCESS){ + switch(type_field(p->type)){ + case TYPE_NULL: + if(der[counter]) return ASN1_DER_ERROR; + counter++; + move=RIGHT; + break; + case TYPE_BOOLEAN: + if(der[counter++]!=1) return ASN1_DER_ERROR; + counter++; + move=RIGHT; + break; + case TYPE_INTEGER: case TYPE_ENUMERATED: + len2=_asn1_get_length_der(der+counter,&len3); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_OBJECT_ID: + len2=_asn1_get_length_der(der+counter,&len3); + counter+=len2+len3; + move=RIGHT; + break; + case TYPE_TIME: + len2=_asn1_get_length_der(der+counter,&len3); + counter+=len2+len3; + move=RIGHT; + break; + case TYPE_OCTET_STRING: + len2=_asn1_get_length_der(der+counter,&len3); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_BIT_STRING: + len2=_asn1_get_length_der(der+counter,&len3); + counter+=len3+len2; + move=RIGHT; + break; + case TYPE_SEQUENCE: case TYPE_SET: + if(move!=UP){ + len3=_asn1_get_length_der(der+counter,&len2); + counter+=len2; + move=DOWN; + } + else move=RIGHT; + break; + case TYPE_SEQUENCE_OF: case TYPE_SET_OF: + if(move!=UP){ + len3=_asn1_get_length_der(der+counter,&len2); + counter+=len2; + if(len3){ + p2=p->down; + while((type_field(p2->type)==TYPE_TAG) || + (type_field(p2->type)==TYPE_SIZE)) p2=p2->right; + p=p2; + } + } + move=RIGHT; + break; + case TYPE_ANY: + tag=_asn1_get_tag_der(der+counter,&class,&len2); + len2+=_asn1_get_length_der(der+counter+len2,&len3); + counter+=len3+len2; + move=RIGHT; + break; + default: + move=(move==UP)?RIGHT:DOWN; + break; + } + } + + if((p==node_to_find) && (move==RIGHT)){ + *end=counter-1; + return ASN1_SUCCESS; + } + + if(p==node && move!=DOWN) break; + + if(move==DOWN){ + if(p->down) p=p->down; + else move=RIGHT; + } + if((move==RIGHT) && !(p->type&CONST_SET)){ + if(p->right) p=p->right; + else move=UP; + } + if(move==UP) p=_asn1_find_up(p); + } + + return ASN1_ELEMENT_NOT_FOUND; +} + + + + + + + + + + diff --git a/lib/element.c b/lib/element.c new file mode 100644 index 0000000..d12330b --- /dev/null +++ b/lib/element.c @@ -0,0 +1,646 @@ +/* + * Copyright (C) 2000,2001 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/*****************************************************/ +/* File: element.c */ +/* Description: Functions with the read and write */ +/* functions. */ +/*****************************************************/ + + +#include +#include +#include "parser_aux.h" +#include "der.h" +#include +#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 value_out_size) + /* VALUE_OUT is too short to contain the value convertion */ + return ASN1_MEM_ERROR; + + for(k2=k;k2down)) 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;ktype&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;k2type&CONST_UTC){ + if(strlen(value)<11) return ASN1_VALUE_NOT_VALID; + for(k=0;k<10;k++) + if(!isdigit(value[k])) return ASN1_VALUE_NOT_VALID; + switch(strlen(value)){ + case 11: + if(value[10]!='Z') return ASN1_VALUE_NOT_VALID; + break; + case 13: + if((!isdigit(value[10])) || (!isdigit(value[11])) || + (value[12]!='Z')) return ASN1_VALUE_NOT_VALID; + break; + case 15: + if((value[10]!='+') && (value[10]!='-')) return ASN1_VALUE_NOT_VALID; + for(k=11;k<15;k++) + if(!isdigit(value[k])) return ASN1_VALUE_NOT_VALID; + break; + case 17: + if((!isdigit(value[10])) || (!isdigit(value[11]))) + return ASN1_VALUE_NOT_VALID; + if((value[12]!='+') && (value[12]!='-')) return ASN1_VALUE_NOT_VALID; + for(k=13;k<17;k++) + if(!isdigit(value[k])) return ASN1_VALUE_NOT_VALID; + break; + default: + return ASN1_VALUE_NOT_FOUND; + } + _asn1_set_value(node,value,strlen(value)+1); + } + else{ /* GENERALIZED TIME */ + if(value) _asn1_set_value(node,value,strlen(value)+1); + } + break; + case TYPE_OCTET_STRING: + _asn1_length_der(len,NULL,&len2); + temp=(unsigned char *)_asn1_alloca(len+len2); + if (temp==NULL) return ASN1_MEM_ERROR; + + _asn1_octet_der(value,len,temp,&len2); + _asn1_set_value(node,temp,len2); + _asn1_afree(temp); + break; + case TYPE_BIT_STRING: + _asn1_length_der((len>>3)+2,NULL,&len2); + temp=(unsigned char *)_asn1_alloca((len>>3)+2+len2); + if (temp==NULL) return ASN1_MEM_ERROR; + + _asn1_bit_der(value,len,temp,&len2); + _asn1_set_value(node,temp,len2); + _asn1_afree(temp); + break; + case TYPE_CHOICE: + p=node->down; + while(p){ + if(!strcmp(p->name,value)){ + p2=node->down; + while(p2){ + if(p2!=p){asn1_delete_structure(&p2); p2=node->down;} + else p2=p2->right; + } + break; + } + p=p->right; + } + if(!p) return ASN1_ELEMENT_NOT_FOUND; + break; + case TYPE_ANY: + _asn1_length_der(len,NULL,&len2); + temp=(unsigned char *)_asn1_alloca(len+len2); + if (temp==NULL) return ASN1_MEM_ERROR; + + _asn1_octet_der(value,len,temp,&len2); + _asn1_set_value(node,temp,len2); + _asn1_afree(temp); + break; + case TYPE_SEQUENCE_OF: case TYPE_SET_OF: + if(strcmp(value,"NEW")) return ASN1_VALUE_NOT_VALID; + _asn1_append_sequence_set(node); + break; + default: + return ASN1_ELEMENT_NOT_FOUND; + break; + } + + return ASN1_SUCCESS; +} + + +#define PUT_VALUE( ptr, ptr_size, data, data_size) \ + *len = data_size; \ + if (ptr_size < data_size) { \ + return ASN1_MEM_ERROR; \ + } else { \ + memcpy( ptr, data, data_size); \ + } + +#define PUT_STR_VALUE( ptr, ptr_size, data) \ + *len = strlen(data) + 1; \ + if (ptr_size < *len) { \ + return ASN1_MEM_ERROR; \ + } else { \ + /* this strcpy is checked */ \ + strcpy(ptr, data); \ + } + +#define ADD_STR_VALUE( ptr, ptr_size, data) \ + *len = strlen(data) + 1; \ + if (ptr_size < strlen(ptr)+(*len)) { \ + return ASN1_MEM_ERROR; \ + } else { \ + /* this strcat is checked */ \ + strcat(ptr, data); \ + } + +/** + * asn1_read_value - Returns the value of one element inside a structure + * @root: pointer to a structure + * @name: the name of the element inside a structure that you want to read. + * @value: vector that will contain the element's content. + * VALUE must be a pointer to memory cells already allocated. + * @len: number of bytes of *value: value[0]..value[len-1]. Initialy holds the sizeof value. + * + * Description: + * + * Returns the value of one element inside a structure. + * + * Returns: + * + * ASN1_SUCCESS\: set value OK + * + * ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element. + * + * ASN1_VALUE_NOT_FOUND\: there isn't any value for the element selected. + * + * Examples: + * a description for each type + * + *\begin{itemize} + * \item INTEGER\: VALUE will contain a two's complement form integer. + * integer=-1 -> value[0]=0xFF , len=1 + * integer=1 -> value[0]=0x01 , len=1 + * + * \item ENUMERATED\: as INTEGER (but only with not negative numbers) + * + * \item BOOLEAN\: VALUE will be the null terminated string "TRUE" or "FALSE" and LEN=5 or LEN=6 + * + * \item OBJECT IDENTIFIER\: VALUE will be a null terminated string with each number separated by + * a blank (i.e. "1 2 3 543 1"). + * LEN = strlen(VALUE)+1 + * + * \item UTCTime\: VALUE will be a null terminated string in one of these formats\: + * "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'" + * LEN=strlen(VALUE)+1 + * + * \item GeneralizedTime\: VALUE will be a null terminated string in the same format used to set + * the value + * + * \item OCTET STRING\: VALUE will contain the octet string and LEN will be the number of octet. + * + * \item BIT STRING\: VALUE will contain the bit string organized by bytes and LEN will be the + * number of bits. + * + * \item CHOICE\: if NAME indicates a choice type, VALUE will specify the alternative selected + * + * \item ANY\: if NAME indicates an any type, VALUE will indicate the DER encoding of the structure + * actually used. + *\end{itemize} + * + * If an element is OPTIONAL and the function "read_value" returns ASN1_ELEMENT_NOT_FOUND, it + * means that this element wasn't present in the der encoding that created the structure. + * The first element of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and so on. + * + **/ +asn1_retCode +asn1_read_value(node_asn *root,char *name,unsigned char *value, int *len) +{ + node_asn *node,*p; + int len2,len3; + int value_size = *len; + + node=_asn1_find_node(root,name); + if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + + if((type_field(node->type)!=TYPE_NULL) && + (type_field(node->type)!=TYPE_CHOICE) && + !(node->type&CONST_DEFAULT) && !(node->type&CONST_ASSIGN) && + (node->value==NULL)) + return ASN1_VALUE_NOT_FOUND; + + switch(type_field(node->type)){ + case TYPE_NULL: + PUT_STR_VALUE( value, value_size, "NULL"); + break; + case TYPE_BOOLEAN: + if((node->type&CONST_DEFAULT) && (node->value==NULL)){ + p=node->down; + while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; + if(p->type&CONST_TRUE) { + PUT_STR_VALUE( value, value_size, "TRUE"); + } else { + PUT_STR_VALUE(value, value_size, "FALSE"); + } + } + else if(node->value[0]=='T') { + PUT_STR_VALUE(value, value_size, "TRUE"); + } + else { + PUT_STR_VALUE(value, value_size, "FALSE"); + } + break; + case TYPE_INTEGER: case TYPE_ENUMERATED: + if((node->type&CONST_DEFAULT) && (node->value==NULL)){ + p=node->down; + while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; + if (_asn1_convert_integer(p->value,value,value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR; + } + else{ + len2=-1; + if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR; + } + break; + case TYPE_OBJECT_ID: + if(node->type&CONST_ASSIGN){ + _asn1_str_cpy(value, *len, ""); + p=node->down; + while(p){ + if(type_field(p->type)==TYPE_CONSTANT){ + ADD_STR_VALUE( value, value_size, p->value); + if(p->right) { + ADD_STR_VALUE( value, value_size, " "); + } + } + p=p->right; + } + } else { + PUT_STR_VALUE(value, value_size, node->value); + } + break; + case TYPE_TIME: + PUT_STR_VALUE( value, value_size, node->value); + break; + case TYPE_OCTET_STRING: + len2=-1; + if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR; + break; + case TYPE_BIT_STRING: + len2=-1; + if (_asn1_get_bit_der(node->value,&len2,value,value_size,len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR; + break; + case TYPE_CHOICE: + PUT_STR_VALUE( value, value_size, node->down->name); + break; + case TYPE_ANY: + len3=-1; + len2=_asn1_get_length_der(node->value,&len3); + PUT_VALUE( value, value_size, node->value+len3, len2); + break; + default: + return ASN1_ELEMENT_NOT_FOUND; + break; + } + return ASN1_SUCCESS; +} diff --git a/lib/element.h b/lib/element.h new file mode 100644 index 0000000..9fff601 --- /dev/null +++ b/lib/element.h @@ -0,0 +1,13 @@ + +#ifndef _ELEMENT_H +#define _ELEMENT_H + + +asn1_retCode _asn1_append_sequence_set(node_asn *node); + +asn1_retCode _asn1_convert_integer(char *value,unsigned char *value_out, + int value_out_size, int *len); + +void _asn1_hierarchical_name(node_asn *node,char *name,int name_size); + +#endif diff --git a/lib/errors.c b/lib/errors.c new file mode 100644 index 0000000..1008171 --- /dev/null +++ b/lib/errors.c @@ -0,0 +1,144 @@ +/* Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include "errors.h" +#ifdef STDC_HEADERS +# include +#endif + + +#define LIBASN1_ERROR_ENTRY(name) \ + { #name, name } + +struct libasn1_error_entry { + char *name; + int number; +}; +typedef struct libasn1_error_entry libasn1_error_entry; + +static libasn1_error_entry error_algorithms[] = { + LIBASN1_ERROR_ENTRY( ASN1_SUCCESS ), + LIBASN1_ERROR_ENTRY( ASN1_FILE_NOT_FOUND ), + LIBASN1_ERROR_ENTRY( ASN1_ELEMENT_NOT_FOUND ), + LIBASN1_ERROR_ENTRY( ASN1_IDENTIFIER_NOT_FOUND ), + LIBASN1_ERROR_ENTRY( ASN1_DER_ERROR ), + LIBASN1_ERROR_ENTRY( ASN1_VALUE_NOT_FOUND ), + LIBASN1_ERROR_ENTRY( ASN1_GENERIC_ERROR ), + LIBASN1_ERROR_ENTRY( ASN1_VALUE_NOT_VALID ), + LIBASN1_ERROR_ENTRY( ASN1_TAG_ERROR ), + LIBASN1_ERROR_ENTRY( ASN1_TAG_IMPLICIT ), + LIBASN1_ERROR_ENTRY( ASN1_ERROR_TYPE_ANY ), + LIBASN1_ERROR_ENTRY( ASN1_SYNTAX_ERROR ), + LIBASN1_ERROR_ENTRY( ASN1_MEM_ERROR ), + LIBASN1_ERROR_ENTRY( ASN1_DER_OVERFLOW ), + LIBASN1_ERROR_ENTRY( ASN1_NAME_TOO_LONG ), + LIBASN1_ERROR_ENTRY( ASN1_ARRAY_ERROR ), + LIBASN1_ERROR_ENTRY( ASN1_ELEMENT_NOT_EMPTY ), + {0} +}; + +#define LIBASN1_ERROR_LOOP(b) \ + libasn1_error_entry *p; \ + for(p = error_algorithms; p->name != NULL; p++) { b ; } + +#define LIBASN1_ERROR_ALG_LOOP(a) \ + LIBASN1_ERROR_LOOP( if(p->number == error) { a; break; } ) + + + +/** + * libasn1_perror - prints a string to stderr with a description of an error + * @error: is an error returned by a libasn1 function. + * + * This function is like perror(). The only difference is that it accepts an + * error returned by a libasn1 function. + **/ +void libasn1_perror(asn1_retCode error) +{ + char *ret = NULL; + + /* avoid prefix */ + LIBASN1_ERROR_ALG_LOOP(ret = + _asn1_strdup(p->name + sizeof("ASN1_") - 1)); + + _libasn1_log( "LIBASN1 ERROR: %s\n", ret); + + _asn1_free( ret); +} + + +/** + * libasn1_strerror - Returns a string with a description of an error + * @error: is an error returned by a libasn1 function. + * + * This function is similar to strerror(). The only difference is that it + * accepts an error (number) returned by a libasn1 function. + **/ +const char* libasn1_strerror(asn1_retCode error) +{ + char *ret = NULL; + + /* avoid prefix */ + LIBASN1_ERROR_ALG_LOOP(ret = + p->name + sizeof("ASN1_") - 1); + + return ret; +} + +/* this function will output a message. + */ +#ifdef DEBUG +void _libasn1_log( const char *fmt, ...) { + va_list args; + char str[MAX_LOG_SIZE]; + + va_start(args,fmt); + vsprintf( str,fmt,args); /* Flawfinder: ignore */ + va_end(args); + + fprintf(stderr, str); + + return; +} +#endif + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/errors.h b/lib/errors.h new file mode 100644 index 0000000..1e09211 --- /dev/null +++ b/lib/errors.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef ERRORS_H +#define ERRORS_H + + +#include "int.h" +#include "errors_int.h" + +#ifdef DEBUG +# ifdef __FILE__ +# ifdef __LINE__ +# define _libasn1_assert() fprintf(stderr, "LIBASN1_ASSERT: %s:%d\n", __FILE__,__LINE__); +# else +# define _libasn1_assert() +# endif +# else /* __FILE__ defined */ +# define _libasn1_assert() +# endif +#else /* no debug */ +# define _libasn1_assert() +#endif + +const char* libasn1_strerror(int error); +void libasn1_perror(int error); + +#ifdef DEBUG + void _libasn1_log( const char *fmt, ...); +#else +# define _libasn1_log ( ...) +#endif + +#endif /* ERRORS_H */ + + + + + + diff --git a/lib/errors_int.h b/lib/errors_int.h new file mode 100644 index 0000000..351dd26 --- /dev/null +++ b/lib/errors_int.h @@ -0,0 +1,23 @@ +/* libasn1 error codes. The mapping to a TLS alert is also shown in + * comments. + */ + +#define ASN1_SUCCESS 0 +#define ASN1_FILE_NOT_FOUND 1 +#define ASN1_ELEMENT_NOT_FOUND 2 +#define ASN1_IDENTIFIER_NOT_FOUND 3 +#define ASN1_DER_ERROR 4 +#define ASN1_VALUE_NOT_FOUND 5 +#define ASN1_GENERIC_ERROR 6 +#define ASN1_VALUE_NOT_VALID 7 +#define ASN1_TAG_ERROR 8 +#define ASN1_TAG_IMPLICIT 9 +#define ASN1_ERROR_TYPE_ANY 10 +#define ASN1_SYNTAX_ERROR 11 +#define ASN1_MEM_ERROR 12 +#define ASN1_DER_OVERFLOW 13 +#define ASN1_NAME_TOO_LONG 14 +#define ASN1_ARRAY_ERROR 15 +#define ASN1_ELEMENT_NOT_EMPTY 16 + + diff --git a/lib/int.h b/lib/int.h new file mode 100644 index 0000000..d2c5598 --- /dev/null +++ b/lib/int.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#ifndef INT_H + +#define INT_H + +#include + + +#define DEBUG +/* +#define DEBUG_PARSER +#define DEBUG_INTEGER +*/ + + +#define MAX32 4294967295 +#define MAX24 16777215 +#define MAX16 65535 + +#define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */ +#define MAX_NAME_SIZE 128 /* maximum number of characters of a name inside an ASN1 file definitons */ +#define MAX_ERROR_DESCRIPTION_SIZE 1024 /* maximum number of characters of a description message */ + + +/* define used for visiting trees */ +#define UP 1 +#define RIGHT 2 +#define DOWN 3 + + +typedef int asn1_retCode; /* type returned by libasn1 functions */ + + +/******************************************************/ +/* Structure definition used for the node of the tree */ +/* that rappresent an ASN.1 DEFINITION. */ +/******************************************************/ +typedef struct node_asn_struct{ + char *name; /* Node name */ + unsigned int type; /* Node type */ + unsigned char *value; /* Node value */ + struct node_asn_struct *down; /* Pointer to the son node */ + struct node_asn_struct *right; /* Pointer to the brother node */ + struct node_asn_struct *left; /* Pointer to the next list element */ +} node_asn; + +typedef node_asn* ASN1_TYPE; + +#define ASN1_TYPE_EMPTY NULL + +struct static_struct_asn{ + char *name; /* Node name */ + unsigned int type; /* Node type */ + unsigned char *value; /* Node value */ +}; + +typedef struct static_struct_asn ASN1_ARRAY_TYPE; + + +/****************************************/ +/* Returns the first 8 bits. */ +/* Used with the field type of node_asn */ +/****************************************/ +#define type_field(x) (x&0xFF) + + +/* List of constants for field type of typedef node_asn */ +#define TYPE_CONSTANT 1 +#define TYPE_IDENTIFIER 2 +#define TYPE_INTEGER 3 +#define TYPE_BOOLEAN 4 +#define TYPE_SEQUENCE 5 +#define TYPE_BIT_STRING 6 +#define TYPE_OCTET_STRING 7 +#define TYPE_TAG 8 +#define TYPE_DEFAULT 9 +#define TYPE_SIZE 10 +#define TYPE_SEQUENCE_OF 11 +#define TYPE_OBJECT_ID 12 +#define TYPE_ANY 13 +#define TYPE_SET 14 +#define TYPE_SET_OF 15 +#define TYPE_DEFINITIONS 16 +#define TYPE_TIME 17 +#define TYPE_CHOICE 18 +#define TYPE_IMPORTS 19 +#define TYPE_NULL 20 +#define TYPE_ENUMERATED 21 + + +/***********************************************************************/ +/* List of constants for specify better the type of typedef node_asn. */ +/***********************************************************************/ +/* Used with TYPE_TAG */ +#define CONST_UNIVERSAL (1<<8) +#define CONST_PRIVATE (1<<9) +#define CONST_APPLICATION (1<<10) +#define CONST_EXPLICIT (1<<11) +#define CONST_IMPLICIT (1<<12) + +#define CONST_TAG (1<<13) /* Used in ASN.1 assignement */ +#define CONST_OPTION (1<<14) +#define CONST_DEFAULT (1<<15) +#define CONST_TRUE (1<<16) +#define CONST_FALSE (1<<17) + +#define CONST_LIST (1<<18) /* Used with TYPE_INTEGER and TYPE_BIT_STRING */ +#define CONST_MIN_MAX (1<<19) + +#define CONST_1_PARAM (1<<20) + +#define CONST_SIZE (1<<21) + +#define CONST_DEFINED_BY (1<<22) + +#define CONST_GENERALIZED (1<<23) +#define CONST_UTC (1<<24) + +// #define CONST_IMPORTS (1<<25) + +#define CONST_NOT_USED (1<<26) +#define CONST_SET (1<<27) +#define CONST_ASSIGN (1<<28) + +#define CONST_DOWN (1<<29) +#define CONST_RIGHT (1<<30) + + +/* functions */ +asn1_retCode asn1_delete_structure(ASN1_TYPE *structure); + +#endif /* INT_H */ + + + + + + + + + + + + + + + diff --git a/lib/parser_aux.c b/lib/parser_aux.c new file mode 100644 index 0000000..8f99bc4 --- /dev/null +++ b/lib/parser_aux.c @@ -0,0 +1,758 @@ +/* + * Copyright (C) 2000,2001 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#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;ktype)==TYPE_INTEGER) && (p->type&CONST_ASSIGN)){ + if(p->value){ + _asn1_convert_integer(p->value,val,sizeof(val), &len); + _asn1_octet_der(val,len,val2,&len); + _asn1_set_value(p,val2,len); + } + } + + if(p->down){ + p=p->down; + } + else{ + if(p==node) p=NULL; + else if(p->right) p=p->right; + else{ + while(1){ + p=_asn1_find_up(p); + if(p==node){ + p=NULL; + break; + } + if(p->right){ + p=p->right; + break; + } + } + } + } + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_expand_object_id */ +/* Description: expand the IDs of an OBJECT IDENTIFIER constant. */ +/* Parameters: */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +asn1_retCode +_asn1_expand_object_id(ASN1_TYPE node) +{ + node_asn *p,*p2,*p3,*p4,*p5; + char name_root[129],name2[129]; + int move; + + if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + + _asn1_str_cpy(name_root, sizeof(name_root), node->name); + + p=node; + move=DOWN; + + while(!((p==node) && (move==UP))){ + if(move!=UP){ + if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){ + p2=p->down; + if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){ + if(p2->value && !isdigit(p2->value[0])){ + _asn1_str_cpy(name2, sizeof(name2), name_root); + _asn1_str_cat(name2, sizeof(name2), "."); + _asn1_str_cat(name2, sizeof(name2), p2->value); + p3=_asn1_find_node(node,name2); + if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) || + !(p3->type&CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND; + _asn1_set_down(p,p2->right); + _asn1_remove_node(p2); + p2=p; + p4=p3->down; + while(p4){ + if(type_field(p4->type)==TYPE_CONSTANT){ + p5=_asn1_add_node_only(TYPE_CONSTANT); + _asn1_set_name(p5,p4->name); + _asn1_set_value(p5,p4->value,strlen(p4->value)+1); + if(p2==p){ + _asn1_set_right(p5,p->down); + _asn1_set_down(p,p5); + } + else{ + _asn1_set_right(p5,p2->right); + _asn1_set_right(p2,p5); + } + p2=p5; + } + p4=p4->right; + } + move=DOWN; + continue; + } + } + } + move=DOWN; + } + else move=RIGHT; + + if(move==DOWN){ + if(p->down) p=p->down; + else move=RIGHT; + } + + if(p==node) {move=UP; continue;} + + if(move==RIGHT){ + if(p->right) p=p->right; + else move=UP; + } + if(move==UP) p=_asn1_find_up(p); + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_type_set_config */ +/* Description: sets the CONST_SET and CONST_NOT_USED properties */ +/* in the fields of the SET elements. */ +/* Parameters: */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +asn1_retCode +_asn1_type_set_config(ASN1_TYPE node) +{ + node_asn *p,*p2; + int move; + + if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + + p=node; + move=DOWN; + + while(!((p==node) && (move==UP))){ + if(move!=UP){ + if(type_field(p->type)==TYPE_SET){ + p2=p->down; + while(p2){ + if(type_field(p2->type)!=TYPE_TAG) + p2->type|=CONST_SET|CONST_NOT_USED; + p2=p2->right; + } + } + move=DOWN; + } + else move=RIGHT; + + if(move==DOWN){ + if(p->down) p=p->down; + else move=RIGHT; + } + + if(p==node) {move=UP; continue;} + + if(move==RIGHT){ + if(p->right) p=p->right; + else move=UP; + } + if(move==UP) p=_asn1_find_up(p); + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_check_identifier */ +/* Description: checks the definitions of all the identifiers */ +/* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */ +/* The identifierMissing global variable is filled if necessary.*/ +/* Parameters: */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +asn1_retCode +_asn1_check_identifier(ASN1_TYPE node) +{ + node_asn *p,*p2; + char name2[MAX_NAME_SIZE*2+2]; + + if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + + p=node; + while(p){ + if(type_field(p->type)==TYPE_IDENTIFIER){ + _asn1_str_cpy(name2, sizeof(name2), node->name); + _asn1_str_cat(name2, sizeof(name2), "."); + _asn1_str_cat(name2, sizeof(name2), p->value); + p2=_asn1_find_node(node,name2); + if(p2==NULL){ + strcpy(identifierMissing,p->value); + return ASN1_IDENTIFIER_NOT_FOUND; + } + } + else if((type_field(p->type)==TYPE_OBJECT_ID) && + (p->type&CONST_ASSIGN)){ + p2=p->down; + if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){ + if(p2->value && !isdigit(p2->value[0])){ + _asn1_str_cpy(name2, sizeof(name2), node->name); + _asn1_str_cat(name2, sizeof(name2), "."); + _asn1_str_cat(name2, sizeof(name2), p2->value); + strcpy(identifierMissing,p2->value); + p2=_asn1_find_node(node,name2); + if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) || + !(p2->type&CONST_ASSIGN)) + return ASN1_IDENTIFIER_NOT_FOUND; + else + identifierMissing[0]=0; + } + } + } + + if(p->down){ + p=p->down; + } + else if(p->right) p=p->right; + else{ + while(1){ + p=_asn1_find_up(p); + if(p==node){ + p=NULL; + break; + } + if(p->right){ + p=p->right; + break; + } + } + } + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_set_default_tag */ +/* Description: sets the default IMPLICIT or EXPLICIT property in */ +/* the tagged elements that don't have this declaration. */ +/* Parameters: */ +/* node: pointer to a DEFINITIONS element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */ +/* a DEFINITIONS element, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +asn1_retCode +_asn1_set_default_tag(ASN1_TYPE node) +{ + node_asn *p; + + if((node==NULL) || (type_field(node->type)!=TYPE_DEFINITIONS)) + return ASN1_ELEMENT_NOT_FOUND; + + p=node; + while(p){ + if((type_field(p->type)==TYPE_TAG) && + !(p->type&CONST_EXPLICIT) && + !(p->type&CONST_IMPLICIT)){ + if(node->type&CONST_EXPLICIT) p->type|=CONST_EXPLICIT; + else p->type|=CONST_IMPLICIT; + } + + if(p->down){ + p=p->down; + } + else if(p->right) p=p->right; + else{ + while(1){ + p=_asn1_find_up(p); + if(p==node){ + p=NULL; + break; + } + if(p->right){ + p=p->right; + break; + } + } + } + } + + return ASN1_SUCCESS; +} + + + + diff --git a/lib/parser_aux.h b/lib/parser_aux.h new file mode 100644 index 0000000..937df66 --- /dev/null +++ b/lib/parser_aux.h @@ -0,0 +1,65 @@ + +#ifndef _PARSER_AUX_H +#define _PARSER_AUX_H + + +/***************************************/ +/* Functions used by ASN.1 parser */ +/***************************************/ +node_asn * +_asn1_add_node(unsigned int type); + +node_asn * +_asn1_set_value(node_asn *node,unsigned char *value,unsigned int len); + +node_asn * +_asn1_set_name(node_asn *node,char *name); + +node_asn * +_asn1_set_right(node_asn *node,node_asn *right); + +node_asn * +_asn1_get_right(node_asn *node); + +node_asn * +_asn1_get_last_right(node_asn *node); + +node_asn * +_asn1_set_down(node_asn *node,node_asn *down); + +char * +_asn1_get_name(node_asn *node); + +node_asn * +_asn1_get_down(node_asn *node); + +node_asn * +_asn1_mod_type(node_asn *node,unsigned int value); + +void +_asn1_remove_node(node_asn *node); + +void _asn1_delete_list(void); + +void _asn1_delete_list_and_nodes(void); + +char * _asn1_ltostr(long v,char *str); + +node_asn * _asn1_find_up(node_asn *node); + +node_asn * _asn1_find_node(node_asn *pointer,char *name); + +asn1_retCode _asn1_change_integer_value(ASN1_TYPE node); + +asn1_retCode _asn1_expand_object_id(ASN1_TYPE node); + +asn1_retCode _asn1_type_set_config(ASN1_TYPE node); + +asn1_retCode _asn1_check_identifier(ASN1_TYPE node); + +asn1_retCode _asn1_set_default_tag(ASN1_TYPE node); + +#endif + + + diff --git a/lib/structure.c b/lib/structure.c new file mode 100644 index 0000000..1467f44 --- /dev/null +++ b/lib/structure.c @@ -0,0 +1,855 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/*****************************************************/ +/* File: structure.c */ +/* Description: Functions to create and delete an */ +/* ASN1 tree. */ +/*****************************************************/ + + +#include +#include +#include +#include "parser_aux.h" +#include "der.h" +#include + + +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;kname) 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;kname) 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;kvalue)[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;kvalue)[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;kvalue)[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;kvalue)[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;kvalue)[k+len3]); + } + break; + case TYPE_SET: + case TYPE_SET_OF: + case TYPE_CHOICE: + case TYPE_DEFINITIONS: + case TYPE_SEQUENCE_OF: + case TYPE_SEQUENCE: + case TYPE_NULL: + break; + default: + break; + } + } + + if(mode==ASN1_PRINT_ALL){ + if(p->type&0x1FFFFF00){ + fprintf(out," attr:"); + if(p->type & CONST_UNIVERSAL) fprintf(out,"UNIVERSAL,"); + if(p->type & CONST_PRIVATE) fprintf(out,"PRIVATE,"); + if(p->type & CONST_APPLICATION) fprintf(out,"APPLICATION,"); + if(p->type & CONST_EXPLICIT) fprintf(out,"EXPLICIT,"); + if(p->type & CONST_IMPLICIT) fprintf(out,"IMPLICIT,"); + if(p->type & CONST_TAG) fprintf(out,"TAG,"); + if(p->type & CONST_DEFAULT) fprintf(out,"DEFAULT,"); + if(p->type & CONST_TRUE) fprintf(out,"TRUE,"); + if(p->type & CONST_FALSE) fprintf(out,"FALSE,"); + if(p->type & CONST_LIST) fprintf(out,"LIST,"); + if(p->type & CONST_MIN_MAX) fprintf(out,"MIN_MAX,"); + if(p->type & CONST_OPTION) fprintf(out,"OPTION,"); + if(p->type & CONST_1_PARAM) fprintf(out,"1_PARAM,"); + if(p->type & CONST_SIZE) fprintf(out,"SIZE,"); + if(p->type & CONST_DEFINED_BY) fprintf(out,"DEF_BY,"); + if(p->type & CONST_GENERALIZED) fprintf(out,"GENERALIZED,"); + if(p->type & CONST_UTC) fprintf(out,"UTC,"); + if(p->type & CONST_SET) fprintf(out,"SET,"); + if(p->type & CONST_NOT_USED) fprintf(out,"NOT_USED,"); + if(p->type & CONST_ASSIGN) fprintf(out,"ASSIGNMENT,"); + } + } + + if(mode == ASN1_PRINT_ALL){ + fprintf(out,"\n"); + } + else{ + switch(type_field(p->type)){ + case TYPE_CONSTANT: + case TYPE_TAG: + case TYPE_SIZE: + break; + default: + fprintf(out,"\n"); + } + } + + if(p->down){ + p=p->down; + indent+=2; + } + else if(p==root){ + p=NULL; + break; + } + else if(p->right) p=p->right; + else{ + while(1){ + p=_asn1_find_up(p); + if(p==root){ + p=NULL; + break; + } + indent-=2; + if(p->right){ + p=p->right; + break; + } + } + } + } +} + + + +/** + * asn1_number_of_elements - Counts the number of elements of a structure. + * @element: pointer to the root of an ASN1 structure. + * @name: the name of a sub-structure of ROOT. + * @num: pointer to an integer where the result will be stored + * Description: + * + * Counts the number of elements of a sub-structure called NAME with names equal to "?1","?2", ... + * + * Returns: + * + * ASN1_SUCCESS: creation OK + * ASN1_ELEMENT_NOT_FOUND: NAME isn't known + * ASN1_GENERIC_ERROR: pointer num equal to NULL + * + **/ +asn1_retCode +asn1_number_of_elements(ASN1_TYPE element,char *name,int *num) +{ + node_asn *node,*p; + + if(num==NULL) return ASN1_GENERIC_ERROR; + + *num=0; + + node=_asn1_find_node(element,name); + if(node==NULL) return ASN1_ELEMENT_NOT_FOUND; + + p=node->down; + + while(p){ + if((p->name) && (p->name[0]=='?')) (*num)++; + p=p->right; + } + + return ASN1_SUCCESS; +} + + + + + + + + + diff --git a/lib/structure.h b/lib/structure.h new file mode 100644 index 0000000..8309761 --- /dev/null +++ b/lib/structure.h @@ -0,0 +1,33 @@ + +/*************************************************/ +/* File: structure.h */ +/* Description: list of exported object by */ +/* "structure.c" */ +/*************************************************/ + +#ifndef _STRUCTURE_H +#define _STRUCTURE_H + + +/*************************************/ +/* Constants used in asn1_visit_tree */ +/*************************************/ +#define ASN1_PRINT_NAME 1 +#define ASN1_PRINT_NAME_TYPE 2 +#define ASN1_PRINT_NAME_TYPE_VALUE 3 +#define ASN1_PRINT_ALL 4 + + +asn1_retCode _asn1_create_static_structure(node_asn *pointer, + char* output_file_name,char *vector_name); + +node_asn* _asn1_copy_structure3(node_asn *source_node); + +node_asn* _asn1_copy_structure2(node_asn *root,char *source_name); + +node_asn * _asn1_add_node_only(unsigned int type); + +node_asn * _asn1_find_left(node_asn *node); + +#endif + diff --git a/src/asn1Coding.c b/src/asn1Coding.c new file mode 100644 index 0000000..ab92f77 --- /dev/null +++ b/src/asn1Coding.c @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/*****************************************************/ +/* File: asn1Coding.c */ +/* Description: program to generate a DER coding */ +/* of an ASN1 definition. */ +/*****************************************************/ + +#include +#include +#include +#include +#include + +#ifdef HAVE_GETOPT_H + #include +#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] \n" + " file with ASN1 definitions.\n" + " 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 , --output 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 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 +#include +#include +#include +#include + +#ifdef HAVE_GETOPT_H + #include +#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] \n" + " file with ASN1 definitions.\n" + " file with a DER coding.\n" + " ASN1 type name\n" + "\n" +#ifdef HAVE_GETOPT_H + "Operation modes:\n" + " -h, --help shows this message and exit.\n" + " -v, --version shows version information and exit.\n" + " -c, --check checks the syntax only.\n"; +#else + "Operation modes:\n" + " -h shows this message and exit.\n" + " -v shows version information and exit.\n" + " -c checks the syntax only.\n"; +#endif + + + +/********************************************************/ +/* Function : main */ +/* Description: */ +/********************************************************/ +int +main(int argc,char *argv[]) +{ + +#ifdef HAVE_GETOPT_H + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, + {"check", no_argument, 0, 'c'}, + {0, 0, 0, 0} + }; +#endif + + int option_result; + int option_index = 0; + char *inputFileAsnName=NULL; + char *inputFileDerName=NULL; + char *typeName=NULL; + char *varName=NULL; + int checkSyntaxOnly=0; + ASN1_TYPE definitions=ASN1_TYPE_EMPTY; + ASN1_TYPE structure=ASN1_TYPE_EMPTY; + char errorDescription[MAX_ERROR_DESCRIPTION_SIZE]; + int asn1_result=ASN1_SUCCESS; + FILE *inputFile; + unsigned char der[1024]; + int der_len=0; + char *dot_p,*char_p; + + opterr=0; /* disable error messages from getopt */ + + printf("\n"); + + while(1){ + +#ifdef HAVE_GETOPT_H + option_result=getopt_long(argc,argv,"hvc",long_options,&option_index); +#else + option_result=getopt(argc,argv,"hvc"); +#endif + + if(option_result == -1) break; + + switch(option_result){ + case 'h': /* HELP */ + printf("%s\n",help_man); + exit(0); + break; + case 'v': /* VERSION */ + printf("%s\n",version_man); + exit(0); + break; + case 'c': /* CHECK SYNTAX */ + checkSyntaxOnly = 1; + break; + case '?': /* UNKNOW OPTION */ + fprintf(stderr,"asn1Decoding: option '%s' not recognized or without argument.\n\n",argv[optind-1]); + printf("%s\n",help_man); + + exit(1); + break; + default: + fprintf(stderr,"asn1Decoding: ?? getopt returned character code Ox%x ??\n",option_result); + } + } + + if(optind == argc){ + fprintf(stderr,"asn1Decoding: input file with ASN1 definitions missing.\n"); + fprintf(stderr," input file with DER coding missing.\n"); + fprintf(stderr," ASN1 type name missing.\n\n"); + printf("%s\n",help_man); + + exit(1); + } + + if(optind == argc-1){ + fprintf(stderr,"asn1Decoding: input file with DER coding missing.\n\n"); + fprintf(stderr," ASN1 type name missing.\n\n"); + printf("%s\n",help_man); + + exit(1); + } + + if(optind == argc-2){ + fprintf(stderr,"asn1Decoding: ASN1 type name missing.\n\n"); + printf("%s\n",help_man); + + exit(1); + } + + inputFileAsnName=(char *)malloc(strlen(argv[optind])+1); + strcpy(inputFileAsnName,argv[optind]); + + inputFileDerName=(char *)malloc(strlen(argv[optind+1])+1); + strcpy(inputFileDerName,argv[optind+1]); + + typeName=(char *)malloc(strlen(argv[optind+2])+1); + strcpy(typeName,argv[optind+2]); + + asn1_result=asn1_parser2tree(inputFileAsnName,&definitions,errorDescription); + + switch(asn1_result){ + case ASN1_SUCCESS: + printf("Parse: done.\n"); + break; + case ASN1_FILE_NOT_FOUND: + printf("asn1Decoding: FILE %s NOT FOUND\n",inputFileAsnName); + break; + case ASN1_SYNTAX_ERROR: + case ASN1_IDENTIFIER_NOT_FOUND: + case ASN1_NAME_TOO_LONG: + printf("asn1Decoding: %s\n",errorDescription); + break; + default: + printf("libasn1 ERROR: %s\n",libasn1_strerror(asn1_result)); + } + + if(asn1_result != ASN1_SUCCESS){ + free(inputFileAsnName); + free(inputFileDerName); + free(typeName); + exit(1); + } + + + inputFile=fopen(inputFileDerName,"r"); + + if(inputFile==NULL){ + printf("asn1Decoding: file '%s' not found\n",inputFileDerName); + asn1_delete_structure(&definitions); + + free(inputFileAsnName); + free(inputFileDerName); + free(typeName); + exit(1); + } + + while(fscanf(inputFile,"%c",der+der_len) != EOF) + der_len++; + + fclose(inputFile); + + /* varName creation */ + dot_p=typeName; + char_p=typeName; + while((char_p=strchr(char_p,'.'))){ + char_p++; + dot_p=char_p; + } + + /* varName= inputFileName after the last '.' */ + varName=(char *)malloc(strlen(typeName)-(dot_p-typeName)+1); + strcpy(varName,dot_p); + + asn1_result=asn1_create_element(definitions,typeName,&structure,varName); + if(asn1_result != ASN1_SUCCESS){ + printf("Structure creation: %s\n",libasn1_strerror(asn1_result)); + asn1_delete_structure(&definitions); + + free(inputFileAsnName); + free(inputFileDerName); + free(typeName); + free(varName); + exit(1); + } + + asn1_result=asn1_der_decoding(&structure,der,der_len,errorDescription); + printf("\nDecoding: %s\n",libasn1_strerror(asn1_result)); + if(asn1_result != ASN1_SUCCESS) + printf("asn1Decoding: %s\n",errorDescription); + + printf("\nDECODING RESULT:\n"); + asn1_print_structure(stdout,structure,varName,ASN1_PRINT_NAME_TYPE_VALUE); + + + asn1_delete_structure(&definitions); + asn1_delete_structure(&structure); + + free(inputFileAsnName); + free(inputFileDerName); + free(typeName); + free(varName); + + if(asn1_result != ASN1_SUCCESS) + exit(1); + + exit(0); +} + + + + + diff --git a/src/asn1Parser.c b/src/asn1Parser.c new file mode 100644 index 0000000..0cbb399 --- /dev/null +++ b/src/asn1Parser.c @@ -0,0 +1,207 @@ +/* + * 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: asn1Parser.c */ +/* Description: program to parse a file with ASN1 */ +/* definitions. */ +/*****************************************************/ + +#include +#include +#include +#include +#include + +#ifdef HAVE_GETOPT_H + #include +#endif + +char version_man[] = "asn1Parser (GNU libasn1) " VERSION; + +char help_man[] = "asn1Parser reads files with ASN1 definitions and\n" + "generates a C array to use with libasn1 functions.\n" + "\n" + "Usage: asn1Parser [options] file\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 , --output output file\n" + " -n , --name array name\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 output file\n" + " -n array name\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'}, + {"output", required_argument, 0, 'o'}, + {"name", required_argument, 0, 'n'}, + {0, 0, 0, 0} + }; +#endif + + int option_result; + int option_index = 0; + char *outputFileName=NULL; + char *inputFileName=NULL; + char *vectorName=NULL; + int checkSyntaxOnly=0; + ASN1_TYPE pointer=ASN1_TYPE_EMPTY; + char errorDescription[MAX_ERROR_DESCRIPTION_SIZE]; + int parse_result=ASN1_SUCCESS; + + opterr=0; /* disable error messages from getopt */ + + printf("\n"); + + while(1){ + +#ifdef HAVE_GETOPT_H + option_result=getopt_long(argc,argv,"hvco:n:",long_options,&option_index); +#else + option_result=getopt(argc,argv,"hvco:n:"); +#endif + + if(option_result == -1) break; + + switch(option_result){ + case 0: +#ifdef HAVE_GETOPT_H + printf("option %s",long_options[option_index].name); + if(optarg) printf(" with arg %s",optarg); + printf("\n"); +#endif + break; + case 'h': /* HELP */ + printf("%s\n",help_man); + + if(outputFileName) free(outputFileName); + if(vectorName) free(vectorName); + exit(0); + break; + case 'v': /* VERSION */ + printf("%s\n",version_man); + + if(outputFileName) free(outputFileName); + if(vectorName) free(vectorName); + exit(0); + break; + case 'c': /* CHECK SYNTAX */ + checkSyntaxOnly = 1; + break; + case 'o': /* OUTPUT */ + outputFileName=(char *)malloc(strlen(optarg)+1); + strcpy(outputFileName,optarg); + break; + case 'n': /* VECTOR NAME */ + vectorName=(char *)malloc(strlen(optarg)+1); + strcpy(vectorName,optarg); + break; + case '?': /* UNKNOW OPTION */ + fprintf(stderr,"asn1Parser: option '%s' not recognized or without argument.\n\n",argv[optind-1]); + printf("%s\n",help_man); + + if(outputFileName) free(outputFileName); + if(vectorName) free(vectorName); + exit(1); + break; + default: + fprintf(stderr,"asn1Parser: ?? getopt returned character code Ox%x ??\n",option_result); + } + + } + + if(optind == argc){ + fprintf(stderr,"asn1Parser: input file name missing.\n\n"); + printf("%s\n",help_man); + + if(outputFileName) free(outputFileName); + if(vectorName) free(vectorName); + exit(1); + } + else{ + inputFileName=(char *)malloc(strlen(argv[optind])+1); + strcpy(inputFileName,argv[optind]); + } + + if(checkSyntaxOnly == 1){ + parse_result=asn1_parser2tree(inputFileName,&pointer,errorDescription); + asn1_delete_structure(&pointer); + } + else /* C VECTOR CREATION */ + parse_result=asn1_parser2array(inputFileName, + outputFileName,vectorName,errorDescription); + + switch(parse_result){ + case ASN1_SUCCESS: + printf("Done.\n"); + break; + case ASN1_FILE_NOT_FOUND: + printf("asn1Parser: FILE %s NOT FOUND\n",inputFileName); + break; + case ASN1_SYNTAX_ERROR: + case ASN1_IDENTIFIER_NOT_FOUND: + case ASN1_NAME_TOO_LONG: + printf("asn1Parser: %s\n",errorDescription); + break; + default: + printf("libasn1 ERROR: %s\n",libasn1_strerror(parse_result)); + } + + + free(inputFileName); + if(outputFileName) free(outputFileName); + if(vectorName) free(vectorName); + + if(parse_result != ASN1_SUCCESS) exit(1); + exit(0); +} + + + + + + + diff --git a/src/pkix_asn1_tab.c b/src/pkix_asn1_tab.c new file mode 100644 index 0000000..eb88626 --- /dev/null +++ b/src/pkix_asn1_tab.c @@ -0,0 +1,874 @@ + +#include "libasn1.h" + +const ASN1_ARRAY_TYPE pkix_asn1_tab[]={ + {"PKIX1Implicit88",536875024,0}, + {0,1610612748,0}, + {"iso",1073741825,"1"}, + {"identified-organization",1073741825,"3"}, + {"dod",1073741825,"6"}, + {"internet",1073741825,"1"}, + {"security",1073741825,"5"}, + {"mechanisms",1073741825,"5"}, + {"pkix",1073741825,"7"}, + {"id-mod",1073741825,"0"}, + {"id-pkix1-implicit-88",1,"2"}, + {"id-ce",1879048204,0}, + {"joint-iso-ccitt",1073741825,"2"}, + {"ds",1073741825,"5"}, + {0,1,"29"}, + {"id-ce-authorityKeyIdentifier",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"35"}, + {"AuthorityKeyIdentifier",1610612741,0}, + {"keyIdentifier",1610637314,"KeyIdentifier"}, + {0,4104,"0"}, + {"authorityCertIssuer",1610637314,"GeneralNames"}, + {0,4104,"1"}, + {"authorityCertSerialNumber",536895490,"CertificateSerialNumber"}, + {0,4104,"2"}, + {"KeyIdentifier",1073741831,0}, + {"id-ce-subjectKeyIdentifier",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"14"}, + {"SubjectKeyIdentifier",1073741826,"KeyIdentifier"}, + {"id-ce-keyUsage",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"15"}, + {"KeyUsage",1610874886,0}, + {"digitalSignature",1073741825,"0"}, + {"nonRepudiation",1073741825,"1"}, + {"keyEncipherment",1073741825,"2"}, + {"dataEncipherment",1073741825,"3"}, + {"keyAgreement",1073741825,"4"}, + {"keyCertSign",1073741825,"5"}, + {"cRLSign",1073741825,"6"}, + {"encipherOnly",1073741825,"7"}, + {"decipherOnly",1,"8"}, + {"id-ce-privateKeyUsagePeriod",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"16"}, + {"PrivateKeyUsagePeriod",1610612741,0}, + {"notBefore",1619025937,0}, + {0,4104,"0"}, + {"notAfter",545284113,0}, + {0,4104,"1"}, + {"id-ce-certificatePolicies",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"32"}, + {"CertificatePolicies",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"PolicyInformation"}, + {"PolicyInformation",1610612741,0}, + {"policyIdentifier",1073741826,"CertPolicyId"}, + {"policyQualifiers",538984459,0}, + {"MAX",1074266122,"1"}, + {0,2,"PolicyQualifierInfo"}, + {"CertPolicyId",1073741836,0}, + {"PolicyQualifierInfo",1610612741,0}, + {"policyQualifierId",1073741826,"PolicyQualifierId"}, + {"qualifier",541065229,0}, + {"policyQualifierId",1,0}, + {"PolicyQualifierId",1073741836,0}, + {"CPSuri",1073741826,"IA5String"}, + {"UserNotice",1610612741,0}, + {"noticeRef",1073758210,"NoticeReference"}, + {"explicitText",16386,"DisplayText"}, + {"NoticeReference",1610612741,0}, + {"organization",1073741826,"DisplayText"}, + {"noticeNumbers",536870923,0}, + {0,3,0}, + {"DisplayText",1610612754,0}, + {"visibleString",1612709890,"VisibleString"}, + {"200",524298,"1"}, + {"bmpString",1612709890,"BMPString"}, + {"200",524298,"1"}, + {"utf8String",538968066,"UTF8String"}, + {"200",524298,"1"}, + {"id-ce-policyMappings",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"33"}, + {"PolicyMappings",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,536870917,0}, + {"issuerDomainPolicy",1073741826,"CertPolicyId"}, + {"subjectDomainPolicy",2,"CertPolicyId"}, + {"id-ce-subjectAltName",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"17"}, + {"SubjectAltName",1073741826,"GeneralNames"}, + {"GeneralNames",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"GeneralName"}, + {"GeneralName",1610612754,0}, + {"otherName",1610620930,"AnotherName"}, + {0,4104,"0"}, + {"rfc822Name",1610620930,"IA5String"}, + {0,4104,"1"}, + {"dNSName",1610620930,"IA5String"}, + {0,4104,"2"}, + {"x400Address",1610620930,"ORAddress"}, + {0,4104,"3"}, + {"directoryName",1610620930,"Name"}, + {0,4104,"4"}, + {"ediPartyName",1610620930,"EDIPartyName"}, + {0,4104,"5"}, + {"uniformResourceIdentifier",1610620930,"IA5String"}, + {0,4104,"6"}, + {"iPAddress",1610620935,0}, + {0,4104,"7"}, + {"registeredID",536879116,0}, + {0,4104,"8"}, + {"AnotherName",1610612741,0}, + {"type-id",1073741836,0}, + {"value",541073421,0}, + {0,1073743880,"0"}, + {"type-id",1,0}, + {"EDIPartyName",1610612741,0}, + {"nameAssigner",1610637314,"DirectoryString"}, + {0,4104,"0"}, + {"partyName",536879106,"DirectoryString"}, + {0,4104,"1"}, + {"id-ce-issuerAltName",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"18"}, + {"IssuerAltName",1073741826,"GeneralNames"}, + {"id-ce-subjectDirectoryAttributes",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"9"}, + {"SubjectDirectoryAttributes",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"Attribute"}, + {"id-ce-basicConstraints",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"19"}, + {"BasicConstraints",1610612741,0}, + {"cA",1610645508,0}, + {0,131081,0}, + {"pathLenConstraint",537411587,0}, + {"0",10,"MAX"}, + {"id-ce-nameConstraints",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"30"}, + {"NameConstraints",1610612741,0}, + {"permittedSubtrees",1610637314,"GeneralSubtrees"}, + {0,4104,"0"}, + {"excludedSubtrees",536895490,"GeneralSubtrees"}, + {0,4104,"1"}, + {"GeneralSubtrees",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"GeneralSubtree"}, + {"GeneralSubtree",1610612741,0}, + {"base",1073741826,"GeneralName"}, + {"minimum",1610653698,"BaseDistance"}, + {0,1073741833,"0"}, + {0,4104,"0"}, + {"maximum",536895490,"BaseDistance"}, + {0,4104,"1"}, + {"BaseDistance",1611137027,0}, + {"0",10,"MAX"}, + {"id-ce-policyConstraints",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"36"}, + {"PolicyConstraints",1610612741,0}, + {"requireExplicitPolicy",1610637314,"SkipCerts"}, + {0,4104,"0"}, + {"inhibitPolicyMapping",536895490,"SkipCerts"}, + {0,4104,"1"}, + {"SkipCerts",1611137027,0}, + {"0",10,"MAX"}, + {"id-ce-cRLDistributionPoints",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"31"}, + {"CRLDistPointsSyntax",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"DistributionPoint"}, + {"DistributionPoint",1610612741,0}, + {"distributionPoint",1610637314,"DistributionPointName"}, + {0,4104,"0"}, + {"reasons",1610637314,"ReasonFlags"}, + {0,4104,"1"}, + {"cRLIssuer",536895490,"GeneralNames"}, + {0,4104,"2"}, + {"DistributionPointName",1610612754,0}, + {"fullName",1610620930,"GeneralNames"}, + {0,4104,"0"}, + {"nameRelativeToCRLIssuer",536879106,"RelativeDistinguishedName"}, + {0,4104,"1"}, + {"ReasonFlags",1610874886,0}, + {"unused",1073741825,"0"}, + {"keyCompromise",1073741825,"1"}, + {"cACompromise",1073741825,"2"}, + {"affiliationChanged",1073741825,"3"}, + {"superseded",1073741825,"4"}, + {"cessationOfOperation",1073741825,"5"}, + {"certificateHold",1,"6"}, + {"id-ce-extKeyUsage",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"37"}, + {"ExtKeyUsageSyntax",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"KeyPurposeId"}, + {"KeyPurposeId",1073741836,0}, + {"id-kp-serverAuth",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"1"}, + {"id-kp-clientAuth",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"2"}, + {"id-kp-codeSigning",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"3"}, + {"id-kp-emailProtection",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"4"}, + {"id-kp-ipsecEndSystem",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"5"}, + {"id-kp-ipsecTunnel",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"6"}, + {"id-kp-ipsecUser",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"7"}, + {"id-kp-timeStamping",1879048204,0}, + {0,1073741825,"id-kp"}, + {0,1,"8"}, + {"id-pe-authorityInfoAccess",1879048204,0}, + {0,1073741825,"id-pe"}, + {0,1,"1"}, + {"AuthorityInfoAccessSyntax",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"AccessDescription"}, + {"AccessDescription",1610612741,0}, + {"accessMethod",1073741836,0}, + {"accessLocation",2,"GeneralName"}, + {"id-ce-cRLNumber",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"20"}, + {"CRLNumber",1611137027,0}, + {"0",10,"MAX"}, + {"id-ce-issuingDistributionPoint",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"28"}, + {"IssuingDistributionPoint",1610612741,0}, + {"distributionPoint",1610637314,"DistributionPointName"}, + {0,4104,"0"}, + {"onlyContainsUserCerts",1610653700,0}, + {0,1073872905,0}, + {0,4104,"1"}, + {"onlyContainsCACerts",1610653700,0}, + {0,1073872905,0}, + {0,4104,"2"}, + {"onlySomeReasons",1610637314,"ReasonFlags"}, + {0,4104,"3"}, + {"indirectCRL",536911876,0}, + {0,1073872905,0}, + {0,4104,"4"}, + {"id-ce-deltaCRLIndicator",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"27"}, + {"BaseCRLNumber",1073741826,"CRLNumber"}, + {"id-ce-cRLReasons",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"21"}, + {"CRLReason",1610874901,0}, + {"unspecified",1073741825,"0"}, + {"keyCompromise",1073741825,"1"}, + {"cACompromise",1073741825,"2"}, + {"affiliationChanged",1073741825,"3"}, + {"superseded",1073741825,"4"}, + {"cessationOfOperation",1073741825,"5"}, + {"certificateHold",1073741825,"6"}, + {"removeFromCRL",1,"8"}, + {"id-ce-certificateIssuer",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"29"}, + {"CertificateIssuer",1073741826,"GeneralNames"}, + {"id-ce-holdInstructionCode",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"23"}, + {"HoldInstructionCode",1073741836,0}, + {"holdInstruction",1879048204,0}, + {"joint-iso-itu-t",1073741825,"2"}, + {"member-body",1073741825,"2"}, + {"us",1073741825,"840"}, + {"x9cm",1073741825,"10040"}, + {0,1,"2"}, + {"id-holdinstruction-none",1879048204,0}, + {0,1073741825,"holdInstruction"}, + {0,1,"1"}, + {"id-holdinstruction-callissuer",1879048204,0}, + {0,1073741825,"holdInstruction"}, + {0,1,"2"}, + {"id-holdinstruction-reject",1879048204,0}, + {0,1073741825,"holdInstruction"}, + {0,1,"3"}, + {"id-ce-invalidityDate",1879048204,0}, + {0,1073741825,"id-ce"}, + {0,1,"24"}, + {"InvalidityDate",1082130449,0}, + {"VisibleString",1610620935,0}, + {0,4360,"26"}, + {"NumericString",1610620935,0}, + {0,4360,"18"}, + {"IA5String",1610620935,0}, + {0,4360,"22"}, + {"TeletexString",1610620935,0}, + {0,4360,"20"}, + {"PrintableString",1610620935,0}, + {0,4360,"19"}, + {"UniversalString",1610620935,0}, + {0,4360,"28"}, + {"BMPString",1610620935,0}, + {0,4360,"30"}, + {"UTF8String",1610620935,0}, + {0,4360,"12"}, + {"id-pkix",1879048204,0}, + {"iso",1073741825,"1"}, + {"identified-organization",1073741825,"3"}, + {"dod",1073741825,"6"}, + {"internet",1073741825,"1"}, + {"security",1073741825,"5"}, + {"mechanisms",1073741825,"5"}, + {"pkix",1,"7"}, + {"id-pe",1879048204,0}, + {0,1073741825,"id-pkix"}, + {0,1,"1"}, + {"id-qt",1879048204,0}, + {0,1073741825,"id-pkix"}, + {0,1,"2"}, + {"id-kp",1879048204,0}, + {0,1073741825,"id-pkix"}, + {0,1,"3"}, + {"id-ad",1879048204,0}, + {0,1073741825,"id-pkix"}, + {0,1,"48"}, + {"id-qt-cps",1879048204,0}, + {0,1073741825,"id-qt"}, + {0,1,"1"}, + {"id-qt-unotice",1879048204,0}, + {0,1073741825,"id-qt"}, + {0,1,"2"}, + {"id-ad-ocsp",1879048204,0}, + {0,1073741825,"id-ad"}, + {0,1,"1"}, + {"id-ad-caIssuers",1879048204,0}, + {0,1073741825,"id-ad"}, + {0,1,"2"}, + {"Attribute",1610612741,0}, + {"type",1073741826,"AttributeType"}, + {"values",536870927,0}, + {0,2,"AttributeValue"}, + {"AttributeType",1073741836,0}, + {"AttributeValue",1073741837,0}, + {"AttributeTypeAndValue",1610612741,0}, + {"type",1073741826,"AttributeType"}, + {"value",2,"AttributeValue"}, + {"id-at",1879048204,0}, + {"joint-iso-ccitt",1073741825,"2"}, + {"ds",1073741825,"5"}, + {0,1,"4"}, + {"id-at-name",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"41"}, + {"id-at-surname",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"4"}, + {"id-at-givenName",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"42"}, + {"id-at-initials",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"43"}, + {"id-at-generationQualifier",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"44"}, + {"X520name",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"ub-name",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"ub-name",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"ub-name",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"ub-name",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"ub-name",524298,"1"}, + {"id-at-commonName",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"3"}, + {"X520CommonName",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"ub-common-name",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"ub-common-name",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"ub-common-name",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"ub-common-name",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"ub-common-name",524298,"1"}, + {"id-at-localityName",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"7"}, + {"X520LocalityName",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"ub-locality-name",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"ub-locality-name",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"ub-locality-name",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"ub-locality-name",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"ub-locality-name",524298,"1"}, + {"id-at-stateOrProvinceName",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"8"}, + {"X520StateOrProvinceName",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"ub-state-name",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"ub-state-name",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"ub-state-name",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"ub-state-name",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"ub-state-name",524298,"1"}, + {"id-at-organizationName",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"10"}, + {"X520OrganizationName",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"ub-organization-name",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"ub-organization-name",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"ub-organization-name",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"ub-organization-name",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"ub-organization-name",524298,"1"}, + {"id-at-organizationalUnitName",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"11"}, + {"X520OrganizationalUnitName",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"ub-organizational-unit-name",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"ub-organizational-unit-name",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"ub-organizational-unit-name",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"ub-organizational-unit-name",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"ub-organizational-unit-name",524298,"1"}, + {"id-at-title",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"12"}, + {"X520Title",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"ub-title",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"ub-title",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"ub-title",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"ub-title",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"ub-title",524298,"1"}, + {"id-at-dnQualifier",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"46"}, + {"X520dnQualifier",1073741826,"PrintableString"}, + {"id-at-countryName",1880096780,"AttributeType"}, + {0,1073741825,"id-at"}, + {0,1,"6"}, + {"X520countryName",1612709890,"PrintableString"}, + {0,1048586,"2"}, + {"pkcs-9",1879048204,0}, + {"iso",1073741825,"1"}, + {"member-body",1073741825,"2"}, + {"us",1073741825,"840"}, + {"rsadsi",1073741825,"113549"}, + {"pkcs",1073741825,"1"}, + {0,1,"9"}, + {"emailAddress",1880096780,"AttributeType"}, + {0,1073741825,"pkcs-9"}, + {0,1,"1"}, + {"Pkcs9email",1612709890,"IA5String"}, + {"ub-emailaddress-length",524298,"1"}, + {"Name",1610612754,0}, + {"rdnSequence",2,"RDNSequence"}, + {"RDNSequence",1610612747,0}, + {0,2,"RelativeDistinguishedName"}, + {"DistinguishedName",1073741826,"RDNSequence"}, + {"RelativeDistinguishedName",1612709903,0}, + {"MAX",1074266122,"1"}, + {0,2,"AttributeTypeAndValue"}, + {"DirectoryString",1610612754,0}, + {"teletexString",1612709890,"TeletexString"}, + {"MAX",524298,"1"}, + {"printableString",1612709890,"PrintableString"}, + {"MAX",524298,"1"}, + {"universalString",1612709890,"UniversalString"}, + {"MAX",524298,"1"}, + {"utf8String",1612709890,"UTF8String"}, + {"MAX",524298,"1"}, + {"bmpString",538968066,"BMPString"}, + {"MAX",524298,"1"}, + {"Certificate",1610612741,0}, + {"tbsCertificate",1073741826,"TBSCertificate"}, + {"signatureAlgorithm",1073741826,"AlgorithmIdentifier"}, + {"signature",6,0}, + {"TBSCertificate",1610612741,0}, + {"version",1610653698,"Version"}, + {0,1073741833,"v1"}, + {0,2056,"0"}, + {"serialNumber",1073741826,"CertificateSerialNumber"}, + {"signature",1073741826,"AlgorithmIdentifier"}, + {"issuer",1073741826,"Name"}, + {"validity",1073741826,"Validity"}, + {"subject",1073741826,"Name"}, + {"subjectPublicKeyInfo",1073741826,"SubjectPublicKeyInfo"}, + {"issuerUniqueID",1610637314,"UniqueIdentifier"}, + {0,4104,"1"}, + {"subjectUniqueID",1610637314,"UniqueIdentifier"}, + {0,4104,"2"}, + {"extensions",536895490,"Extensions"}, + {0,2056,"3"}, + {"Version",1610874883,0}, + {"v1",1073741825,"0"}, + {"v2",1073741825,"1"}, + {"v3",1,"2"}, + {"CertificateSerialNumber",1073741827,0}, + {"Validity",1610612741,0}, + {"notBefore",1073741826,"Time"}, + {"notAfter",2,"Time"}, + {"Time",1610612754,0}, + {"utcTime",1090519057,0}, + {"generalTime",8388625,0}, + {"UniqueIdentifier",1073741830,0}, + {"SubjectPublicKeyInfo",1610612741,0}, + {"algorithm",1073741826,"AlgorithmIdentifier"}, + {"subjectPublicKey",6,0}, + {"Extensions",1612709899,0}, + {"MAX",1074266122,"1"}, + {0,2,"Extension"}, + {"Extension",1610612741,0}, + {"extnID",1073741836,0}, + {"critical",1610645508,0}, + {0,131081,0}, + {"extnValue",7,0}, + {"CertificateList",1610612741,0}, + {"tbsCertList",1073741826,"TBSCertList"}, + {"signatureAlgorithm",1073741826,"AlgorithmIdentifier"}, + {"signature",6,0}, + {"TBSCertList",1610612741,0}, + {"version",1073758210,"Version"}, + {"signature",1073741826,"AlgorithmIdentifier"}, + {"issuer",1073741826,"Name"}, + {"thisUpdate",1073741826,"Time"}, + {"nextUpdate",1073758210,"Time"}, + {"revokedCertificates",1610629131,0}, + {0,536870917,0}, + {"userCertificate",1073741826,"CertificateSerialNumber"}, + {"revocationDate",1073741826,"Time"}, + {"crlEntryExtensions",16386,"Extensions"}, + {"crlExtensions",536895490,"Extensions"}, + {0,2056,"0"}, + {"AlgorithmIdentifier",1610612741,0}, + {"algorithm",1073741836,0}, + {"parameters",541081613,0}, + {"algorithm",1,0}, + {"pkcs-1",1879048204,0}, + {"iso",1073741825,"1"}, + {"member-body",1073741825,"2"}, + {"us",1073741825,"840"}, + {"rsadsi",1073741825,"113549"}, + {"pkcs",1073741825,"1"}, + {0,1,"1"}, + {"rsaEncryption",1879048204,0}, + {0,1073741825,"pkcs-1"}, + {0,1,"1"}, + {"md2WithRSAEncryption",1879048204,0}, + {0,1073741825,"pkcs-1"}, + {0,1,"2"}, + {"md5WithRSAEncryption",1879048204,0}, + {0,1073741825,"pkcs-1"}, + {0,1,"4"}, + {"sha1WithRSAEncryption",1879048204,0}, + {0,1073741825,"pkcs-1"}, + {0,1,"5"}, + {"id-dsa-with-sha1",1879048204,0}, + {"iso",1073741825,"1"}, + {"member-body",1073741825,"2"}, + {"us",1073741825,"840"}, + {"x9-57",1073741825,"10040"}, + {"x9algorithm",1073741825,"4"}, + {0,1,"3"}, + {"Dss-Sig-Value",1610612741,0}, + {"r",1073741827,0}, + {"s",3,0}, + {"dhpublicnumber",1879048204,0}, + {"iso",1073741825,"1"}, + {"member-body",1073741825,"2"}, + {"us",1073741825,"840"}, + {"ansi-x942",1073741825,"10046"}, + {"number-type",1073741825,"2"}, + {0,1,"1"}, + {"DomainParameters",1610612741,0}, + {"p",1073741827,0}, + {"g",1073741827,0}, + {"q",1073741827,0}, + {"j",1073758211,0}, + {"validationParms",16386,"ValidationParms"}, + {"ValidationParms",1610612741,0}, + {"seed",1073741830,0}, + {"pgenCounter",3,0}, + {"id-dsa",1879048204,0}, + {"iso",1073741825,"1"}, + {"member-body",1073741825,"2"}, + {"us",1073741825,"840"}, + {"x9-57",1073741825,"10040"}, + {"x9algorithm",1073741825,"4"}, + {0,1,"1"}, + {"Dss-Parms",1610612741,0}, + {"p",1073741827,0}, + {"q",1073741827,0}, + {"g",3,0}, + {"ORAddress",1610612741,0}, + {"built-in-standard-attributes",1073741826,"BuiltInStandardAttributes"}, + {"built-in-domain-defined-attributes",1073758210,"BuiltInDomainDefinedAttributes"}, + {"extension-attributes",16386,"ExtensionAttributes"}, + {"BuiltInStandardAttributes",1610612741,0}, + {"country-name",1073758210,"CountryName"}, + {"administration-domain-name",1073758210,"AdministrationDomainName"}, + {"network-address",1610637314,"NetworkAddress"}, + {0,2056,"0"}, + {"terminal-identifier",1610637314,"TerminalIdentifier"}, + {0,2056,"1"}, + {"private-domain-name",1610637314,"PrivateDomainName"}, + {0,2056,"2"}, + {"organization-name",1610637314,"OrganizationName"}, + {0,2056,"3"}, + {"numeric-user-identifier",1610637314,"NumericUserIdentifier"}, + {0,2056,"4"}, + {"personal-name",1610637314,"PersonalName"}, + {0,2056,"5"}, + {"organizational-unit-names",536895490,"OrganizationalUnitNames"}, + {0,2056,"6"}, + {"CountryName",1610620946,0}, + {0,1073746952,"1"}, + {"x121-dcc-code",1612709890,"NumericString"}, + {0,1048586,"ub-country-name-numeric-length"}, + {"iso-3166-alpha2-code",538968066,"PrintableString"}, + {0,1048586,"ub-country-name-alpha-length"}, + {"AdministrationDomainName",1610620946,0}, + {0,1073744904,"2"}, + {"numeric",1612709890,"NumericString"}, + {"ub-domain-name-length",524298,"0"}, + {"printable",538968066,"PrintableString"}, + {"ub-domain-name-length",524298,"0"}, + {"NetworkAddress",1073741826,"X121Address"}, + {"X121Address",1612709890,"NumericString"}, + {"ub-x121-address-length",524298,"1"}, + {"TerminalIdentifier",1612709890,"PrintableString"}, + {"ub-terminal-id-length",524298,"1"}, + {"PrivateDomainName",1610612754,0}, + {"numeric",1612709890,"NumericString"}, + {"ub-domain-name-length",524298,"1"}, + {"printable",538968066,"PrintableString"}, + {"ub-domain-name-length",524298,"1"}, + {"OrganizationName",1612709890,"PrintableString"}, + {"ub-organization-name-length",524298,"1"}, + {"NumericUserIdentifier",1612709890,"NumericString"}, + {"ub-numeric-user-id-length",524298,"1"}, + {"PersonalName",1610612750,0}, + {"surname",1814044674,"PrintableString"}, + {0,1073745928,"0"}, + {"ub-surname-length",524298,"1"}, + {"given-name",1814061058,"PrintableString"}, + {0,1073745928,"1"}, + {"ub-given-name-length",524298,"1"}, + {"initials",1814061058,"PrintableString"}, + {0,1073745928,"2"}, + {"ub-initials-length",524298,"1"}, + {"generation-qualifier",740319234,"PrintableString"}, + {0,1073745928,"3"}, + {"ub-generation-qualifier-length",524298,"1"}, + {"OrganizationalUnitNames",1612709899,0}, + {"ub-organizational-units",1074266122,"1"}, + {0,2,"OrganizationalUnitName"}, + {"OrganizationalUnitName",1612709890,"PrintableString"}, + {"ub-organizational-unit-name-length",524298,"1"}, + {"BuiltInDomainDefinedAttributes",1612709899,0}, + {"ub-domain-defined-attributes",1074266122,"1"}, + {0,2,"BuiltInDomainDefinedAttribute"}, + {"BuiltInDomainDefinedAttribute",1610612741,0}, + {"type",1612709890,"PrintableString"}, + {"ub-domain-defined-attribute-type-length",524298,"1"}, + {"value",538968066,"PrintableString"}, + {"ub-domain-defined-attribute-value-length",524298,"1"}, + {"ExtensionAttributes",1612709903,0}, + {"ub-extension-attributes",1074266122,"1"}, + {0,2,"ExtensionAttribute"}, + {"ExtensionAttribute",1610612741,0}, + {"extension-attribute-type",1611145219,0}, + {0,1073743880,"0"}, + {"0",10,"ub-extension-attributes"}, + {"extension-attribute-value",541073421,0}, + {0,1073743880,"1"}, + {"extension-attribute-type",1,0}, + {"common-name",1342177283,"1"}, + {"CommonName",1612709890,"PrintableString"}, + {"ub-common-name-length",524298,"1"}, + {"teletex-common-name",1342177283,"2"}, + {"TeletexCommonName",1612709890,"TeletexString"}, + {"ub-common-name-length",524298,"1"}, + {"teletex-organization-name",1342177283,"3"}, + {"TeletexOrganizationName",1612709890,"TeletexString"}, + {"ub-organization-name-length",524298,"1"}, + {"teletex-personal-name",1342177283,"4"}, + {"TeletexPersonalName",1610612750,0}, + {"surname",1814044674,"TeletexString"}, + {0,1073743880,"0"}, + {"ub-surname-length",524298,"1"}, + {"given-name",1814061058,"TeletexString"}, + {0,1073743880,"1"}, + {"ub-given-name-length",524298,"1"}, + {"initials",1814061058,"TeletexString"}, + {0,1073743880,"2"}, + {"ub-initials-length",524298,"1"}, + {"generation-qualifier",740319234,"TeletexString"}, + {0,1073743880,"3"}, + {"ub-generation-qualifier-length",524298,"1"}, + {"teletex-organizational-unit-names",1342177283,"5"}, + {"TeletexOrganizationalUnitNames",1612709899,0}, + {"ub-organizational-units",1074266122,"1"}, + {0,2,"TeletexOrganizationalUnitName"}, + {"TeletexOrganizationalUnitName",1612709890,"TeletexString"}, + {"ub-organizational-unit-name-length",524298,"1"}, + {"pds-name",1342177283,"7"}, + {"PDSName",1612709890,"PrintableString"}, + {"ub-pds-name-length",524298,"1"}, + {"physical-delivery-country-name",1342177283,"8"}, + {"PhysicalDeliveryCountryName",1610612754,0}, + {"x121-dcc-code",1612709890,"NumericString"}, + {0,1048586,"ub-country-name-numeric-length"}, + {"iso-3166-alpha2-code",538968066,"PrintableString"}, + {0,1048586,"ub-country-name-alpha-length"}, + {"postal-code",1342177283,"9"}, + {"PostalCode",1610612754,0}, + {"numeric-code",1612709890,"NumericString"}, + {"ub-postal-code-length",524298,"1"}, + {"printable-code",538968066,"PrintableString"}, + {"ub-postal-code-length",524298,"1"}, + {"physical-delivery-office-name",1342177283,"10"}, + {"PhysicalDeliveryOfficeName",1073741826,"PDSParameter"}, + {"physical-delivery-office-number",1342177283,"11"}, + {"PhysicalDeliveryOfficeNumber",1073741826,"PDSParameter"}, + {"extension-OR-address-components",1342177283,"12"}, + {"ExtensionORAddressComponents",1073741826,"PDSParameter"}, + {"physical-delivery-personal-name",1342177283,"13"}, + {"PhysicalDeliveryPersonalName",1073741826,"PDSParameter"}, + {"physical-delivery-organization-name",1342177283,"14"}, + {"PhysicalDeliveryOrganizationName",1073741826,"PDSParameter"}, + {"extension-physical-delivery-address-components",1342177283,"15"}, + {"ExtensionPhysicalDeliveryAddressComponents",1073741826,"PDSParameter"}, + {"unformatted-postal-address",1342177283,"16"}, + {"UnformattedPostalAddress",1610612750,0}, + {"printable-address",1814052875,0}, + {"ub-pds-physical-address-lines",1074266122,"1"}, + {0,538968066,"PrintableString"}, + {"ub-pds-parameter-length",524298,"1"}, + {"teletex-string",740311042,"TeletexString"}, + {"ub-unformatted-address-length",524298,"1"}, + {"street-address",1342177283,"17"}, + {"StreetAddress",1073741826,"PDSParameter"}, + {"post-office-box-address",1342177283,"18"}, + {"PostOfficeBoxAddress",1073741826,"PDSParameter"}, + {"poste-restante-address",1342177283,"19"}, + {"PosteRestanteAddress",1073741826,"PDSParameter"}, + {"unique-postal-name",1342177283,"20"}, + {"UniquePostalName",1073741826,"PDSParameter"}, + {"local-postal-attributes",1342177283,"21"}, + {"LocalPostalAttributes",1073741826,"PDSParameter"}, + {"PDSParameter",1610612750,0}, + {"printable-string",1814052866,"PrintableString"}, + {"ub-pds-parameter-length",524298,"1"}, + {"teletex-string",740311042,"TeletexString"}, + {"ub-pds-parameter-length",524298,"1"}, + {"extended-network-address",1342177283,"22"}, + {"ExtendedNetworkAddress",1610612754,0}, + {"e163-4-address",1610612741,0}, + {"number",1612718082,"NumericString"}, + {0,1073743880,"0"}, + {"ub-e163-4-number-length",524298,"1"}, + {"sub-address",538992642,"NumericString"}, + {0,1073743880,"1"}, + {"ub-e163-4-sub-address-length",524298,"1"}, + {"psap-address",536879106,"PresentationAddress"}, + {0,2056,"0"}, + {"PresentationAddress",1610612741,0}, + {"pSelector",1610637319,0}, + {0,2056,"0"}, + {"sSelector",1610637319,0}, + {0,2056,"1"}, + {"tSelector",1610637319,0}, + {0,2056,"2"}, + {"nAddresses",538976271,0}, + {0,1073743880,"3"}, + {"MAX",1074266122,"1"}, + {0,7,0}, + {"terminal-type",1342177283,"23"}, + {"TerminalType",1611137027,0}, + {"0",10,"ub-integer-options"}, + {"teletex-domain-defined-attributes",1342177283,"6"}, + {"TeletexDomainDefinedAttributes",1612709899,0}, + {"ub-domain-defined-attributes",1074266122,"1"}, + {0,2,"TeletexDomainDefinedAttribute"}, + {"TeletexDomainDefinedAttribute",1610612741,0}, + {"type",1612709890,"TeletexString"}, + {"ub-domain-defined-attribute-type-length",524298,"1"}, + {"value",538968066,"TeletexString"}, + {"ub-domain-defined-attribute-value-length",524298,"1"}, + {"ub-name",1342177283,"32768"}, + {"ub-common-name",1342177283,"64"}, + {"ub-locality-name",1342177283,"128"}, + {"ub-state-name",1342177283,"128"}, + {"ub-organization-name",1342177283,"64"}, + {"ub-organizational-unit-name",1342177283,"64"}, + {"ub-title",1342177283,"64"}, + {"ub-match",1342177283,"128"}, + {"ub-emailaddress-length",1342177283,"128"}, + {"ub-common-name-length",1342177283,"64"}, + {"ub-country-name-alpha-length",1342177283,"2"}, + {"ub-country-name-numeric-length",1342177283,"3"}, + {"ub-domain-defined-attributes",1342177283,"4"}, + {"ub-domain-defined-attribute-type-length",1342177283,"8"}, + {"ub-domain-defined-attribute-value-length",1342177283,"128"}, + {"ub-domain-name-length",1342177283,"16"}, + {"ub-extension-attributes",1342177283,"256"}, + {"ub-e163-4-number-length",1342177283,"15"}, + {"ub-e163-4-sub-address-length",1342177283,"40"}, + {"ub-generation-qualifier-length",1342177283,"3"}, + {"ub-given-name-length",1342177283,"16"}, + {"ub-initials-length",1342177283,"5"}, + {"ub-integer-options",1342177283,"256"}, + {"ub-numeric-user-id-length",1342177283,"32"}, + {"ub-organization-name-length",1342177283,"64"}, + {"ub-organizational-unit-name-length",1342177283,"32"}, + {"ub-organizational-units",1342177283,"4"}, + {"ub-pds-name-length",1342177283,"16"}, + {"ub-pds-parameter-length",1342177283,"30"}, + {"ub-pds-physical-address-lines",1342177283,"6"}, + {"ub-postal-code-length",1342177283,"16"}, + {"ub-surname-length",1342177283,"40"}, + {"ub-terminal-id-length",1342177283,"24"}, + {"ub-unformatted-address-length",1342177283,"180"}, + {"ub-x121-address-length",268435459,"16"}, + {0,0,0} +}; diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..709f4b3 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES = -I../lib + +EXTRA_DIST = Test_parser.asn Test_tree.asn Test_tree_asn1_tab.c + +noinst_PROGRAMS = Test_parser Test_tree +Test_parser_SOURCES = Test_parser.c +Test_parser_LDADD = ../lib/libasn1.la + +Test_tree_SOURCES = Test_tree.c +Test_tree_LDADD = ../lib/libasn1.la diff --git a/tests/Test_parser.c b/tests/Test_parser.c new file mode 100644 index 0000000..488ad36 --- /dev/null +++ b/tests/Test_parser.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/*****************************************************/ +/* File: Test_parser.c */ +/* Description: Test sequences for these functions: */ +/* asn1_parser_asn1, */ +/*****************************************************/ + +#include +#include +#include "libasn1.h" + +typedef struct{ + int lineNumber; + char *line; + int errorNumber; + char *errorDescription; +} test_type; + +char fileCorrectName[]="Test_parser.asn"; +char fileErroredName[]="Test_parser_ERROR.asn"; + +#define _FILE_ "Test_parser_ERROR.asn" + +test_type test_array[]={ + /* Test DEFINITIONS syntax */ + {5,"TEST_PARSER2 { } DEFINITIONS IMPLICIT TAGS ::= BEGIN int1 ::= INTEGER END", + ASN1_SYNTAX_ERROR,_FILE_":6: parse error near 'TEST_PARSER'"}, + {6,"TEST_PARSER { }",ASN1_SUCCESS,""}, + + /* Test MAX_NAME_SIZE (128) */ + {12,"a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 ::= INTEGER", + ASN1_SUCCESS,""}, + {12,"a12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 ::= INTEGER", + ASN1_NAME_TOO_LONG,_FILE_":12: name too long (more than 128 characters)"}, + + /* Test 'check identifier' function */ + {12,"ident1 ::= ident2 ident2 ::= INTEGER", + ASN1_SUCCESS,""}, + {12,"ident1 ::= ident2", + ASN1_IDENTIFIER_NOT_FOUND,_FILE_":: identifier 'ident2' not found"}, + {12,"obj1 OBJECT IDENTIFIER ::= {pkix 0 5 4} " + "pkix OBJECT IDENTIFIER ::= {1 2}", + ASN1_SUCCESS,""}, + {12,"obj1 OBJECT IDENTIFIER ::= {pkix 0 5 4}", + ASN1_IDENTIFIER_NOT_FOUND,_FILE_":: identifier 'pkix' not found"}, + + /* Test INTEGER */ + {14,"int1 INTEGER OPTIONAL,",ASN1_SUCCESS,""}, + {14,"int1 INTEGER DEFAULT 1,",ASN1_SUCCESS,""}, + {14,"int1 INTEGER DEFAULT -1,",ASN1_SUCCESS,""}, + {14,"int1 INTEGER DEFAULT v1,",ASN1_SUCCESS,""}, + {14,"int1 [1] INTEGER,",ASN1_SUCCESS,""}, + {14,"int1 [1] EXPLICIT INTEGER,",ASN1_SUCCESS,""}, + {14,"int1 [1] IMPLICIT INTEGER,",ASN1_SUCCESS,""}, + {12,"Integer ::= [1] EXPLICIT INTEGER {v1(-1), v2(1)}",ASN1_SUCCESS,""}, + {12,"Integer ::= INTEGER {v1(0), v2}", + ASN1_SYNTAX_ERROR,_FILE_":12: parse error near '}'"}, + {12,"Integer ::= INTEGER {v1(0), 1}", + ASN1_SYNTAX_ERROR,_FILE_":12: parse error near '1'"}, + {12,"const1 INTEGER ::= -10",ASN1_SUCCESS,""}, + {12,"const1 INTEGER ::= 10",ASN1_SUCCESS,""}, + {12,"const1 INTEGER ::= v1", + ASN1_SYNTAX_ERROR,_FILE_":12: parse error near 'v1'"}, + + + + /* end */ + {0} +}; + +char +readLine(FILE *file,char *line) +{ + char c; + + while(((c=fgetc(file))!=EOF) && (c!='\n')){ + *line=c; + line++; + } + + *line=0; + + return c; +} + + +void +createFile(int lineNumber,char *line) +{ + FILE *fileIn,*fileOut; + char lineRead[1024]; + int fileInLineNumber=0; + + fileIn=fopen(fileCorrectName,"r"); + fileOut=fopen(fileErroredName,"w"); + + while(readLine(fileIn,lineRead) != EOF){ + fileInLineNumber++; + if(fileInLineNumber==lineNumber) + fprintf(fileOut,"%s\n",line); + else + fprintf(fileOut,"%s\n",lineRead); + } + + fclose(fileOut); + fclose(fileIn); +} + + +int +main(int argc,char *argv[]) +{ + asn1_retCode result; + ASN1_TYPE definitions=ASN1_TYPE_EMPTY; + char errorDescription[MAX_ERROR_DESCRIPTION_SIZE]; + test_type *test; + int errorCounter=0,testCounter=0; + + printf("\n\n/****************************************/\n"); + printf( "/* Test sequence : Test_parser */\n"); + printf( "/****************************************/\n\n"); + + + result=asn1_parser2tree(fileCorrectName,&definitions,errorDescription); + + if(result!=ASN1_SUCCESS){ + printf("File '%s' not correct\n",fileCorrectName); + libasn1_perror(result); + printf("ErrorDescription = %s\n\n",errorDescription); + exit(1); + } + + /* Only for Test */ + //asn1_visit_tree(stdout,definitions,"TEST_PARSER",ASN1_PRINT_ALL); + + /* Clear the definitions structures */ + asn1_delete_structure(&definitions); + + + test=test_array; + + while(test->lineNumber != 0){ + testCounter++; + + createFile(test->lineNumber,test->line); + + result=asn1_parser2tree(fileErroredName,&definitions,errorDescription); + asn1_delete_structure(&definitions); + + if((result != test->errorNumber) || + (strcmp(errorDescription,test->errorDescription))){ + errorCounter++; + printf("ERROR N. %d:\n",errorCounter); + printf(" Line %d - %s\n",test->lineNumber,test->line); + printf(" Error expected: %s - %s\n",libasn1_strerror(test->errorNumber), + test->errorDescription); + printf(" Error detected: %s - %s\n\n",libasn1_strerror(result), + errorDescription); + } + + test++; + } + + + printf("Total tests : %d\n",testCounter); + printf("Total errors: %d\n",errorCounter); + + exit(0); +} + + + + + + + diff --git a/tests/Test_tree.asn b/tests/Test_tree.asn new file mode 100644 index 0000000..b7a441c --- /dev/null +++ b/tests/Test_tree.asn @@ -0,0 +1,22 @@ +-- +-- File used in the test sequence Test_tree. +-- + +TEST_TREE {iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit-88(2)} + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +Sequence1 ::= SEQUENCE{ + int1 INTEGER DEFAULT -5, + int2 INTEGER +} + +END + + + + + diff --git a/tests/Test_tree.c b/tests/Test_tree.c new file mode 100644 index 0000000..6b0ef69 --- /dev/null +++ b/tests/Test_tree.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2002 Fabio Fiorina + * + * This file is part of LIBASN1. + * + * LIBASN1 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBASN1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/*****************************************************/ +/* File: Test_tree.c */ +/* Description: Test sequences for these functions: */ +/* asn1_visit_tree, */ +/* asn1_create_structure, */ +/* asn1_delete_structure, */ +/* asn1_write_value, */ +/* asn1_read_value, */ +/*****************************************************/ + +#include +#include +#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;kpar2[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;kpar3;k++) + printf("%02x",test->par2[k]); + printf("\n Error detected: %s - %d - ",libasn1_strerror(result), + valueLen); + for(k=0;k