Initial revision
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 5 Apr 2002 19:57:55 +0000 (19:57 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 5 Apr 2002 19:57:55 +0000 (19:57 +0000)
34 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
THANKS [new file with mode: 0644]
acconfig.h [new file with mode: 0644]
acinclude.m4 [new file with mode: 0644]
buildconf [new file with mode: 0755]
configure.in [new file with mode: 0644]
doc/Makefile.am [new file with mode: 0644]
doc/TODO [new file with mode: 0644]
doc/asn1.tex [new file with mode: 0644]
doc/fdl.tex [new file with mode: 0644]
doc/scripts/Makefile.am [new file with mode: 0644]
doc/scripts/gdoc [new file with mode: 0755]
lib/ASN.c [new file with mode: 0644]
lib/ASN.y [new file with mode: 0644]
lib/Makefile.am [new file with mode: 0644]
lib/asn1.c [new file with mode: 0644]
lib/asn1.h [new file with mode: 0644]
lib/defines.h [new file with mode: 0644]
lib/der.c [new file with mode: 0644]
lib/der.h [new file with mode: 0644]
lib/gstr.c [new file with mode: 0644]
lib/gstr.h [new file with mode: 0644]
lib/mem.h [new file with mode: 0644]
src/CertificateExample.c [new file with mode: 0644]
src/CrlExample.c [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/asn1c.c [new file with mode: 0644]
src/pkix.asn [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..e20eef2
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+
+Fabio Fiorina          <Fabio.Fiorina@alcatel.it>
+
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..60549be
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..b42a17a
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..60f3825
--- /dev/null
@@ -0,0 +1,7 @@
+## Process this file with automake to produce Makefile.in
+
+EXTRA_DIST = ChangeLog NEWS INSTALL README THANKS COPYING 
+SUBDIRS = lib src doc
+
+ChangeLog:
+       cvs2cl --utc -U .cvsusers --fsf -t -S --prune
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..f1cc949
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,2 @@
+Version 0.1.0
+- Initial release
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..8f4947a
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+This is the ASN.1 library used in GNUTLS. 
+More up to date information can be found at 
+http://www.gnu.org/software/gnutls and http://www.gnutls.org
+
+* Documentation:
+ view the doc/ directory and the examples in the src/ directory.
+
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/acconfig.h b/acconfig.h
new file mode 100644 (file)
index 0000000..a29dd8e
--- /dev/null
@@ -0,0 +1,13 @@
+#undef PACKAGE
+#undef VERSION
+
+#undef T_CPU
+#undef T_VENDOR
+#undef T_OS
+
+#undef LT_CURRENT
+#undef LT_REVISION
+#undef LT_AGE
+
+#undef ASN1_VERSION
+
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644 (file)
index 0000000..aad539d
--- /dev/null
@@ -0,0 +1,2 @@
+
+dnl *-*wedit:notab*-*  Please keep this as the last line.
diff --git a/buildconf b/buildconf
new file mode 100755 (executable)
index 0000000..5903699
--- /dev/null
+++ b/buildconf
@@ -0,0 +1,9 @@
+#! /bin/sh
+
+aclocal && \
+libtoolize -c --force --automake && \
+aclocal && \
+autoheader  && \
+automake -a -c --gnu || automake -a -c --gnu
+autoconf
+
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..0723bbe
--- /dev/null
@@ -0,0 +1,111 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.50)
+AC_INIT
+
+AC_PREFIX_DEFAULT(/usr/local)
+
+AC_CANONICAL_TARGET([])
+AC_DEFINE_UNQUOTED(T_CPU, "$target_cpu")
+AC_DEFINE_UNQUOTED(T_VENDOR, "$target_vendor")
+AC_DEFINE_UNQUOTED(T_OS, "$target_os")
+
+dnl libasn1 Version
+ASN1_MAJOR_VERSION=0
+ASN1_MINOR_VERSION=1
+ASN1_MICRO_VERSION=0
+ASN1_VERSION=$ASN1_MAJOR_VERSION.$ASN1_MINOR_VERSION.$ASN1_MICRO_VERSION
+
+AC_DEFINE_UNQUOTED(ASN1_VERSION, "$ASN1_VERSION")
+
+AM_INIT_AUTOMAKE(gnutls, $ASN1_VERSION)
+AM_CONFIG_HEADER(config.h)
+
+dnl This is the library version
+ASN1_MOST_RECENT_INTERFACE=0
+ASN1_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER=$ASN1_MICRO_VERSION
+ASN1_OLDEST_INTERFACE=0
+
+
+AC_SUBST(ASN1_MAJOR_VERSION)
+AC_SUBST(ASN1_MINOR_VERSION)
+AC_SUBST(ASN1_MICRO_VERSION)
+AC_SUBST(ASN1_VERSION)
+
+AC_SUBST(ASN1_MOST_RECENT_INTERFACE)
+AC_SUBST(ASN1_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER)
+AC_SUBST(ASN1_OLDEST_INTERFACE)
+
+LT_CURRENT=$ASN1_MOST_RECENT_INTERFACE
+LT_REVISION=$ASN1_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER
+LT_AGE=`expr $ASN1_MOST_RECENT_INTERFACE - $ASN1_OLDEST_INTERFACE`
+AC_SUBST(LT_CURRENT)
+AC_SUBST(LT_REVISION)
+AC_SUBST(LT_AGE)
+
+AC_PROG_CC
+
+AC_PROG_YACC
+
+AC_PROG_LN_S
+
+
+dnl Checks for programs.
+AC_PROG_INSTALL
+
+
+AC_MSG_RESULT([***
+*** Detecting compiler options...
+])
+
+
+AC_C_CONST
+AC_C_INLINE
+
+
+if test $ac_cv_c_compiler_gnu != no; then
+
+        CFLAGS="${CFLAGS} -Wall -Wpointer-arith -Wstrict-prototypes"
+
+       AC_MSG_CHECKING([whether we have GNU assembler])
+       
+       GAS=`as --version < /dev/null|grep GNU`
+       if test "$GAS"; then
+         CFLAGS="${CFLAGS} -pipe"
+         AC_MSG_RESULT(yes)
+       else
+         AC_MSG_RESULT(no)
+       fi
+fi
+
+
+AC_MSG_RESULT([***
+*** Detecting C library capabilities...
+])
+
+AC_HEADER_STDC
+AC_CHECK_HEADERS(unistd.h strings.h)
+AC_CHECK_FUNCS(bzero memset memmove bcopy,,)
+AC_FUNC_ALLOCA
+
+
+AC_MSG_RESULT([***
+*** Detecting system's parameters...
+])
+
+AC_CHECK_SIZEOF(unsigned long long, 8)
+AC_CHECK_SIZEOF(unsigned long int, 4)
+AC_CHECK_SIZEOF(unsigned int, 4)
+AC_CHECK_SIZEOF(unsigned short int, 2)
+AC_CHECK_SIZEOF(unsigned char, 1)
+
+
+
+AC_MSG_RESULT([***
+*** Detecting options for shared libraries...
+])
+AM_PROG_LIBTOOL
+
+AC_CONFIG_FILES([Makefile src/Makefile lib/Makefile \
+doc/Makefile doc/scripts/Makefile])
+AC_OUTPUT
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644 (file)
index 0000000..a257afb
--- /dev/null
@@ -0,0 +1,19 @@
+EXTRA_DIST = asn1.tex asn1.ps asn1.html fdl.tex TODO
+SUBDIRS = scripts
+
+
+TEX_OBJECTS = asn1.tex ../lib/asn1-api.tex 
+
+asn1.ps: $(TEX_OBJECTS)
+       -$(LN_S) ../lib/asn1-api.tex .
+       -latex asn1.tex && latex asn1.tex && dvips asn1.dvi -o asn1.ps
+
+asn1.html: $(TEX_OBJECTS)
+       -latex2html asn1.tex -no_navigation -no_subdir 1 -split 0 -local_icons -html_version 3.2,math \
+       -info "" -white
+
+
+clean:
+       @-rm *.log *.aux *.toc
+       @-rm *.pl index.html asn1.dvi
+       @-rm WARNINGS asn1-api.tex
diff --git a/doc/TODO b/doc/TODO
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/doc/asn1.tex b/doc/asn1.tex
new file mode 100644 (file)
index 0000000..1ef06ed
--- /dev/null
@@ -0,0 +1,142 @@
+\documentclass{book}
+\usepackage{html}
+\usepackage{fancyheadings}
+\usepackage{graphicx}
+
+\begin{document}
+
+\vspace*{\stretch{2}}
+
+\begin{center}
+\par
+Copyright \copyright\ 2001, 2002 Fabio Fiorina\\
+\setlength{\parskip}{4mm}
+\par
+Permission is granted to copy, distribute and/or modify this
+document under the terms of the GNU Free Documentation License,
+Version 1.1 or any later version published by the Free Software
+Foundation; with no Invariant Sections, no Front-Cover Texts and
+no Back-Cover Texts.  A copy of the license is included in the
+chapter entitled "GNU Free Documentation License".
+\end{center}
+
+\setlength{\parindent}{2mm}
+
+\setlength{\parskip}{1mm}
+
+
+\chapter{ASN.1 structures handling}
+
+\section{Introduction}
+ This file describes the forth version of ASN.1 parser I
+developed.
+The main difference from the first version is the use of pointers and the
+possibility to save/get ASN1 definitions in/from a C vector.
+Other differences are:
+\begin{itemize}
+\item write\_value function for type ANY
+\item the introduction of ENUMERATED type,
+\item negative integer are allowed in ASN.1 syntax files,
+\item PKIX1Implicit88.txt instead of Certificate.txt for the Certificate description
+\item functions naming 
+\item an easier way to set INTEGER and get OBJECT IDENTFIER  
+\end{itemize}
+
+
+\section{ASN.1 syntax}
+The parser is case sensitive. The comments begin with "-- " and end at the end of line.
+An example is in "Certificate.txt" file.
+The ASN.1 declarations must have this form:
+      
+\begin{verbatim}
+      object_name {<object definition>}
+
+      DEFINITIONS <EXPLICIT or IMPLICIT> TAGS ::=
+
+      BEGIN 
+
+      <type and constants definitions>
+
+      END
+\end{verbatim}
+
+\par
+The token "::=" must be separate from others elements, so this is a wrong declaration:
+      Version ::=INTEGER 
+the correct one is :   Version ::= INTEGER
+Here is the list of types that the parser can manage:
+\begin{itemize}
+
+\item      INTEGER
+\item      ENUMERATED
+\item      BOOLEAN
+\item      OBJECT IDENTIFIER
+\item      NULL
+\item      BIT STRING
+\item      OCTET STRING
+\item      UTCTime
+\item      GeneralizedTime
+\item      SEQUENCE
+\item      SEQUENCE OF
+\item      SET 
+\item      SET OF
+\item      CHOICE
+\item      ANY
+\item      ANY DEFINED BY
+\end{itemize}
+
+This version doesn't manage REAL type. It also not allow the use of 
+"EXPORT" and "IMPORT" sections.
+
+The SIZE constraints are allowed but no check is done on them.
+
+
+
+\section{Naming}
+If you have this definitions:
+
+\begin{verbatim}
+      Example { 1 2 3 4 }
+
+      DEFINITIONS EXPLICIT TAGS ::=
+
+      BEGIN 
+
+      Group ::= SEQUENCE {
+         id   OBJECT IDENTIFIER,
+         value  Value
+      }
+
+      Value ::= SEQUENCE {
+         value1  INTEGER,
+         value2  BOOLEAN 
+      }
+
+      END
+\end{verbatim}
+
+to identify the type 'Group' you have to use the null terminated string "Example.Group".
+Others examples:
+Field 'id' in 'Group' type :  "Example.Group.id"
+Field 'value1' in filed 'value' in type 'Group':   "Example.Group.value.value1" 
+These strings are used in functions that are described below.
+Elements of structured types that don't have a name, receve the name "?1","?2", and so on. 
+The name "?LAST" indicates the last element of a SET\_OF or SEQUENCE\_OF.
+
+\section{Future developments}
+\begin{enumerate}
+\item type REAL 
+\item improve the error signaling with strings that give you more details. 
+   Examples: in case of ASN1 syntax error you will have the line number where the error is,  
+             if creating a der encoding the result is ASN\_VALUE\_NOT\_FOUND you will have the
+             name of the element without the value.
+\item improve the 'visit\_tree' function and change the output from stdout to a null terminated 
+   string.  
+
+\end{enumerate}
+
+\input{asn1-api}
+
+\input{fdl.tex}
+
+\end{document}
diff --git a/doc/fdl.tex b/doc/fdl.tex
new file mode 100644 (file)
index 0000000..c0fcbe3
--- /dev/null
@@ -0,0 +1,367 @@
+% fdl.tex 
+% This file is a chapter.  It must be included in a larger document to work
+% properly.
+
+\chapter{GNU Free Documentation License}
+
+Version 1.1, March 2000\\
+
+ Copyright \copyright\ 2000  Free Software Foundation, Inc.\\
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\\
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+\section*{Preamble}
+
+The purpose of this License is to make a manual, textbook, or other
+written document ``free'' in the sense of freedom: to assure everyone
+the effective freedom to copy and redistribute it, with or without
+modifying it, either commercially or noncommercially.  Secondarily,
+this License preserves for the author and publisher a way to get
+credit for their work, while not being considered responsible for
+modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+\section{Applicability and Definitions}
+
+This License applies to any manual or other work that contains a
+notice placed by the copyright holder saying it can be distributed
+under the terms of this License.  The ``Document'', below, refers to any
+such manual or work.  Any member of the public is a licensee, and is
+addressed as ``you''.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section of
+the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall subject
+(or to related matters) and contains nothing that could fall directly
+within that overall subject.  (For example, if the Document is in part a
+textbook of mathematics, a Secondary Section may not explain any
+mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, whose contents can be viewed and edited directly and
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup has been designed to thwart or discourage
+subsequent modification by readers is not Transparent.  A copy that is
+not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, \LaTeX~input format, SGML
+or XML using a publicly available DTD, and standard-conforming simple
+HTML designed for human modification.  Opaque formats include
+PostScript, PDF, proprietary formats that can be read and edited only
+by proprietary word processors, SGML or XML for which the DTD and/or
+processing tools are not generally available, and the
+machine-generated HTML produced by some word processors for output
+purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+
+\section{Verbatim Copying}
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+
+\section{Copying in Quantity}
+
+If you publish printed copies of the Document numbering more than 100,
+and the Document's license notice requires Cover Texts, you must enclose
+the copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a publicly-accessible computer-network location containing a complete
+Transparent copy of the Document, free of added material, which the
+general network-using public has access to download anonymously at no
+charge using public-standard network protocols.  If you use the latter
+option, you must take reasonably prudent steps, when you begin
+distribution of Opaque copies in quantity, to ensure that this
+Transparent copy will remain thus accessible at the stated location
+until at least one year after the last time you distribute an Opaque
+copy (directly or through your agents or retailers) of that edition to
+the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+
+\section{Modifications}
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+\begin{itemize}
+
+\item Use in the Title Page (and on the covers, if any) a title distinct
+   from that of the Document, and from those of previous versions
+   (which should, if there were any, be listed in the History section
+   of the Document).  You may use the same title as a previous version
+   if the original publisher of that version gives permission.
+\item List on the Title Page, as authors, one or more persons or entities
+   responsible for authorship of the modifications in the Modified
+   Version, together with at least five of the principal authors of the
+   Document (all of its principal authors, if it has less than five).
+\item State on the Title page the name of the publisher of the
+   Modified Version, as the publisher.
+\item Preserve all the copyright notices of the Document.
+\item Add an appropriate copyright notice for your modifications
+   adjacent to the other copyright notices.
+\item Include, immediately after the copyright notices, a license notice
+   giving the public permission to use the Modified Version under the
+   terms of this License, in the form shown in the Addendum below.
+\item Preserve in that license notice the full lists of Invariant Sections
+   and required Cover Texts given in the Document's license notice.
+\item Include an unaltered copy of this License.
+\item Preserve the section entitled ``History'', and its title, and add to
+   it an item stating at least the title, year, new authors, and
+   publisher of the Modified Version as given on the Title Page.  If
+   there is no section entitled ``History'' in the Document, create one
+   stating the title, year, authors, and publisher of the Document as
+   given on its Title Page, then add an item describing the Modified
+   Version as stated in the previous sentence.
+\item Preserve the network location, if any, given in the Document for
+   public access to a Transparent copy of the Document, and likewise
+   the network locations given in the Document for previous versions
+   it was based on.  These may be placed in the ``History'' section.
+   You may omit a network location for a work that was published at
+   least four years before the Document itself, or if the original
+   publisher of the version it refers to gives permission.
+\item In any section entitled ``Acknowledgements'' or ``Dedications'',
+   preserve the section's title, and preserve in the section all the
+   substance and tone of each of the contributor acknowledgements
+   and/or dedications given therein.
+\item Preserve all the Invariant Sections of the Document,
+   unaltered in their text and in their titles.  Section numbers
+   or the equivalent are not considered part of the section titles.
+\item Delete any section entitled ``Endorsements''.  Such a section
+   may not be included in the Modified Version.
+\item Do not retitle any existing section as ``Endorsements''
+   or to conflict in title with any Invariant Section.
+
+\end{itemize}
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties -- for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+
+\section{Combining Documents}
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections entitled ``History''
+in the various original documents, forming one section entitled
+``History''; likewise combine any sections entitled ``Acknowledgements'',
+and any sections entitled ``Dedications''.  You must delete all sections
+entitled ``Endorsements.''
+
+
+\section{Collections of Documents}
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+
+
+\section{Aggregation With Independent Works}
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, does not as a whole count as a Modified Version
+of the Document, provided no compilation copyright is claimed for the
+compilation.  Such a compilation is called an ``aggregate'', and this
+License does not apply to the other self-contained works thus compiled
+with the Document, on account of their being thus compiled, if they
+are not themselves derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one quarter
+of the entire aggregate, the Document's Cover Texts may be placed on
+covers that surround only the Document within the aggregate.
+Otherwise they must appear on covers around the whole aggregate.
+
+
+\section{Translation}
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License provided that you also include the
+original English version of this License.  In case of a disagreement
+between the translation and the original English version of this
+License, the original English version will prevail.
+
+
+\section{Termination}
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License.  Any other attempt to
+copy, modify, sublicense or distribute the Document is void, and will
+automatically terminate your rights under this License.  However,
+parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+
+\section{Future Revisions of This License}
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation License from time to time.  Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns. See
+http://www.gnu.org/copyleft/.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License "or any later version" applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+
+\section*{ADDENDUM: How to use this License for your documents}
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+\begin{quote}
+
+      Copyright \copyright\ YEAR  YOUR NAME.
+      Permission is granted to copy, distribute and/or modify this document
+      under the terms of the GNU Free Documentation License, Version 1.1
+      or any later version published by the Free Software Foundation;
+      with the Invariant Sections being LIST THEIR TITLES, with the
+      Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
+      A copy of the license is included in the section entitled ``GNU
+      Free Documentation License''.
+
+\end{quote}
+
+If you have no Invariant Sections, write ``with no Invariant Sections''
+instead of saying which ones are invariant.  If you have no
+Front-Cover Texts, write ``no Front-Cover Texts'' instead of
+``Front-Cover Texts being LIST''; likewise for Back-Cover Texts.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
diff --git a/doc/scripts/Makefile.am b/doc/scripts/Makefile.am
new file mode 100644 (file)
index 0000000..7deb104
--- /dev/null
@@ -0,0 +1,3 @@
+EXTRA_DIST = gdoc
+
+
diff --git a/doc/scripts/gdoc b/doc/scripts/gdoc
new file mode 100755 (executable)
index 0000000..9597148
--- /dev/null
@@ -0,0 +1,703 @@
+#!/usr/bin/perl
+
+## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
+##                    hacked to allow -tex option --nmav         ##
+##                                                               ##
+## This software falls under the GNU Public License. Please read ##
+##              the COPYING file for more information            ##
+
+#
+# This will read a 'c' file and scan for embedded comments in the
+# style of gnome comments (+minor extensions - see below).
+#
+# This program is modified by Nikos Mavroyanopoulos, for the gnutls
+# project.
+
+# Note: This only supports 'c'.
+
+# usage:
+# gdoc [ -docbook | -html | -text | -man | -tex ]
+#      [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
+#
+#  Set output format using one of -docbook -html -text or -man.  Default is man.
+#
+#  -function funcname
+#      If set, then only generate documentation for the given function(s).  All
+#      other functions are ignored.
+#
+#  c files - list of 'c' files to process
+#
+#  All output goes to stdout, with errors to stderr.
+
+#
+# format of comments.
+# In the following table, (...)? signifies optional structure.
+#                         (...)* signifies 0 or more structure elements
+# /**
+#  * function_name(:)? (- short description)?
+# (* @parameterx: (description of parameter x)?)*
+# (* a blank line)?
+#  * (Description:)? (Description of function)?
+#  * (section header: (section description)? )*
+#  (*)?*/
+#
+# So .. the trivial example would be:
+#
+# /**
+#  * my_function
+#  **/
+#
+# If the Description: header tag is ommitted, then there must be a blank line
+# after the last parameter specification.
+# e.g.
+# /**
+#  * my_function - does my stuff
+#  * @my_arg: its mine damnit
+#  *
+#  * Does my stuff explained. 
+#  */
+#
+#  or, could also use:
+# /**
+#  * my_function - does my stuff
+#  * @my_arg: its mine damnit
+#  * Description: Does my stuff explained. 
+#  */
+# etc.
+#
+# All descriptions can be multiline, apart from the short function description.
+#
+# All descriptive text is further processed, scanning for the following special
+# patterns, which are highlighted appropriately.
+#
+# 'funcname()' - function
+# '$ENVVAR' - environmental variable
+# '&struct_name' - name of a structure
+# '@parameter' - name of a parameter
+# '%CONST' - name of a constant.
+
+#
+# Extensions for LaTeX:
+#
+# 1. the symbol '->' will be replaced with a rightarrow
+# 2. x^y with ${x}^{y}$.
+# 3. xxx\: with xxx:
+
+
+# match expressions used to find embedded type information
+$type_constant = "\\\%(\\w+)";
+#$type_func = "(\\w+\\(\\))";
+$type_func = "(\\(w||\\\\)+\\(\\))";
+$type_param = "\\\@(\\w+)";
+$type_struct = "\\\&(\\w+)";
+$type_env = "(\\\$\\w+)";
+
+
+# Output conversion substitutions.
+#  One for each output format
+
+# these work fairly well
+%highlights_html = ( $type_constant, "<i>\$1</i>",
+                    $type_func, "<b>\$1</b>",
+                    $type_struct, "<i>\$1</i>",
+                    $type_param, "<tt><b>\$1</b></tt>" );
+$blankline_html = "<p>";
+
+%highlights_tex = ( $type_constant, "{\\\\it \$1}",
+                    $type_func, "{\\\\bf \$1}",
+                    $type_struct, "{\\\\it \$1}",
+                    $type_param, "{\\\\bf \$1}" );
+$blankline_tex = "\\par";
+
+# sgml, docbook format
+%highlights_sgml = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
+                    $type_func, "<function>\$1</function>",
+                    $type_struct, "<structname>\$1</structname>",
+                    $type_env, "<envar>\$1</envar>",
+                    $type_param, "<parameter>\$1</parameter>" );
+$blankline_sgml = "</para><para>\n";
+
+# these are pretty rough
+%highlights_man = ( $type_constant, "\\n.I \\\"\$1\\\"\\n",
+                   $type_func, "\\n.B \\\"\$1\\\"\\n",
+                   $type_struct, "\\n.I \\\"\$1\\\"\\n",
+                   $type_param."([\.\, ]*)\n?", "\\n.I \\\"\$1\$2\\\"\\n" );
+$blankline_man = "";
+
+# text-mode
+%highlights_text = ( $type_constant, "\$1",
+                    $type_func, "\$1",
+                    $type_struct, "\$1",
+                    $type_param, "\$1" );
+$blankline_text = "";
+
+
+sub usage {
+    print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -tex ]\n";
+    print "         [ -function funcname [ -function funcname ...] ]\n";
+    print "         c source file(s) > outputfile\n";
+    exit 1;
+}
+
+# read arguments
+if ($#ARGV==-1) {
+    usage();
+}
+
+$verbose = 0;
+$output_mode = "man";
+%highlights = %highlights_man;
+$blankline = $blankline_man;
+$modulename = "API Documentation";
+$function_only = 0;
+while ($ARGV[0] =~ m/^-(.*)/) {
+    $cmd = shift @ARGV;
+    if ($cmd eq "-html") {
+       $output_mode = "html";
+       %highlights = %highlights_html;
+       $blankline = $blankline_html;
+    } elsif ($cmd eq "-man") {
+       $output_mode = "man";
+       %highlights = %highlights_man;
+       $blankline = $blankline_man;
+    } elsif ($cmd eq "-tex") {
+       $output_mode = "tex";
+       %highlights = %highlights_tex;
+       $blankline = $blankline_tex;
+    } elsif ($cmd eq "-text") {
+       $output_mode = "text";
+       %highlights = %highlights_text;
+       $blankline = $blankline_text;
+    } elsif ($cmd eq "-docbook") {
+       $output_mode = "sgml";
+       %highlights = %highlights_sgml;
+       $blankline = $blankline_sgml;
+    } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
+       $modulename = shift @ARGV;
+    } elsif ($cmd eq "-function") { # to only output specific functions
+       $function_only = 1;
+       $function = shift @ARGV;
+       $function_table{$function} = 1;
+    } elsif ($cmd eq "-v") {
+       $verbose = 1;
+    } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
+       usage();
+    }
+}
+
+
+# generate a sequence of code that will splice in highlighting information
+# using the s// operator.
+$dohighlight = "";
+foreach $pattern (keys %highlights) {
+#    print "scanning pattern $pattern ($highlights{$pattern})\n";
+    $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
+}
+
+##
+# dumps section contents to arrays/hashes intended for that purpose.
+#
+sub dump_section {
+    my $name = shift @_;
+    my $contents = join "\n", @_;
+
+    if ($name =~ m/$type_constant/) {
+       $name = $1;
+#      print STDERR "constant section '$1' = '$contents'\n";
+       $constants{$name} = $contents;
+    } elsif ($name =~ m/$type_param/) {
+#      print STDERR "parameter def '$1' = '$contents'\n";
+       $name = $1;
+       $parameters{$name} = $contents;
+    } else {
+#      print STDERR "other section '$name' = '$contents'\n";
+       $sections{$name} = $contents;
+       push @sectionlist, $name;
+    }
+}
+
+##
+# output function
+#
+# parameters, a hash.
+#  function => "function name"
+#  parameterlist => @list of parameters
+#  parameters => %parameter descriptions
+#  sectionlist => @list of sections
+#  sections => %descriont descriptions
+#  
+
+sub output_highlight {
+    my $contents = join "\n", @_;
+    my $line;
+
+    eval $dohighlight;
+    foreach $line (split "\n", $contents) {
+       if ($line eq ""){
+           print $lineprefix, $blankline;
+       } else {
+           print $lineprefix, $line;
+       }
+       print "\n";
+    }
+}
+
+
+# output in html
+sub output_html {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+    my $count;
+    print "\n\n<a name=\"". $args{'function'} . "\">&nbsp</a><h2>Function</h2>\n";
+
+    print "<i>".$args{'functiontype'}."</i>\n";
+    print "<b>".$args{'function'}."</b>\n";
+    print "(";
+    $count = 0;
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "<i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n";
+       if ($count != $#{$args{'parameterlist'}}) {
+           $count++;
+           print ", ";
+       }
+    }
+    print ")\n";
+
+    print "<h3>Arguments</h3>\n";
+    print "<dl>\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "<dt><i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n";
+       print "<dd>";
+       output_highlight($args{'parameters'}{$parameter});
+    }
+    print "</dl>\n";
+    foreach $section (@{$args{'sectionlist'}}) {
+       print "<h3>$section</h3>\n";
+       print "<ul>\n";
+       output_highlight($args{'sections'}{$section});
+       print "</ul>\n";
+    }
+    print "<hr>\n";
+}
+
+# output in tex
+sub output_tex {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+    my $count;
+    my $func = $args{'function'};
+    my $param;
+    my $param2;
+    my $sec;
+    my $check;
+    my $type;
+
+    $func =~ s/_/\\_/g;
+
+    print "\n\n\\subsection{". $func . "}\n\\label{" . $args{'function'} . "}\n";
+
+    $type = $args{'functiontype'};
+    $type =~ s/_/\\_/g;
+
+    print "{\\it ".$type."}\n";
+    print "{\\bf ".$func."}\n";
+    print "(\n";
+    $count = 0;
+    foreach $parameter (@{$args{'parameterlist'}}) {
+        $param = $args{'parametertypes'}{$parameter};
+        $param2 = $parameter;
+       $param =~ s/_/\\_/g;
+        $param2 =~ s/_/\\_/g;
+
+       print "{\\it ".$param."} {\\bf ".$param2."}\n";
+       if ($count != $#{$args{'parameterlist'}}) {
+           $count++;
+           print ", ";
+       }
+    }
+    print ")\n";
+
+    print "\n{\\large{Arguments}}\n";
+
+    print "\\begin{itemize}\n";
+    $check=0;
+    foreach $parameter (@{$args{'parameterlist'}}) {
+        $param1 = $args{'parametertypes'}{$parameter};
+        $param1 =~ s/_/\\_/g;
+        $param2 = $parameter;
+       $param2 =~ s/_/\\_/g;
+
+       $check = 1;
+       print "\\item {\\it ".$param1."} {\\bf ".$param2."}: \n";
+#      print "\n";
+
+       $param3 = $args{'parameters'}{$parameter};
+       $param3 =~ s/_/\\_/g;
+       $param3 =~ s/&([a-zA-Z\_]+)/{\\it \1}/g;
+
+       output_highlight($param3);
+    }
+    if ($check==0) {
+       print "\\item void\n";
+    }
+    print "\\end{itemize}\n";
+
+    foreach $section (@{$args{'sectionlist'}}) {
+       $sec = $section;
+       $sec =~ s/_/\\_/g;
+       $sec =~ s/&([a-zA-Z\_]+)/{\\it \1}/g;
+
+       print "\n\\par{\\large{$sec}}\\par\n";
+       print "\\begin{rmfamily}\n";
+
+       $sec = $args{'sections'}{$section};
+       $sec =~ s/_/\\_/g;
+       $sec =~ s/\\:/:/g;
+       $sec =~ s/&([a-zA-Z\_]+)/{\\it \1}/g;
+       $sec =~ s/->/\$\\rightarrow\$/g;
+       $sec =~ s/([0-9]+)\^([0-9]+)/\$\{\1\}\^\{\2\}\$/g;
+
+       output_highlight($sec);
+       print "\\end{rmfamily}\n";
+    }
+    print "\n";
+}
+
+
+# output in sgml DocBook
+sub output_sgml {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+    my $count;
+    my $id;
+
+    $id = $args{'module'}."-".$args{'function'};
+    $id =~ s/[^A-Za-z0-9]/-/g;
+
+    print "<refentry>\n";
+    print "<refmeta>\n";
+    print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+    print "</refmeta>\n";
+    print "<refnamediv>\n";
+    print " <refname>".$args{'function'}."</refname>\n";
+    print " <refpurpose>\n";
+    print "  ".$args{'purpose'}."\n";
+    print " </refpurpose>\n";
+    print "</refnamediv>\n";
+
+    print "<refsynopsisdiv>\n";
+    print " <title>Synopsis</title>\n";
+    print "  <funcsynopsis>\n";
+    print "   <funcdef>".$args{'functiontype'}." ";
+    print "<function>".$args{'function'}." ";
+    print "</function></funcdef>\n";
+
+#    print "<refsect1>\n";
+#    print " <title>Synopsis</title>\n";
+#    print "  <funcsynopsis>\n";
+#    print "   <funcdef>".$args{'functiontype'}." ";
+#    print "<function>".$args{'function'}." ";
+#    print "</function></funcdef>\n";
+
+    $count = 0;
+    if ($#{$args{'parameterlist'}} >= 0) {
+       foreach $parameter (@{$args{'parameterlist'}}) {
+           print "   <paramdef>".$args{'parametertypes'}{$parameter};
+           print " <parameter>$parameter</parameter></paramdef>\n";
+       }
+    } else {
+       print "  <void>\n";
+    }
+    print "  </funcsynopsis>\n";
+    print "</refsynopsisdiv>\n";
+#    print "</refsect1>\n";
+
+    # print parameters
+    print "<refsect1>\n <title>Arguments</title>\n";
+#    print "<para>\nArguments\n";
+    if ($#{$args{'parameterlist'}} >= 0) {
+       print " <variablelist>\n";
+       foreach $parameter (@{$args{'parameterlist'}}) {
+           print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
+           print "   <listitem>\n    <para>\n";
+           $lineprefix="     ";
+           output_highlight($args{'parameters'}{$parameter});
+           print "    </para>\n   </listitem>\n  </varlistentry>\n";
+       }
+       print " </variablelist>\n";
+    } else {
+       print " <para>\n  None\n </para>\n";
+    }
+    print "</refsect1>\n";
+
+    # print out each section
+    $lineprefix="   ";
+    foreach $section (@{$args{'sectionlist'}}) {
+       print "<refsect1>\n <title>$section</title>\n <para>\n";
+#      print "<para>\n$section\n";
+       if ($section =~ m/EXAMPLE/i) {
+           print "<example><para>\n";
+       }
+       output_highlight($args{'sections'}{$section});
+#      print "</para>";
+       if ($section =~ m/EXAMPLE/i) {
+           print "</para></example>\n";
+       }
+       print " </para>\n</refsect1>\n";
+    }
+
+    print "\n\n";
+}
+
+##
+# output in man
+sub output_man {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+    my $count;
+
+    print ".TH \"$args{'module'}\" \"$args{'function'}\" \"25 May 1998\" \"API Manual\" GNOME\n";
+
+    print ".SH Function\n";
+
+    print ".I \"".$args{'functiontype'}."\"\n";
+    print ".B \"".$args{'function'}."\"\n";
+    print "(\n";
+    $count = 0;
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print ".I \"".$args{'parametertypes'}{$parameter}."\"\n.B \"".$parameter."\"\n";
+       if ($count != $#{$args{'parameterlist'}}) {
+           $count++;
+           print ",\n";
+       }
+    }
+    print ")\n";
+
+    print ".SH Arguments\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print ".IP \"".$args{'parametertypes'}{$parameter}." ".$parameter."\" 12\n";
+       output_highlight($args{'parameters'}{$parameter});
+    }
+    foreach $section (@{$args{'sectionlist'}}) {
+       print ".SH \"$section\"\n";
+       output_highlight($args{'sections'}{$section});
+    }
+}
+
+##
+# output in text
+sub output_text {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+
+    print "Function = ".$args{'function'}."\n";
+    print "  return type: ".$args{'functiontype'}."\n\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print " ".$args{'parametertypes'}{$parameter}." ".$parameter."\n";
+       print "    -> ".$args{'parameters'}{$parameter}."\n";
+    }
+    foreach $section (@{$args{'sectionlist'}}) {
+       print " $section:\n";
+       print "    -> ";
+       output_highlight($args{'sections'}{$section});
+    }
+}
+
+##
+# generic output function - calls the right one based
+# on current output mode.
+sub output_function {
+#    output_html(@_);
+    eval "output_".$output_mode."(\@_);";
+}
+
+
+##
+# takes a function prototype and spits out all the details
+# stored in the global arrays/hsahes.
+sub dump_function {
+    my $prototype = shift @_;
+
+    if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
+       $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
+       $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
+       $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/)  {
+       $return_type = $1;
+       $function_name = $2;
+       $args = $3;
+
+#      print STDERR "ARGS = '$args'\n";
+
+       foreach $arg (split ',', $args) {
+           # strip leading/trailing spaces
+           $arg =~ s/^\s*//;
+           $arg =~ s/\s*$//;
+#          print STDERR "SCAN ARG: '$arg'\n";
+           @args = split('\s', $arg);
+
+#          print STDERR " -> @args\n";
+           $param = pop @args;
+#          print STDERR " -> @args\n";
+           if ($param =~ m/^(\*+)(.*)/) {
+               $param = $2;
+               push @args, $1;
+           }
+           $type = join " ", @args;
+
+           if ($parameters{$param} eq "" && $param != "void") {
+               $parameters{$param} = "-- undescribed --";
+               print STDERR "Warning($lineno): Function parameter '$param' not described in '$function_name'\n";
+           }
+
+           push @parameterlist, $param;
+           $parametertypes{$param} = $type;
+
+#          print STDERR "param = '$param', type = '$type'\n";
+       }
+    } else {
+       print STDERR "Error($lineno): cannot understand prototype: '$prototype'\n";
+       return;
+    }
+
+    if ($function_only==0 || defined($function_table{$function_name})) {
+       output_function({'function' => $function_name,
+                        'module' => $modulename,
+                        'functiontype' => $return_type,
+                        'parameterlist' => \@parameterlist,
+                        'parameters' => \%parameters,
+                        'parametertypes' => \%parametertypes,
+                        'sectionlist' => \@sectionlist,
+                        'sections' => \%sections,
+                        'purpose' => $function_purpose
+                        });
+    }
+}
+
+######################################################################
+# main
+# states
+# 0 - normal code
+# 1 - looking for function name
+# 2 - scanning field start.
+# 3 - scanning prototype.
+$state = 0;
+$section = "";
+
+$doc_special = "\@\%\$\&";
+
+$doc_start = "^/\\*\\*\$";
+$doc_end = "\\*/";
+$doc_com = "\\s*\\*\\s*";
+$doc_func = $doc_com."(\\w+):?";
+$doc_sect = $doc_com."([".$doc_special."]?[\\w ]+):(.*)";
+$doc_content = $doc_com."(.*)";
+
+%constants = ();
+%parameters = ();
+@parameterlist = ();
+%sections = ();
+@sectionlist = ();
+
+$contents = "";
+$section_default = "Description";      # default section
+$section = $section_default;
+
+$lineno = 0;
+foreach $file (@ARGV) {
+    if (!open(IN,"<$file")) {
+       print STDERR "Error: Cannot open file $file\n";
+       next;
+    }
+    while (<IN>) {
+       $lineno++;
+
+       if ($state == 0) {
+           if (/$doc_start/o) {
+               $state = 1;             # next line is always the function name
+           }
+       } elsif ($state == 1) { # this line is the function name (always)
+           if (/$doc_func/o) {
+               $function = $1;
+               $state = 2;
+               if (/-(.*)/) {
+                   $function_purpose = $1;
+               } else {
+                   $function_purpose = "";
+               }
+               if ($verbose) {
+                   print STDERR "Info($lineno): Scanning doc for $function\n";
+               }
+           } else {
+               print STDERR "WARN($lineno): Cannot understand $_ on line $lineno",
+               " - I thought it was a doc line\n";
+               $state = 0;
+           }
+       } elsif ($state == 2) { # look for head: lines, and include content
+           if (/$doc_sect/o) {
+               $newsection = $1;
+               $newcontents = $2;
+
+               if ($contents ne "") {
+                   dump_section($section, $contents);
+                   $section = $section_default;
+               }
+
+               $contents = $newcontents;
+               if ($contents ne "") {
+                   $contents .= "\n";
+               }
+               $section = $newsection;
+           } elsif (/$doc_end/) {
+
+               if ($contents ne "") {
+                   dump_section($section, $contents);
+                   $section = $section_default;
+                   $contents = "";
+               }
+
+#          print STDERR "end of doc comment, looking for prototype\n";
+               $prototype = "";
+               $state = 3;
+           } elsif (/$doc_content/) {
+               # miguel-style comment kludge, look for blank lines after
+               # @parameter line to signify start of description
+               if ($1 eq "" && $section =~ m/^@/) {
+                   dump_section($section, $contents);
+                   $section = $section_default;
+                   $contents = "";
+               } else {
+                   $contents .= $1."\n";
+               }
+           } else {
+               # i dont know - bad line?  ignore.
+               print STDERR "WARNING($lineno): bad line: $_"; 
+           }
+       } elsif ($state == 3) { # scanning for function { (end of prototype)
+           if (m#\s*/\*\s+MACDOC\s*#io) {
+             # do nothing
+           }
+           elsif (/([^\{]*)/) {
+               $prototype .= $1;
+           }
+           if (/\{/) {
+               $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
+               $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
+               $prototype =~ s@^ +@@gos; # strip leading spaces
+               dump_function($prototype);
+
+               $function = "";
+               %constants = ();
+               %parameters = ();
+               %parametertypes = ();
+               @parameterlist = ();
+               %sections = ();
+               @sectionlist = ();
+               $prototype = "";
+
+               $state = 0;
+           }
+       }
+    }
+}
+
diff --git a/lib/ASN.c b/lib/ASN.c
new file mode 100644 (file)
index 0000000..8db7b46
--- /dev/null
+++ b/lib/ASN.c
@@ -0,0 +1,1997 @@
+/* A Bison parser, made from ASN.y
+   by GNU bison 1.32.  */
+
+#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 30 "ASN.y"
+#include <defines.h>
+#include <asn1.h>
+
+FILE *file_asn1;         /* Pointer to file to parse */
+extern int parse_mode;   /* PARSE_MODE_CHECK  = only syntax check
+                            PARSE_MODE_CREATE = structure creation */ 
+int result_parse;        /* result of the parser algorithm */
+node_asn *p_tree;        /* pointer to the root of the structure 
+                            created by the parser*/     
+
+int yyerror (char *);
+int yylex(void);
+
+
+#line 47 "ASN.y"
+#ifndef YYSTYPE
+typedef union {
+  unsigned int constant;
+  char str[129];
+  node_asn* node;
+} yystype;
+# define YYSTYPE yystype
+#endif
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+
+
+#define        YYFINAL         189
+#define        YYFLAG          -32768
+#define        YYNTBASE        50
+
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 293 ? yytranslate[x] : 93)
+
+/* 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,     1,     4,     6,     9,    12,    14,    16,    18,
+      20,    22,    24,    28,    33,    35,    39,    41,    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,   297,   303,   305,   307
+};
+static const short yyrhs[] =
+{
+      -1,    50,    92,     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,     5,
+       0,    58,     5,     0,    54,     0,     5,    42,     4,    43,
+       0,    59,     0,    60,    59,     0,    13,     0,    14,     0,
+      15,     0,    45,     4,    46,     0,    45,    61,     4,    46,
+       0,    62,     0,    62,    29,     0,    62,    30,     0,    16,
+      55,     0,    16,    22,     0,    16,    23,     0,     7,     0,
+       7,    47,    57,    48,     0,    65,    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,    68,     0,    42,    68,    43,     0,     9,    10,
+       0,     9,    10,    69,     0,     5,    42,     4,    43,     0,
+      71,     0,    72,    44,    71,     0,    12,    10,     0,    12,
+      10,    47,    72,    48,     0,    39,    47,    72,    48,     0,
+      19,    20,     0,     5,     0,     5,    69,     0,    65,     0,
+      74,     0,    66,     0,    67,     0,    70,     0,    73,     0,
+      81,     0,    75,     0,    83,     0,    84,     0,    82,     0,
+      24,     0,    76,     0,    63,    76,     0,    77,     0,    77,
+      64,     0,    77,     6,     0,     5,    78,     0,    79,     0,
+      80,    44,    79,     0,    11,    47,    80,    48,     0,    11,
+      18,    76,     0,    11,    69,    18,    76,     0,    28,    47,
+      80,    48,     0,    28,    18,    76,     0,    28,    69,    18,
+      76,     0,    17,    47,    80,    48,     0,    25,     0,    25,
+      26,    27,     5,     0,     5,     3,    77,     0,     5,    19,
+      20,     3,    47,    60,    48,     0,     5,     5,     3,    47,
+      60,    48,     0,     5,     7,     3,     4,     0,    85,     0,
+      86,     0,    87,     0,    88,    87,     0,     5,    47,    60,
+      48,     0,     5,    47,    48,     0,     0,    38,    58,    37,
+       5,    60,     0,    29,     0,    30,     0,    89,    31,    91,
+      32,     3,    33,    90,    88,    34,     0
+};
+
+#endif
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,   106,   107,   110,   111,   114,   118,   119,   122,   123,
+     126,   127,   130,   132,   137,   138,   142,   144,   150,   152,
+     157,   158,   162,   163,   164,   167,   169,   173,   174,   175,
+     178,   180,   181,   184,   185,   187,   194,   197,   198,   201,
+     203,   209,   210,   213,   214,   218,   223,   224,   228,   229,
+     234,   239,   242,   244,   247,   248,   249,   250,   251,   252,
+     253,   254,   255,   256,   257,   258,   261,   262,   267,   268,
+     271,   274,   277,   278,   282,   284,   286,   291,   293,   295,
+     300,   304,   305,   310,   313,   317,   322,   328,   329,   332,
+     333,   337,   340,   344,   345,   353,   354,   357
+};
+#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", "'+'", "'-'", "'('", "')'", "','", "'['", "']'", "'{'", 
+  "'}'", "'.'", "input", "pos_num", "neg_num", "pos_neg_num", 
+  "num_identifier", "pos_neg_identifier", "constant", "constant_list", 
+  "identifier_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", 
+  "imports_def", "explicit_implicit", "definitions", NULL
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    50,    50,    51,    51,    52,    53,    53,    54,    54,
+      55,    55,    56,    56,    57,    57,    58,    58,    59,    59,
+      60,    60,    61,    61,    61,    62,    62,    63,    63,    63,
+      64,    64,    64,    65,    65,    65,    66,    67,    67,    68,
+      68,    69,    69,    70,    70,    71,    72,    72,    73,    73,
+      74,    75,    76,    76,    76,    76,    76,    76,    76,    76,
+      76,    76,    76,    76,    76,    76,    77,    77,    78,    78,
+      78,    79,    80,    80,    81,    81,    81,    82,    82,    82,
+      83,    84,    84,    85,    86,    86,    86,    87,    87,    88,
+      88,    89,    89,    90,    90,    91,    91,    92
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     0,     2,     1,     2,     2,     1,     1,     1,     1,
+       1,     1,     3,     4,     1,     3,     1,     2,     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,     0,     5,     1,     1,     9
+};
+
+/* 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[] =
+{
+       1,     0,     0,     0,     2,     0,     0,     8,     9,    92,
+      18,    20,     0,    95,    96,     0,     0,    91,    21,     0,
+       0,     0,    19,    93,     0,     0,    16,     0,     0,    87,
+      88,    89,     0,    17,     0,     0,     0,     0,     0,    97,
+      90,     0,    52,    33,     0,     0,     0,     0,     0,    36,
+      65,    81,     0,    37,    38,     0,     0,    27,     0,    54,
+      56,    57,    58,    59,    55,    61,    66,    83,    60,    64,
+      62,    63,     0,     0,     0,     0,     0,     0,    41,    53,
+       0,    43,     0,     0,     0,    48,     0,    51,     0,     0,
+       0,     0,     0,     0,    22,    23,    24,     0,    28,    29,
+      67,     0,     0,    86,     0,     0,     0,     0,     0,    14,
+       0,    44,    75,     0,    72,     0,     0,     0,     0,     0,
+      78,     0,     0,     0,    46,     0,    25,     0,     9,     0,
+       0,     0,     0,    42,     0,     3,     0,     0,     6,     7,
+       0,     0,    34,    68,    71,     0,    74,    76,     0,    80,
+      82,    77,    79,     0,     0,    50,    26,     0,    85,     0,
+      39,     0,     0,     4,     5,    12,    15,    70,     0,    69,
+      73,    49,     0,    47,     0,    84,     0,    13,    11,    31,
+      32,    10,    30,    45,     0,     0,    35,    40,     0,     0
+};
+
+static const short yydefgoto[] =
+{
+       1,   138,   139,   140,    10,   182,   109,   110,    27,    11,
+      12,    97,    57,    58,   169,    59,    60,    61,    78,    79,
+      62,   124,   125,    63,    64,    65,    66,    67,   144,   114,
+     115,    68,    69,    70,    71,    29,    30,    31,    32,     3,
+      25,    15,     4
+};
+
+static const short yypact[] =
+{
+  -32768,    33,    -7,    28,-32768,     0,    -5,-32768,    22,-32768,
+  -32768,-32768,     3,-32768,-32768,    42,    62,-32768,-32768,    76,
+      45,    60,-32768,    85,   109,   127,-32768,     8,   108,-32768,
+  -32768,-32768,     9,-32768,   128,    11,   131,   132,   116,-32768,
+  -32768,    67,    18,    90,   129,    23,   130,    91,   121,-32768,
+  -32768,   117,    34,-32768,-32768,    95,   106,    87,    73,   102,
+  -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+  -32768,-32768,    98,   142,   145,    67,   107,   143,-32768,-32768,
+      12,    18,    73,   147,   135,   103,   147,-32768,   133,    73,
+     147,   136,   150,   110,-32768,-32768,-32768,   153,-32768,-32768,
+  -32768,   126,    67,-32768,   111,   126,   118,   120,    17,-32768,
+      51,-32768,-32768,    11,-32768,    52,    73,   150,    58,   154,
+  -32768,    59,    73,   122,-32768,    78,-32768,   119,-32768,   114,
+       5,    67,    40,-32768,    17,-32768,   162,   163,-32768,-32768,
+     125,    12,-32768,    13,-32768,   147,-32768,-32768,    80,-32768,
+  -32768,-32768,-32768,   165,   150,-32768,-32768,   123,-32768,     7,
+  -32768,   124,   134,-32768,-32768,-32768,-32768,-32768,    64,-32768,
+  -32768,-32768,   137,-32768,   126,-32768,   126,-32768,-32768,-32768,
+  -32768,-32768,-32768,-32768,   138,   139,-32768,-32768,   170,-32768
+};
+
+static const short yypgoto[] =
+{
+  -32768,-32768,-32768,  -119,   -99,-32768,    30,-32768,-32768,   -12,
+     -40,-32768,-32768,-32768,-32768,-32768,-32768,-32768,    97,    -8,
+  -32768,    21,    61,-32768,-32768,-32768,   -55,    63,-32768,    38,
+      39,-32768,-32768,-32768,-32768,-32768,-32768,   152,-32768,-32768,
+  -32768,-32768,-32768
+};
+
+
+#define        YYLAST          184
+
+
+static const short yytable[] =
+{
+      18,    75,   129,   100,     7,     8,   132,     7,     8,     7,
+       8,     7,     8,    33,    28,   162,    42,   107,    43,   167,
+      44,   135,    45,    46,    13,    14,    76,   112,    47,   168,
+      48,    76,    49,   188,   120,    50,    51,    84,     2,    52,
+       5,    82,    76,    39,    91,    34,    53,    54,     9,   181,
+      55,    17,    89,   158,   108,   175,    56,   136,   137,     6,
+      77,   147,   130,    18,    16,    77,    20,   152,   135,   178,
+      83,     7,     8,   111,    19,   184,    77,   185,    42,    21,
+      43,    90,    44,   160,    45,    46,   179,   180,    22,   161,
+      47,   159,    48,    23,    49,   141,   145,    50,    51,   142,
+     146,    52,   145,   145,   136,   137,   149,   151,    53,    54,
+      93,    35,    55,    36,    26,    37,    98,    99,    18,    94,
+      95,    96,   154,    24,   154,   118,   155,    38,   171,   121,
+       7,   128,    28,    41,    72,    73,    74,    80,    86,    81,
+      85,    87,    92,    88,   101,   102,   103,    18,   104,   105,
+     117,    76,   113,   116,   122,   123,   126,   127,   131,   150,
+     119,   133,   134,   157,   153,   156,   163,   164,   165,   172,
+     189,   166,   174,   176,   106,   173,   143,   177,   148,     0,
+     183,   186,   187,   170,    40
+};
+
+static const short yycheck[] =
+{
+      12,    41,   101,    58,     4,     5,   105,     4,     5,     4,
+       5,     4,     5,     5,     5,   134,     5,     5,     7,     6,
+       9,     4,    11,    12,    29,    30,     8,    82,    17,    16,
+      19,     8,    21,     0,    89,    24,    25,    45,     5,    28,
+      47,    18,     8,    34,    52,    37,    35,    36,    48,   168,
+      39,    48,    18,    48,    42,    48,    45,    40,    41,    31,
+      42,   116,   102,    75,    42,    42,     4,   122,     4,     5,
+      47,     4,     5,    81,    32,   174,    42,   176,     5,     3,
+       7,    47,     9,    43,    11,    12,    22,    23,    43,    49,
+      17,   131,    19,    33,    21,    44,    44,    24,    25,    48,
+      48,    28,    44,    44,    40,    41,    48,    48,    35,    36,
+       4,     3,    39,     5,     5,     7,    29,    30,   130,    13,
+      14,    15,    44,    38,    44,    86,    48,    19,    48,    90,
+       4,     5,     5,     5,     3,     3,    20,    47,    47,    10,
+      10,    20,    47,    26,    42,    47,     4,   159,     3,    42,
+      47,     8,     5,    18,    18,     5,    46,     4,    47,     5,
+      27,    43,    42,    49,    42,    46,     4,     4,    43,     4,
+       0,   141,    49,    49,    77,   154,   113,    43,   117,    -1,
+      43,    43,    43,   145,    32
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/share/bison/bison.simple"
+
+/* Skeleton output parser for bison,
+   Copyright (C) 1984, 1989, 1990, 2000, 2001 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
+#  define YYSIZE_T YYSTD (size_t)
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#    define YYSIZE_T YYSTD (size_t)
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  ifdef __cplusplus
+#   include <cstdlib> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T std::size_t
+#  else
+#   ifdef __STDC__
+#    include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#    define YYSIZE_T size_t
+#   endif
+#  endif
+#  define YYSTACK_ALLOC YYSTD (malloc)
+#  define YYSTACK_FREE YYSTD (free)
+# endif
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))     \
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Relocate the TYPE STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Type, Stack)                                 \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       yymemcpy ((char *) yyptr, (char *) (Stack),                     \
+                 yysize * (YYSIZE_T) sizeof (Type));                   \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (Type) + YYSTACK_GAP_MAX;     \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# ifdef __cplusplus
+#  include <cstddef> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T std::size_t
+# else
+#  ifdef __STDC__
+#   include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT        goto yyabortlab
+#define YYERROR                goto yyerrlab1
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL         goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");                        \
+      YYERROR;                                                 \
+    }                                                          \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
+
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)               \
+   Current.last_line   = Rhs[N].last_line;     \
+   Current.last_column = Rhs[N].last_column;
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX                 yylex ()
+#endif /* !YYPURE */
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  ifdef __cplusplus
+#   include <cstdio>  /* INFRINGES ON USER NAME SPACE */
+#  else
+#   include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  endif
+#  define YYFPRINTF YYSTD (fprintf)
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+/* Nonzero means print parse trace. [The following comment makes no
+   sense to me.  Could someone clarify it?  --akim] Since this is
+   uninitialized, it does not stop multiple parsers from coexisting.
+   */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+\f
+#if ! defined (yyoverflow) && ! defined (yymemcpy)
+# if __GNUC__ > 1              /* GNU C and GNU C++ define this.  */
+#  define yymemcpy __builtin_memcpy
+# else                         /* not GNU C or C++ */
+
+/* This is the most reliable way to avoid incompatibilities
+   in available built-in functions on various systems.  */
+static void
+#  if defined (__STDC__) || defined (__cplusplus)
+yymemcpy (char *yyto, const char *yyfrom, YYSIZE_T yycount)
+#  else
+yymemcpy (yyto, yyfrom, yycount)
+     char *yyto;
+     const char *yyfrom;
+     YYSIZE_T yycount;
+#  endif
+{
+  register const char *yyf = yyfrom;
+  register char *yyt = yyto;
+  register YYSIZE_T yyi = yycount;
+
+  while (yyi-- != 0)
+    *yyt++ = *yyf++;
+}
+# endif
+#endif
+
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+#endif
+\f
+#line 341 "/usr/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 3:
+#line 110 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 4:
+#line 111 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 5:
+#line 114 "ASN.y"
+{strcpy(yyval.str,"-");
+                       strcat(yyval.str,yyvsp[0].str);}
+    break;
+case 6:
+#line 118 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 7:
+#line 119 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 8:
+#line 122 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 9:
+#line 123 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 10:
+#line 126 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 11:
+#line 127 "ASN.y"
+{strcpy(yyval.str,yyvsp[0].str);}
+    break;
+case 12:
+#line 130 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_CONSTANT); 
+                                       _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 13:
+#line 132 "ASN.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 14:
+#line 137 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 15:
+#line 138 "ASN.y"
+{yyval.node=yyvsp[-2].node;
+                                            _asn1_set_right(_asn1_get_last_right(yyvsp[-2].node),yyvsp[0].node);}
+    break;
+case 16:
+#line 142 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_IDENTIFIER);
+                                 _asn1_set_name(yyval.node,yyvsp[0].str);}
+    break;
+case 17:
+#line 145 "ASN.y"
+{yyval.node=yyvsp[-1].node;
+                                 _asn1_set_right(_asn1_get_last_right(yyval.node),_asn1_add_node(TYPE_IDENTIFIER));
+                                 _asn1_set_name(_asn1_get_last_right(yyval.node),yyvsp[0].str);}
+    break;
+case 18:
+#line 150 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_CONSTANT); 
+                                   _asn1_set_value(yyval.node,yyvsp[0].str,strlen(yyvsp[0].str)+1);}
+    break;
+case 19:
+#line 152 "ASN.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 20:
+#line 157 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 21:
+#line 158 "ASN.y"
+{yyval.node=yyvsp[-1].node;
+                                                    _asn1_set_right(_asn1_get_last_right(yyvsp[-1].node),yyvsp[0].node);}
+    break;
+case 22:
+#line 162 "ASN.y"
+{yyval.constant=CONST_UNIVERSAL;}
+    break;
+case 23:
+#line 163 "ASN.y"
+{yyval.constant=CONST_PRIVATE;}
+    break;
+case 24:
+#line 164 "ASN.y"
+{yyval.constant=CONST_APPLICATION;}
+    break;
+case 25:
+#line 167 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_TAG); 
+                            _asn1_set_value(yyval.node,yyvsp[-1].str,strlen(yyvsp[-1].str)+1);}
+    break;
+case 26:
+#line 169 "ASN.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 27:
+#line 173 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 28:
+#line 174 "ASN.y"
+{yyval.node=_asn1_mod_type(yyvsp[-1].node,CONST_EXPLICIT);}
+    break;
+case 29:
+#line 175 "ASN.y"
+{yyval.node=_asn1_mod_type(yyvsp[-1].node,CONST_IMPLICIT);}
+    break;
+case 30:
+#line 178 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_DEFAULT); 
+                                       _asn1_set_value(yyval.node,yyvsp[0].str,strlen(yyvsp[0].str)+1);}
+    break;
+case 31:
+#line 180 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);}
+    break;
+case 32:
+#line 181 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);}
+    break;
+case 33:
+#line 184 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_INTEGER);}
+    break;
+case 34:
+#line 185 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_INTEGER|CONST_LIST);
+                                        _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 35:
+#line 188 "ASN.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 36:
+#line 194 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_BOOLEAN);}
+    break;
+case 37:
+#line 197 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_TIME|CONST_UTC);}
+    break;
+case 38:
+#line 198 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);}
+    break;
+case 39:
+#line 201 "ASN.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 40:
+#line 204 "ASN.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 41:
+#line 209 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 42:
+#line 210 "ASN.y"
+{yyval.node=yyvsp[-1].node;}
+    break;
+case 43:
+#line 213 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_OCTET_STRING);}
+    break;
+case 44:
+#line 214 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE);
+                                           _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 45:
+#line 218 "ASN.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 46:
+#line 223 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 47:
+#line 224 "ASN.y"
+{yyval.node=yyvsp[-2].node;
+                                                       _asn1_set_right(_asn1_get_last_right(yyvsp[-2].node),yyvsp[0].node);}
+    break;
+case 48:
+#line 228 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_BIT_STRING);}
+    break;
+case 49:
+#line 230 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST);
+                                _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 50:
+#line 235 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST);
+                                _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 51:
+#line 239 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_OBJECT_ID);}
+    break;
+case 52:
+#line 242 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_IDENTIFIER);
+                                       _asn1_set_value(yyval.node,yyvsp[0].str,strlen(yyvsp[0].str)+1);}
+    break;
+case 53:
+#line 244 "ASN.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 54:
+#line 247 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 55:
+#line 248 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 56:
+#line 249 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 58:
+#line 251 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 59:
+#line 252 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 60:
+#line 253 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 61:
+#line 254 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 62:
+#line 255 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 63:
+#line 256 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 64:
+#line 257 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 65:
+#line 258 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_NULL);}
+    break;
+case 66:
+#line 261 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 67:
+#line 262 "ASN.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 68:
+#line 267 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 69:
+#line 268 "ASN.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 70:
+#line 271 "ASN.y"
+{yyval.node=_asn1_mod_type(yyvsp[-1].node,CONST_OPTION);}
+    break;
+case 71:
+#line 274 "ASN.y"
+{yyval.node=_asn1_set_name(yyvsp[0].node,yyvsp[-1].str);}
+    break;
+case 72:
+#line 277 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 73:
+#line 278 "ASN.y"
+{yyval.node=yyvsp[-2].node;
+                                                _asn1_set_right(_asn1_get_last_right(yyvsp[-2].node),yyvsp[0].node);}
+    break;
+case 74:
+#line 282 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_SEQUENCE);
+                                              _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 75:
+#line 284 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_SEQUENCE_OF);
+                                              _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 76:
+#line 286 "ASN.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 77:
+#line 291 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_SET);
+                                     _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 78:
+#line 293 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_SET_OF);
+                                     _asn1_set_down(yyval.node,yyvsp[0].node);}
+    break;
+case 79:
+#line 295 "ASN.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 80:
+#line 300 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_CHOICE);
+                                             _asn1_set_down(yyval.node,yyvsp[-1].node);}
+    break;
+case 81:
+#line 304 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_ANY);}
+    break;
+case 82:
+#line 305 "ASN.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 83:
+#line 310 "ASN.y"
+{yyval.node=_asn1_set_name(yyvsp[0].node,yyvsp[-2].str);}
+    break;
+case 84:
+#line 314 "ASN.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 85:
+#line 318 "ASN.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 86:
+#line 323 "ASN.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 87:
+#line 328 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 88:
+#line 329 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 89:
+#line 332 "ASN.y"
+{yyval.node=yyvsp[0].node;}
+    break;
+case 90:
+#line 333 "ASN.y"
+{yyval.node=yyvsp[-1].node;
+                                                          _asn1_set_right(_asn1_get_last_right(yyvsp[-1].node),yyvsp[0].node);}
+    break;
+case 91:
+#line 337 "ASN.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 92:
+#line 340 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_OBJECT_ID);
+                                                          _asn1_set_name(yyval.node,yyvsp[-2].str);}
+    break;
+case 93:
+#line 344 "ASN.y"
+{yyval.node=NULL;}
+    break;
+case 94:
+#line 346 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_IMPORTS);
+                         _asn1_set_down(yyval.node,_asn1_add_node(TYPE_OBJECT_ID));
+                         _asn1_set_name(_asn1_get_down(yyval.node),yyvsp[-1].str);  
+                         _asn1_set_down(_asn1_get_down(yyval.node),yyvsp[0].node);
+                         _asn1_set_right(yyval.node,yyvsp[-3].node);}
+    break;
+case 95:
+#line 353 "ASN.y"
+{yyval.constant=CONST_EXPLICIT;}
+    break;
+case 96:
+#line 354 "ASN.y"
+{yyval.constant=CONST_IMPLICIT;}
+    break;
+case 97:
+#line 360 "ASN.y"
+{yyval.node=_asn1_add_node(TYPE_DEFINITIONS|yyvsp[-6].constant|((yyvsp[-2].node==NULL)?0:CONST_IMPORTS));
+                    _asn1_set_name(yyval.node,_asn1_get_name(yyvsp[-8].node));
+                    _asn1_set_name(yyvsp[-8].node,"");
+                    if(yyvsp[-2].node==NULL) _asn1_set_right(yyvsp[-8].node,yyvsp[-1].node);
+                    else {_asn1_set_right(yyvsp[-2].node,yyvsp[-1].node);_asn1_set_right(yyvsp[-8].node,yyvsp[-2].node);}
+                    _asn1_set_down(yyval.node,yyvsp[-8].node);
+                   if(parse_mode==PARSE_MODE_CREATE){
+                     _asn1_set_default_tag(yyval.node);
+                     _asn1_type_set_config(yyval.node);
+                     result_parse=_asn1_check_identifier(yyval.node);
+                     if(result_parse==ASN_IDENTIFIER_NOT_FOUND)
+                       asn1_delete_structure(yyval.node);
+                     else p_tree=yyval.node;
+                   }}
+    break;
+}
+
+#line 727 "/usr/share/bison/bison.simple"
+
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#if YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
+#endif
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+       {
+         YYSIZE_T yysize = 0;
+         char *yymsg;
+         int yyx, yycount;
+
+         yycount = 0;
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         for (yyx = yyn < 0 ? -yyn : 0;
+              yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+           if (yycheck[yyx + yyn] == yyx)
+             yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+         yysize += yystrlen ("parse error, unexpected ") + 1;
+         yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
+           {
+             char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
+
+             if (yycount < 5)
+               {
+                 yycount = 0;
+                 for (yyx = yyn < 0 ? -yyn : 0;
+                      yyx < (int) (sizeof (yytname) / sizeof (char *));
+                      yyx++)
+                   if (yycheck[yyx + yyn] == yyx)
+                     {
+                       const char *yyq = ! yycount ? ", expecting " : " or ";
+                       yyp = yystpcpy (yyp, yyq);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yycount++;
+                     }
+               }
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exhausted");
+       }
+      else
+#endif /* defined (YYERROR_VERBOSE) */
+       yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+       YYABORT;
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+                 yychar, yytname[yychar1]));
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;             /* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
+#endif
+
+
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#if YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
+yyerrhandle:
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+#line 376 "ASN.y"
+
+
+
+#include <ctype.h>
+#include <string.h>
+
+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[129]; /* will contain the next token */  
+  while(1)
+    {
+    while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n');
+    if(c==EOF) return 0;
+    if(c=='(' || c==')' || c=='[' || c==']' || 
+       c=='{' || c=='}' || c==',' || c=='.' ||
+       c=='+') return c;
+    if(c=='-'){  /* Maybe the first '-' of a comment */
+      if((c=fgetc(file_asn1))!='-'){
+       ungetc(c,file_asn1);
+       return '-';
+      }
+      else{ /* Comments */
+       counter=0;
+       /* A comment finishes at the end of line */
+       while((c=fgetc(file_asn1))!=EOF && c!='\n');
+       if(c==EOF) return 0;
+       else 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=='.'))
+      { 
+      string[counter++]=c;
+      }
+    ungetc(c,file_asn1);
+    string[counter]=0;
+
+    /* Is STRING a number? */
+    for(k=0;k<counter;k++) 
+      if(!isdigit(string[k])) break;
+    if(k>=counter)
+      {
+      strcpy(yylval.str,string);  
+      return NUM; /* return the number */
+      }
+    /* Is STRING a keyword? */
+    for(k=0;k<(sizeof(key_word)/sizeof(char*));k++)  
+      if(!strcmp(string,key_word[k])) return key_word_token[k]; 
+    /* STRING is an IDENTIFIER */
+    strcpy(yylval.str,string);
+    return IDENTIFIER;
+    }
+}
+
+
+/**
+  * asn1_parser_asn1 - function used to start the parse algorithm.
+  * @file_name: specify the path and the name of file that contains ASN.1 declarations.
+  * @pointer: return the pointer to the structure created from 
+  *   "file_name" ASN.1 declarations.  
+  * Description:
+  *
+  * Creates the structures needed to manage the definitions included in *FILE_NAME file.
+  *
+  * Returns:
+  *
+  * ASN_OK\: the file has a correct syntax and every identifier is known. 
+  *
+  * ASN_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  * ASN_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  * ASN_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  **/
+int asn1_parser_asn1(char *file_name,node_asn **pointer){
+  p_tree=NULL;
+  *pointer=NULL;
+  
+  /* open the file to parse */
+  file_asn1=fopen(file_name,"r");
+  if(file_asn1==NULL) return ASN_FILE_NOT_FOUND;
+
+  result_parse=ASN_OK;
+
+  /* only syntax check */
+  parse_mode=PARSE_MODE_CHECK;
+  yyparse();
+
+  if(result_parse==ASN_OK){ /* syntax OK */
+    fclose(file_asn1);
+    file_asn1=fopen(file_name,"r");
+
+    /* structure creation */
+    parse_mode=PARSE_MODE_CREATE;
+    yyparse();
+
+    _asn1_change_integer_value(p_tree);
+    _asn1_expand_object_id(p_tree);
+  }
+
+  fclose(file_asn1);
+
+  parse_mode=PARSE_MODE_CREATE;
+
+  *pointer=p_tree;
+
+  return result_parse;
+}
+
+
+/**
+  * asn1_parser_asn1_file_c - function that generates a C structure from an ASN1 file
+  * @file_name: specify the path and the name of file that contains ASN.1 declarations.
+  * Description:
+  *
+  * Creates a file containing a C vector to use to manage the definitions included in
+  * *FILE_NAME file. If *FILE_NAME is "/aa/bb/xx.yy" the file created is "/aa/bb/xx_asn1_tab.c",
+  * and the vector is "xx_asn1_tab".
+  *
+  * Returns:
+  *
+  *  ASN_OK\: the file has a correct syntax and every identifier is known. 
+  *
+  *  ASN_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  *  ASN_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  *  ASN_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  **/
+int asn1_parser_asn1_file_c(char *file_name){
+  int result;
+
+  p_tree=NULL;
+    
+  /* open the file to parse */
+  file_asn1=fopen(file_name,"r");
+  if(file_asn1==NULL) return ASN_FILE_NOT_FOUND;
+
+  result_parse=ASN_OK;
+
+  /* syntax check */
+  parse_mode=PARSE_MODE_CHECK;
+  yyparse();
+
+  if(result_parse==ASN_OK){ /* syntax OK */
+    fclose(file_asn1);
+    file_asn1=fopen(file_name,"r");
+
+    /* structure creation */
+    parse_mode=PARSE_MODE_CREATE;
+    yyparse();
+
+    /* structure saved in a file */
+    result=_asn1_create_static_structure(p_tree,file_name,NULL);
+
+    /* delete structure in memory */
+    asn1_delete_structure(p_tree);
+   }
+
+  fclose(file_asn1);
+
+  parse_mode=PARSE_MODE_CREATE;
+
+  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 */
+  /*  printf("%s\n",s); */
+  result_parse=ASN_SYNTAX_ERROR;
+  return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ASN.y b/lib/ASN.y
new file mode 100644 (file)
index 0000000..00ce4cf
--- /dev/null
+++ b/lib/ASN.y
@@ -0,0 +1,600 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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
+ */
+
+
+/*****************************************************/
+/* File: x509_ASN.y                                  */
+/* Description: input file for 'bison' program.      */
+/*   The output file is a parser (in C language) for */
+/*   ASN.1 syntax                                    */
+/*****************************************************/
+
+%{ 
+#include <defines.h>
+#include <asn1.h>
+
+FILE *file_asn1;         /* Pointer to file to parse */
+extern int parse_mode;   /* PARSE_MODE_CHECK  = only syntax check
+                            PARSE_MODE_CREATE = structure creation */ 
+int result_parse;        /* result of the parser algorithm */
+node_asn *p_tree;        /* pointer to the root of the structure 
+                            created by the parser*/     
+
+int yyerror (char *);
+int yylex(void);
+
+%}
+
+
+%union {
+  unsigned int constant;
+  char str[129];
+  node_asn* node;
+}
+
+
+%token ASSIG "::=" 
+%token <str> NUM
+%token <str> IDENTIFIER
+%token OPTIONAL
+%token INTEGER
+%token SIZE
+%token OCTET
+%token STRING
+%token SEQUENCE
+%token BIT
+%token UNIVERSAL
+%token PRIVATE
+%token APPLICATION
+%token OPTIONAL
+%token DEFAULT
+%token CHOICE
+%token OF
+%token OBJECT
+%token STR_IDENTIFIER
+%token BOOLEAN
+%token TRUE
+%token FALSE
+%token TOKEN_NULL
+%token ANY
+%token DEFINED
+%token BY
+%token SET
+%token EXPLICIT
+%token IMPLICIT
+%token DEFINITIONS
+%token TAGS
+%token BEGIN
+%token END
+%token UTCTime 
+%token GeneralizedTime
+%token FROM
+%token IMPORTS
+%token ENUMERATED
+
+%type <node> octet_string_def constant constant_list type_assig_right 
+%type <node> integer_def type_assig type_assig_list sequence_def type_def
+%type <node> bit_string_def default size_def choise_def object_def 
+%type <node> boolean_def any_def size_def2 obj_constant obj_constant_list
+%type <node> constant_def type_constant type_constant_list definitions
+%type <node> definitions_id Time bit_element bit_element_list set_def
+%type <node> identifier_list imports_def tag_type tag type_assig_right_tag
+%type <node> type_assig_right_tag_default enumerated_def
+%type <str>  pos_num neg_num pos_neg_num pos_neg_identifier num_identifier 
+%type <constant> class explicit_implicit
+
+%%
+
+input:  /* empty */  
+       | input definitions
+;
+
+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);}
+;
+
+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);}
+;
+
+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 "::=" 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);}
+;
+
+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;}
+;
+
+definitions:   definitions_id
+               DEFINITIONS explicit_implicit TAGS "::=" BEGIN imports_def 
+               type_constant_list END
+                   {$$=_asn1_add_node(TYPE_DEFINITIONS|$3|(($7==NULL)?0:CONST_IMPORTS));
+                    _asn1_set_name($$,_asn1_get_name($1));
+                    _asn1_set_name($1,"");
+                    if($7==NULL) _asn1_set_right($1,$8);
+                    else {_asn1_set_right($7,$8);_asn1_set_right($1,$7);}
+                    _asn1_set_down($$,$1);
+                   if(parse_mode==PARSE_MODE_CREATE){
+                     _asn1_set_default_tag($$);
+                     _asn1_type_set_config($$);
+                     result_parse=_asn1_check_identifier($$);
+                     if(result_parse==ASN_IDENTIFIER_NOT_FOUND)
+                       asn1_delete_structure($$);
+                     else p_tree=$$;
+                   }}
+;
+
+%%
+
+
+#include <ctype.h>
+#include <string.h>
+
+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[129]; /* will contain the next token */  
+  while(1)
+    {
+    while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n');
+    if(c==EOF) return 0;
+    if(c=='(' || c==')' || c=='[' || c==']' || 
+       c=='{' || c=='}' || c==',' || c=='.' ||
+       c=='+') return c;
+    if(c=='-'){  /* Maybe the first '-' of a comment */
+      if((c=fgetc(file_asn1))!='-'){
+       ungetc(c,file_asn1);
+       return '-';
+      }
+      else{ /* Comments */
+       counter=0;
+       /* A comment finishes at the end of line */
+       while((c=fgetc(file_asn1))!=EOF && c!='\n');
+       if(c==EOF) return 0;
+       else 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=='.'))
+      { 
+      string[counter++]=c;
+      }
+    ungetc(c,file_asn1);
+    string[counter]=0;
+
+    /* Is STRING a number? */
+    for(k=0;k<counter;k++) 
+      if(!isdigit(string[k])) break;
+    if(k>=counter)
+      {
+      strcpy(yylval.str,string);  
+      return NUM; /* return the number */
+      }
+    /* Is STRING a keyword? */
+    for(k=0;k<(sizeof(key_word)/sizeof(char*));k++)  
+      if(!strcmp(string,key_word[k])) return key_word_token[k]; 
+    /* STRING is an IDENTIFIER */
+    strcpy(yylval.str,string);
+    return IDENTIFIER;
+    }
+}
+
+
+/**
+  * asn1_parser_asn1 - function used to start the parse algorithm.
+  * @file_name: specify the path and the name of file that contains ASN.1 declarations.
+  * @pointer: return the pointer to the structure created from 
+  *   "file_name" ASN.1 declarations.  
+  * Description:
+  *
+  * Creates the structures needed to manage the definitions included in *FILE_NAME file.
+  *
+  * Returns:
+  *
+  * ASN_OK\: the file has a correct syntax and every identifier is known. 
+  *
+  * ASN_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  * ASN_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  * ASN_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  **/
+int asn1_parser_asn1(char *file_name,node_asn **pointer){
+  p_tree=NULL;
+  *pointer=NULL;
+  
+  /* open the file to parse */
+  file_asn1=fopen(file_name,"r");
+  if(file_asn1==NULL) return ASN_FILE_NOT_FOUND;
+
+  result_parse=ASN_OK;
+
+  /* only syntax check */
+  parse_mode=PARSE_MODE_CHECK;
+  yyparse();
+
+  if(result_parse==ASN_OK){ /* syntax OK */
+    fclose(file_asn1);
+    file_asn1=fopen(file_name,"r");
+
+    /* structure creation */
+    parse_mode=PARSE_MODE_CREATE;
+    yyparse();
+
+    _asn1_change_integer_value(p_tree);
+    _asn1_expand_object_id(p_tree);
+  }
+
+  fclose(file_asn1);
+
+  parse_mode=PARSE_MODE_CREATE;
+
+  *pointer=p_tree;
+
+  return result_parse;
+}
+
+
+/**
+  * asn1_parser_asn1_file_c - function that generates a C structure from an ASN1 file
+  * @file_name: specify the path and the name of file that contains ASN.1 declarations.
+  * Description:
+  *
+  * Creates a file containing a C vector to use to manage the definitions included in
+  * *FILE_NAME file. If *FILE_NAME is "/aa/bb/xx.yy" the file created is "/aa/bb/xx_asn1_tab.c",
+  * and the vector is "xx_asn1_tab".
+  *
+  * Returns:
+  *
+  *  ASN_OK\: the file has a correct syntax and every identifier is known. 
+  *
+  *  ASN_FILE_NOT_FOUND\: an error occured while opening FILE_NAME.
+  *
+  *  ASN_SYNTAX_ERROR\: the syntax is not correct.
+  *
+  *  ASN_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined.
+  **/
+int asn1_parser_asn1_file_c(char *file_name){
+  int result;
+
+  p_tree=NULL;
+    
+  /* open the file to parse */
+  file_asn1=fopen(file_name,"r");
+  if(file_asn1==NULL) return ASN_FILE_NOT_FOUND;
+
+  result_parse=ASN_OK;
+
+  /* syntax check */
+  parse_mode=PARSE_MODE_CHECK;
+  yyparse();
+
+  if(result_parse==ASN_OK){ /* syntax OK */
+    fclose(file_asn1);
+    file_asn1=fopen(file_name,"r");
+
+    /* structure creation */
+    parse_mode=PARSE_MODE_CREATE;
+    yyparse();
+
+    /* structure saved in a file */
+    result=_asn1_create_static_structure(p_tree,file_name,NULL);
+
+    /* delete structure in memory */
+    asn1_delete_structure(p_tree);
+   }
+
+  fclose(file_asn1);
+
+  parse_mode=PARSE_MODE_CREATE;
+
+  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 */
+  /*  printf("%s\n",s); */
+  result_parse=ASN_SYNTAX_ERROR;
+  return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644 (file)
index 0000000..5ca829d
--- /dev/null
@@ -0,0 +1,22 @@
+include_HEADERS = asn1.h 
+
+EXTRA_DIST = asn1.h der.h asn1-api.tex mem.h gstr.h
+
+lib_LTLIBRARIES = libasn1.la
+
+# Separate so we can create the documentation
+COBJECTS = ASN.y asn1.c der.c gstr.c
+
+libasn1_la_SOURCES = $(COBJECTS) 
+
+libasn1_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+
+asn1-api.tex: $(COBJECTS)
+       @echo "\\newpage" > asn1-api.tex
+       @echo "\\section{ASN.1 parser function reference}" >> asn1-api.tex
+       @for i in $(COBJECTS); \
+       do echo -n "Creating documentation for file $$i... " && ../doc/scripts/gdoc -tex $$i >> asn1-api.tex \
+       && echo "ok"; \
+       done
+
+all-local: asn1-api.tex
diff --git a/lib/asn1.c b/lib/asn1.c
new file mode 100644 (file)
index 0000000..5221955
--- /dev/null
@@ -0,0 +1,1954 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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
+ */
+
+
+/*****************************************************/
+/* File: x509_asn1.c                                 */
+/* Description: Functions to manage ASN.1 DEFINITIONS*/
+/*****************************************************/
+
+
+#include <defines.h>
+#include "asn1.h" 
+#include "der.h"
+#include <gstr.h>
+
+/* define used for visiting trees */
+#define UP     1
+#define RIGHT  2
+#define DOWN   3
+
+
+int parse_mode;  /* PARSE_MODE_CHECK  = only syntax check
+                    PARSE_MODE_CREATE = structure creation */
+
+
+/******************************************************/
+/* Function : _asn1_add_node                          */
+/* 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(unsigned int type)
+{
+  node_asn *punt;
+
+  if(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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_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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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(parse_mode==PARSE_MODE_CHECK) return NULL;
+
+  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_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_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;  
+}
+
+/******************************************************************/
+/* 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_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: ASN_MEM_ERROR or ASN_OK                                */
+/******************************************************************/
+int
+_asn1_convert_integer(char *value,unsigned char *value_out,int value_out_size, int *len)
+{
+  char negative;
+  unsigned char val[4],temp;
+  int k,k2;
+
+  *((long*)val)=strtol(value,NULL,10);
+  for(k=0;k<2;k++){
+    temp=val[k];
+    val[k]=val[3-k];
+    val[3-k]=temp;
+  }
+       
+  if(val[0]&0x80) negative=1;
+  else negative=0;
+  
+  for(k=0;k<3;k++){
+    if(negative && (val[k]!=0xFF)) break;
+    else if(!negative && val[k]) break;
+  }
+       
+  if((negative && !(val[k]&0x80)) ||
+     (!negative && (val[k]&0x80))) k--; 
+
+  for(k2=k;k2<4;k2++) {
+    if (k2-k > value_out_size-1) {
+       return ASN_MEM_ERROR;
+    }
+    /* VALUE_OUT is too short to contain the value convertion */
+    value_out[k2-k]=val[k2];
+  }
+  *len=4-k;
+
+  return ASN_OK;
+}
+
+/**
+  * asn1_create_tree - Creates the structures needed to manage the ASN1 definitions.
+  * @root: specify vector that contains ASN.1 declarations
+  * @pointer: return the pointer to the structure created by *ROOT ASN.1 declarations
+  * Description:
+  *
+  * Creates the structures needed to manage the ASN1 definitions. ROOT is a vector created by
+  * 'asn1_parser_asn1_file_c' function.
+  *
+  * Returns:
+  *
+  *  ASN_OK\: structure created correctly. 
+  *
+  *  ASN_GENERIC_ERROR\: an error occured while structure creation  
+  **/
+int
+asn1_create_tree(const static_asn *root,node_asn **pointer)
+{
+  node_asn *p,*p_last;
+  unsigned long k;
+  int move;
+
+  *pointer=NULL;
+  move=UP;
+
+  k=0;
+  while(root[k].value || root[k].type || root[k].name){
+    p=_asn1_add_node(root[k].type&(~CONST_DOWN));
+    if(root[k].name) _asn1_set_name(p,root[k].name);
+    if(root[k].value) _asn1_set_value(p,root[k].value,strlen(root[k].value)+1);
+
+    if(*pointer==NULL) *pointer=p;
+
+    if(move==DOWN) _asn1_set_down(p_last,p);
+    else if(move==RIGHT) _asn1_set_right(p_last,p);
+
+    p_last=p;
+
+    if(root[k].type&CONST_DOWN) move=DOWN;
+    else if(root[k].type&CONST_RIGHT) move=RIGHT;
+    else{
+      while(1){
+       if(p_last==*pointer) 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==*pointer){
+    _asn1_change_integer_value(*pointer);
+    _asn1_expand_object_id(*pointer);
+  }
+  else asn1_delete_structure(*pointer);
+
+  return (p_last==*pointer)?ASN_OK:ASN_GENERIC_ERROR;
+}
+
+
+int
+_asn1_create_static_structure(node_asn *pointer,char *file_name, char* out_name)
+{
+  FILE *file;  
+  node_asn *p;
+  unsigned long t;
+  char structure_name[128],file_out_name[128],*char_p,*slash_p,*dot_p;
+
+  char_p=file_name;
+  slash_p=file_name;
+  while((char_p=strchr(char_p,'/'))){
+    char_p++;
+    slash_p=char_p;
+  }
+
+  char_p=slash_p;
+  dot_p=file_name+strlen(file_name);
+
+  while((char_p=strchr(char_p,'.'))){
+    dot_p=char_p;
+    char_p++;
+  }
+
+  memcpy(structure_name,slash_p,dot_p-slash_p);
+  structure_name[dot_p-slash_p]=0;
+  _asn1_str_cat(structure_name, sizeof(structure_name),"_asn1_tab");
+
+  if (out_name==NULL) {
+         memcpy(file_out_name,file_name,dot_p-file_name);
+         file_out_name[dot_p-file_name]=0;
+         _asn1_str_cat(file_out_name, sizeof(file_out_name), "_asn1_tab.c");
+  } else {
+         _asn1_str_cpy( file_out_name, sizeof(file_out_name), out_name);
+  }
+  file=fopen( file_out_name,"w");
+
+  if(file==NULL) return ASN_FILE_NOT_FOUND;
+
+ fprintf(file,"\n#include \"asn1.h\"\n\n");
+ fprintf(file,"const static_asn %s[]={\n",structure_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 ASN_OK;
+}
+
+
+/**
+  * asn1_visit_tree - Prints on the standard output the structure's tree
+  * @pointer: pointer to the structure that you want to delete.
+  * @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_visit_tree(node_asn *pointer,char *name)
+{
+  node_asn *p,*root;
+  int k,indent=0,len,len2,len3;
+
+  root=_asn1_find_node(pointer,name);   
+
+  if(root==NULL) return;
+
+  p=root;
+  while(p){
+    for(k=0;k<indent;k++)printf(" ");
+
+    printf("name:");
+    if(p->name) printf("%s  ",p->name);
+    else printf("NULL  ");
+
+    printf("type:");
+    switch(type_field(p->type)){
+    case TYPE_NULL:
+      printf("NULL");
+      break;
+    case TYPE_CONSTANT:
+      printf("CONST");
+       if(p->value) printf("  value:%s",p->value);
+      break;
+    case TYPE_IDENTIFIER:
+      printf("IDENTIFIER");
+      if(p->value) printf("  value:%s",p->value);
+      break;
+    case TYPE_INTEGER:
+      printf("INTEGER");
+      if(p->value){
+       len2=-1;
+       len=_asn1_get_length_der(p->value,&len2);
+       printf("  value:0x");
+       for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]);
+      }
+      break;
+    case TYPE_ENUMERATED:
+      printf("ENUMERATED");
+      if(p->value){
+       len2=-1;
+       len=_asn1_get_length_der(p->value,&len2);
+       printf("  value:0x");
+       for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]);
+      }
+      break;
+    case TYPE_TIME:
+      printf("TIME");
+      if(p->value) printf("  value:%s",p->value);
+      break;
+    case TYPE_BOOLEAN:
+      printf("BOOLEAN");
+      if(p->value){
+       if(p->value[0]=='T') printf("  value:TRUE");
+       else if(p->value[0]=='F') printf("  value:FALSE");
+      }
+      break;
+    case TYPE_SEQUENCE:
+      printf("SEQUENCE");
+      break;
+    case TYPE_BIT_STRING:
+      printf("BIT_STR");
+      if(p->value){
+       len2=-1;
+       len=_asn1_get_length_der(p->value,&len2);
+       printf("  value(%i):",(len-1)*8-(p->value[len2]));
+       for(k=1;k<len;k++) printf("%02x",(p->value)[k+len2]);
+      }
+      break;
+    case TYPE_OCTET_STRING:
+      printf("OCT_STR");
+      if(p->value){
+       len2=-1;
+       len=_asn1_get_length_der(p->value,&len2);
+       printf("  value:");
+       for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]);
+      }
+      break;
+    case TYPE_TAG:
+      printf("TAG");
+      printf("  value:%s",p->value);
+      break;
+    case TYPE_DEFAULT:
+      printf("DEFAULT");
+      if(p->value) printf("  value:%s",p->value);
+      break;
+    case TYPE_SIZE:
+      printf("SIZE");
+      if(p->value) printf("  value:%s",p->value);
+      break;
+    case TYPE_SEQUENCE_OF:
+      printf("SEQ_OF");
+      break;
+    case TYPE_OBJECT_ID:
+      printf("OBJ_ID");
+      if(p->value) printf("  value:%s",p->value);
+      break;
+    case TYPE_ANY:
+      printf("ANY");
+      if(p->value){
+       len3=-1;
+       len2=_asn1_get_length_der(p->value,&len3);
+       printf("  value:");
+       for(k=0;k<len2;k++) printf("%02x",(p->value)[k+len3]);
+      }
+
+      break;
+    case TYPE_SET:
+      printf("SET");
+      break;
+    case TYPE_SET_OF:
+      printf("SET_OF");
+      break;
+    case TYPE_CHOICE:
+      printf("CHOICE");
+      break;
+    case TYPE_DEFINITIONS:
+      printf("DEFINITIONS");
+      break;
+    default:
+      printf("ERROR\n");
+      break;
+    }
+
+    if(p->type&0xFFFFFF00){
+      printf("  attr:");
+      if(p->type & CONST_UNIVERSAL) printf("UNIVERSAL,");
+      if(p->type & CONST_PRIVATE) printf("PRIVATE,");
+      if(p->type & CONST_APPLICATION) printf("APPLICATION,");
+      if(p->type & CONST_EXPLICIT) printf("EXPLICIT,");
+      if(p->type & CONST_IMPLICIT) printf("IMPLICIT,");
+      if(p->type & CONST_TAG) printf("TAG,");
+      if(p->type & CONST_DEFAULT) printf("DEFAULT,");
+      if(p->type & CONST_TRUE) printf("TRUE,");
+      if(p->type & CONST_FALSE) printf("FALSE,");
+      if(p->type & CONST_LIST) printf("LIST,");
+      if(p->type & CONST_MIN_MAX) printf("MIN_MAX,");
+      if(p->type & CONST_OPTION) printf("OPTION,");
+      if(p->type & CONST_1_PARAM) printf("1_PARAM,");
+      if(p->type & CONST_SIZE) printf("SIZE,");
+      if(p->type & CONST_DEFINED_BY) printf("DEF_BY,");
+      if(p->type & CONST_GENERALIZED) printf("GENERALIZED,");
+      if(p->type & CONST_UTC) printf("UTC,");
+      if(p->type & CONST_IMPORTS) printf("IMPORTS,");
+      if(p->type & CONST_SET) printf("SET,");
+      if(p->type & CONST_NOT_USED) printf("NOT_USED,");
+      if(p->type & CONST_ASSIGN) printf("ASSIGNEMENT,");
+    }
+
+    printf("\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_delete_structure - Deletes the structure *POINTER. 
+  * @root: pointer to the structure that you want to delete.
+  * Description:
+  * 
+  * Deletes the structure *POINTER. 
+  * 
+  * Returns:
+  *
+  *   ASN_OK\: everything OK
+  *
+  *   ASN_ELEMENT_NOT_FOUND\: pointer==NULL.
+  *
+  **/
+int
+asn1_delete_structure(node_asn *root)
+{
+  node_asn *p,*p2,*p3;
+
+  if(root==NULL) return ASN_ELEMENT_NOT_FOUND;
+
+  p=root;
+  while(p){
+    if(p->down){
+      p=p->down;
+    }
+    else{   /* no down */
+      p2=p->right;
+      if(p!=root){
+       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;
+      }
+    }
+  }
+  return ASN_OK;
+}
+
+
+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(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(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(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_create_structure - Creates a structure called DEST_NAME of type SOURCE_NAME.
+  * @root: 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).
+  * @pointer: 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:
+  *
+  *  ASN_OK\: creation OK
+  *
+  *  ASN_ELEMENT_NOT_FOUND\: SOURCE_NAME isn't known
+  * 
+  * Example: using "pkix.asn"
+  *  result=asn1_create_structure(cert_def,"PKIX1.Certificate",&cert,"certificate1");
+  **/
+int
+asn1_create_structure(node_asn *root,char *source_name,node_asn **pointer,char *dest_name)
+{
+  node_asn *dest_node;
+  int res;
+  char *end,n[129];
+
+  *pointer=NULL;
+
+  dest_node=_asn1_copy_structure2(root,source_name);
+  if(dest_node==NULL) return ASN_ELEMENT_NOT_FOUND;
+
+  _asn1_set_name(dest_node,dest_name);
+
+  end=strchr(source_name,'.');
+  if(end){
+    memcpy(n,source_name,end-source_name);
+    n[end-source_name]=0;
+  }
+  else{
+    _asn1_str_cpy(n,sizeof(n),source_name);
+  }
+
+  res=_asn1_expand_identifier(&dest_node,root);
+  _asn1_type_choice_config(dest_node);
+
+  *pointer=dest_node;
+
+  return res;
+}
+
+
+int 
+_asn1_append_sequence_set(node_asn *node)
+{
+  node_asn *p,*p2;
+  char temp[10];
+  long n;
+
+  if(!node || !(node->down)) return ASN_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 ASN_OK;
+}
+
+
+/**
+  * 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:
+  * 
+  *   ASN_OK\: set value OK
+  *
+  *   ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element.
+  *
+  *   ASN_VALUE_NOT_VALID\: VALUE has a wrong format.
+  * 
+  * Examples:  
+  *   description for each type
+  *   INTEGER: VALUE must contain a two's complement form integer.
+  *            value[0]=0xFF ,               len=1 -> integer=-1
+  *            value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1
+  *            value[0]=0x01 ,               len=1 -> integer= 1
+  *            value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1
+  *            value="123"                 , len=0 -> integer= 123
+  *   ENUMERATED: as INTEGER (but only with not negative numbers)
+  *   BOOLEAN: VALUE must be the null terminated string "TRUE" or "FALSE" and LEN != 0
+  *            value="TRUE" , len=1 -> boolean=TRUE
+  *            value="FALSE" , len=1 -> boolean=FALSE
+  *   OBJECT IDENTIFIER: VALUE must be a null terminated string with each number separated by
+  *                      a blank (e.g. "1 2 3 543 1"). 
+  *                      LEN != 0
+  *            value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha
+  *   UTCTime: VALUE must be a null terminated string in one of these formats:
+  *            "YYMMDDhhmmssZ" "YYMMDDhhmmssZ" "YYMMDDhhmmss+hh'mm'" "YYMMDDhhmmss-hh'mm'"
+  *            "YYMMDDhhmm+hh'mm'" "YYMMDDhhmm-hh'mm'".  
+  *            LEN != 0
+  *            value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 at 12h 00m  Greenwich Mean Time
+  *   GeneralizedTime: VALUE must be in one of this format:
+  *                    "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.s+hh'mm'" 
+  *                    "YYYYMMDDhhmmss.s-hh'mm'" "YYYYMMDDhhmm+hh'mm'" "YYYYMMDDhhmm-hh'mm'" 
+  *                    where ss.s indicates the seconds with any precision like "10.1" or "01.02".
+  *                    LEN != 0
+  *            value="2001010112001.12-0700" , len=1 -> time=Jannuary 1st, 2001 at 12h 00m 01.12s 
+  *                                                     Pacific Daylight Time
+  *   OCTET STRING: VALUE contains the octet string and LEN is the number of octet.
+  *            value="$\backslash$x01$\backslash$x02$\backslash$x03" , len=3  -> three bytes octet string
+  *   BIT STRING: VALUE contains the bit string organized by bytes and LEN is the number of bits.
+  *            value="$\backslash$xCF" , len=6 -> bit string="110011" (six bits)
+  *   CHOICE: if NAME indicates a choice type, VALUE must specify one of the alternatives with a
+  *           null terminated string. LEN != 0
+  *           Using "pkix.asn":
+  *           result=asn1_write_value(cert,"certificate1.tbsCertificate.subject","rdnSequence",1);
+  *   ANY: VALUE indicates the der encoding of a structure.
+  *        LEN != 0 
+  *   SEQUENCE OF: VALUE must be the null terminated string "NEW" and LEN != 0. With this 
+  *                instruction another element is appended in the sequence. The name of this
+  *                element will be "?1" if it's the first one, "?2" for the second and so on.
+  *           Using "pkix.asn":   
+  *           result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence","NEW",1);
+  *   SET OF: the same as SEQUENCE OF. 
+  *           Using "pkix.asn":
+  *           result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
+  * 
+  * 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);
+  * 
+  **/
+int 
+asn1_write_value(node_asn *node_root,char *name,unsigned char *value,int len)
+{
+  node_asn *node,*p,*p2;
+  unsigned char *temp,*value_temp,*default_temp;
+  int len2,k,k2,negative;
+
+  node=_asn1_find_node(node_root,name);
+  if(node==NULL) return  ASN_ELEMENT_NOT_FOUND;
+
+  if((node->type & CONST_OPTION) && (value==NULL) && (len==0)){
+    asn1_delete_structure(node);
+    return ASN_OK;
+  }
+
+  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 ASN_VALUE_NOT_VALID;
+    break;
+  case TYPE_INTEGER: case TYPE_ENUMERATED:
+    if(len==0){
+      if(isdigit(value[0])){
+       value_temp=(unsigned char *)_asn1_alloca(4);
+       if (value_temp==NULL) return ASN_MEM_ERROR;
+
+       _asn1_convert_integer(value,value_temp,4, &len);
+      }
+      else{ /* is an identifier like v1 */
+       if(!(node->type&CONST_LIST)) return ASN_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(4);
+             if (value_temp==NULL) return ASN_MEM_ERROR;
+
+             _asn1_convert_integer(p->value,value_temp,4, &len);
+             break;
+           }
+         }
+         p=p->right;
+       }
+       if(p==NULL) return ASN_VALUE_NOT_VALID;
+      }
+    }
+    else{
+      value_temp=(unsigned char *)_asn1_alloca(len);
+      if (value_temp==NULL) return ASN_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 ASN_VALUE_NOT_VALID;}
+
+    for(k=0;k<len-1;k++)
+      if(negative && (value_temp[k]!=0xFF)) break;
+      else if(!negative && value_temp[k]) break;
+
+    if((negative && !(value_temp[k]&0x80)) ||
+       (!negative && (value_temp[k]&0x80))) k--; 
+
+    _asn1_length_der(len-k,NULL,&len2);
+    temp=(unsigned char *)_asn1_alloca(len-k+len2);
+    if (temp==NULL) return ASN_MEM_ERROR;
+
+    _asn1_octet_der(value_temp+k,len-k,temp,&len2);
+    _asn1_set_value(node,temp,len2);
+
+    _asn1_afree(temp);
+
+    if(node->type&CONST_DEFAULT){
+      p=node->down;
+      while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
+      if(isdigit(p->value[0])){
+       default_temp=(unsigned char *)_asn1_alloca(4);
+        if (default_temp==NULL) return ASN_MEM_ERROR;
+
+       _asn1_convert_integer(p->value,default_temp,4,&len2);
+      }
+      else{ /* is an identifier like v1 */
+       if(!(node->type&CONST_LIST)) return ASN_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(4);
+             if (default_temp==NULL) return ASN_MEM_ERROR;
+
+             _asn1_convert_integer(p2->value,default_temp,4,&len2);
+             break;
+           }
+         }
+         p2=p2->right;
+       }
+       if(p2==NULL) return ASN_VALUE_NOT_VALID;
+      }
+
+      if((len-k)==len2){
+       for(k2=0;k2<len2;k2++) 
+         if(value_temp[k+k2]!=default_temp[k2]){
+           break;
+         }
+       if(k2==len2) _asn1_set_value(node,NULL,0);
+      }
+      _asn1_afree(default_temp);
+    }
+    _asn1_afree(value_temp);
+    break;
+  case TYPE_OBJECT_ID:
+    for(k=0;k<strlen(value);k++)
+      if((!isdigit(value[k])) && (value[k]!=' ') && (value[k]!='+')) 
+       return ASN_VALUE_NOT_VALID; 
+    _asn1_set_value(node,value,strlen(value)+1);
+    break;
+  case TYPE_TIME:
+    if(node->type&CONST_UTC){
+      if(strlen(value)<11) return ASN_VALUE_NOT_VALID;
+      for(k=0;k<10;k++) 
+       if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID;
+      switch(strlen(value)){
+      case 11:
+      if(value[10]!='Z') return ASN_VALUE_NOT_VALID;
+      break;
+      case 13:
+       if((!isdigit(value[10])) || (!isdigit(value[11])) ||
+          (value[12]!='Z')) return ASN_VALUE_NOT_VALID;
+       break;
+      case 15:
+       if((value[10]!='+') && (value[10]!='-')) return ASN_VALUE_NOT_VALID;
+       for(k=11;k<15;k++) 
+         if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID;
+       break;
+      case 17:
+       if((!isdigit(value[10])) || (!isdigit(value[11]))) 
+          return ASN_VALUE_NOT_VALID;
+       if((value[12]!='+') && (value[12]!='-')) return ASN_VALUE_NOT_VALID;
+       for(k=13;k<17;k++) 
+         if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID;
+       break; 
+      default:
+       return ASN_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 ASN_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 ASN_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 ASN_ELEMENT_NOT_FOUND;
+    break;
+  case TYPE_ANY:
+    _asn1_length_der(len,NULL,&len2);
+    temp=(unsigned char *)_asn1_alloca(len+len2);
+    if (temp==NULL) return ASN_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 ASN_VALUE_NOT_VALID;    
+    _asn1_append_sequence_set(node);
+    break;
+  default:
+    return  ASN_ELEMENT_NOT_FOUND;
+    break;
+  }
+
+  return ASN_OK;
+}
+
+#define PUT_VALUE( ptr, ptr_size, data, data_size) \
+       *len = data_size; \
+       if (ptr_size < data_size) { \
+               return ASN_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 ASN_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 ASN_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:
+  *
+  *   ASN_OK\: set value OK
+  *
+  *   ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element.
+  *
+  *   ASN_VALUE_NOT_FOUND\: there isn't any value for the element selected.
+  * 
+  * Examples: 
+  *   a description for each type
+  *   INTEGER: VALUE will contain a two's complement form integer.
+  *            integer=-1  -> value[0]=0xFF , len=1
+  *            integer=1   -> value[0]=0x01 , len=1
+  *   ENUMERATED: as INTEGER (but only with not negative numbers)
+  *   BOOLEAN: VALUE will be the null terminated string "TRUE" or "FALSE" and LEN=5 or LEN=6
+  *   OBJECT IDENTIFIER: VALUE will be a null terminated string with each number separated by
+  *                      a blank (i.e. "1 2 3 543 1"). 
+  *                      LEN = strlen(VALUE)+1
+  *   UTCTime: VALUE will be a null terminated string in one of these formats: 
+  *            "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'"
+  *            LEN=strlen(VALUE)+1
+  *   GeneralizedTime: VALUE will be a null terminated string in the same format used to set
+  *                    the value
+  *   OCTET STRING: VALUE will contain the octet string and LEN will be the number of octet.
+  *   BIT STRING: VALUE will contain the bit string organized by bytes and LEN will be the 
+  *               number of bits.
+  *   CHOICE: if NAME indicates a choice type, VALUE will specify the alternative selected
+  *   ANY: if NAME indicates an any type, VALUE will indicate the DER encoding of the structure 
+  *        actually used.
+  * 
+  * If an element is OPTIONAL and the function "read_value" returns ASN_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.
+  * 
+  **/
+int 
+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  ASN_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 ASN_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)!=ASN_OK) return ASN_MEM_ERROR;
+    }
+    else{
+      len2=-1;
+      if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN_OK) return ASN_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)!=ASN_OK) return ASN_MEM_ERROR;
+    break;
+  case TYPE_BIT_STRING:
+    len2=-1;
+    if (_asn1_get_bit_der(node->value,&len2,value,value_size,len)!=ASN_OK) return ASN_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  ASN_ELEMENT_NOT_FOUND;
+    break;
+  }
+  return ASN_OK;
+}
+
+/**
+  * asn1_number_of_elements - Counts the number of elements of a structure.
+  * @root: 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:
+  *
+  *  ASN_OK: creation OK
+  *  ASN_ELEMENT_NOT_FOUND: NAME isn't known
+  *  ASN_GENERIC_ERROR: parameter num equal to NULL
+  *
+  **/
+int 
+asn1_number_of_elements(node_asn *root,char *name,int *num)
+{
+  node_asn *node,*p;
+
+  if(num==NULL) return ASN_GENERIC_ERROR;
+
+  *num=0;
+
+  node=_asn1_find_node(root,name);
+  if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
+
+  p=node->down;
+
+  while(p){
+    if((p->name) && (p->name[0]=='?')) (*num)++; 
+    p=p->right;
+  }
+
+  return ASN_OK;
+}
+
+
+int 
+_asn1_set_default_tag(node_asn *node)
+{
+  node_asn *p;
+
+  if((node==NULL) || (type_field(node->type)!=TYPE_DEFINITIONS))
+    return ASN_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 ASN_OK;
+}
+    
+
+int 
+_asn1_check_identifier(node_asn *node)
+{
+  node_asn *p,*p2;
+  char name2[129];
+
+  if(node==NULL) return ASN_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){printf("%s\n",name2); return ASN_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);
+         p2=_asn1_find_node(node,name2);
+         if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) ||
+            !(p2->type&CONST_ASSIGN)) 
+           {printf("%s\n",name2); return ASN_IDENTIFIER_NOT_FOUND;}
+       }
+      }
+    }
+    
+    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 ASN_OK;
+}
+
+
+int 
+_asn1_change_integer_value(node_asn *node)
+{
+  node_asn *p;
+  unsigned char val[4],val2[5];
+  int len;
+
+  if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
+
+  p=node;
+  while(p){
+    if((type_field(p->type)==TYPE_INTEGER) && (p->type&CONST_ASSIGN)){
+      if(p->value){
+       _asn1_convert_integer(p->value,val,sizeof(val), &len);  
+       _asn1_octet_der(val,len,val2,&len);
+       _asn1_set_value(p,val2,len);
+      }
+    }
+
+    if(p->down){
+      p=p->down;
+    }
+    else{
+      if(p==node) p=NULL;
+      else if(p->right) p=p->right;
+      else{
+       while(1){
+         p=_asn1_find_up(p);
+         if(p==node){
+           p=NULL;
+           break;
+         }
+         if(p->right){
+           p=p->right;
+           break;
+         }
+       }
+      }
+    }
+  }
+
+  return ASN_OK;
+}
+
+
+int 
+_asn1_delete_not_used(node_asn *node)
+{
+  node_asn *p,*p2;
+
+  if(node==NULL) return ASN_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 ASN_OK;
+}
+
+
+
+int 
+_asn1_expand_identifier(node_asn **node,node_asn *root)
+{
+  node_asn *p,*p2,*p3;
+  char name2[129];
+  int move;
+  if(node==NULL) return ASN_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 ASN_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 ASN_OK;
+}
+
+
+
+int 
+_asn1_type_choice_config(node_asn *node)
+{
+  node_asn *p,*p2,*p3,*p4;
+  int move;
+  if(node==NULL) return ASN_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(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 ASN_OK;
+}
+
+
+int 
+_asn1_type_set_config(node_asn *node)
+{
+  node_asn *p,*p2;
+  int move;
+  if(node==NULL) return ASN_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 ASN_OK;
+}
+
+
+int 
+_asn1_expand_object_id(node_asn *node)
+{
+  node_asn *p,*p2,*p3,*p4,*p5;
+  char name_root[129],name2[129];
+  int move;
+  if(node==NULL) return ASN_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 ASN_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(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 ASN_OK;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/asn1.h b/lib/asn1.h
new file mode 100644 (file)
index 0000000..2890b9d
--- /dev/null
@@ -0,0 +1,204 @@
+
+/*************************************************/
+/* File: x509_asn1.h                             */
+/* Description: list of exported object by       */
+/*   "x509_asn1.c"                               */
+/*************************************************/
+
+#ifndef _GNUTLS_ASN1_H
+#define _GNUTLS_ASN1_H
+
+#define PARSE_MODE_CHECK  1
+#define PARSE_MODE_CREATE 2
+
+/* 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)
+
+
+#define ASN_OK                    0
+#define ASN_FILE_NOT_FOUND        1
+#define ASN_ELEMENT_NOT_FOUND     2
+#define ASN_IDENTIFIER_NOT_FOUND  3
+#define ASN_DER_ERROR             4
+#define ASN_VALUE_NOT_FOUND       5
+#define ASN_GENERIC_ERROR         6
+#define ASN_VALUE_NOT_VALID       7
+#define ASN_TAG_ERROR             8
+#define ASN_TAG_IMPLICIT          9
+#define ASN_ERROR_TYPE_ANY        10
+#define ASN_SYNTAX_ERROR          11
+#define ASN_MEM_ERROR            12
+#define ASN_DER_OVERFLOW          13
+
+
+/******************************************************/
+/* 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 struct static_struct_asn{
+  char *name;                    /* Node name */
+  unsigned int type;             /* Node type */
+  unsigned char *value;          /* Node value */
+} static_asn;
+
+
+/****************************************/
+/* Returns the first 8 bits.            */
+/* Used with the field type of node_asn */
+/****************************************/
+#define type_field(x)     (x&0xFF) 
+
+
+/***************************************/
+/*  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_append_tree(node_asn *node);
+
+node_asn *
+_asn1_find_node(node_asn *pointer,char *name);
+
+node_asn *
+_asn1_find_up(node_asn *node);
+
+int 
+_asn1_append_sequence_set(node_asn *node);
+
+int 
+_asn1_delete_not_used(node_asn *node);
+
+int 
+_asn1_set_default_tag(node_asn *node);
+
+/* prototypes - not defined elsewere */
+int _asn1_change_integer_value(node_asn *node);
+int _asn1_expand_object_id(node_asn *node);
+int _asn1_expand_identifier(node_asn **node,node_asn *root);
+int _asn1_type_choice_config(node_asn *node);
+int _asn1_type_set_config(node_asn *node);
+int _asn1_check_identifier(node_asn *node);
+int _asn1_create_static_structure(node_asn *pointer,char *file_name, char* out_name);
+
+int 
+asn1_parser_asn1(char *file_name,node_asn **pointer);
+
+int
+asn1_create_structure(node_asn *root,char *source_name,node_asn **pointer,
+                char *dest_name);
+
+int
+asn1_delete_structure(node_asn *root);
+
+int 
+asn1_write_value(node_asn *root,char *name,unsigned char *value,int len);
+
+int 
+asn1_read_value(node_asn *root,char *name,unsigned char *value,int *len);
+
+int
+asn1_create_tree(const static_asn *root,node_asn **pointer);
+
+int 
+asn1_number_of_elements(node_asn *root,char *name,int *num);
+
+#endif
+
diff --git a/lib/defines.h b/lib/defines.h
new file mode 100644 (file)
index 0000000..3b8acdc
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *      Copyright (C) 2000,2001,2002 Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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 DEFINES_H
+# define DEFINES_H
+
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+#pragma alloca
+#  else
+#   ifndef alloca      /* predefined by HP cc +Olibcalls */
+char *alloca();
+#   endif
+#  endif
+# endif
+#endif
+
+
+#include <config.h>
+
+#ifdef STDC_HEADERS
+# include <string.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <ctype.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+
+#if SIZEOF_UNSIGNED_LONG_INT == 4
+typedef unsigned long int uint32;
+typedef signed long int sint32;
+#elif SIZEOF_UNSIGNED_INT == 4
+typedef unsigned int uint32;
+typedef signed int sint32;
+#else
+# error "Cannot find a 32 bit integer in your system, sorry."
+#endif
+
+#if SIZEOF_UNSIGNED_INT == 2
+typedef unsigned int uint16;
+typedef signed int sint16;
+#elif SIZEOF_UNSIGNED_SHORT_INT == 2
+typedef unsigned short int uint16;
+typedef signed short int sint16;
+#else
+# error "Cannot find a 16 bit integer in your system, sorry."
+#endif
+
+#if SIZEOF_UNSIGNED_CHAR == 1
+typedef unsigned char uint8;
+typedef signed char int8;
+#else
+# error "Cannot find an 8 bit char in your system, sorry."
+#endif
+
+#ifndef HAVE_MEMMOVE
+# ifdef HAVE_BCOPY
+#  define memmove(d, s, n) bcopy ((s), (d), (n))
+# else
+#  error "Neither memmove nor bcopy exists on your system."
+# endif
+#endif
+
+#include <mem.h>
+
+#endif                         /* defines_h */
diff --git a/lib/der.c b/lib/der.c
new file mode 100644 (file)
index 0000000..4c1c8ed
--- /dev/null
+++ b/lib/der.c
@@ -0,0 +1,1417 @@
+/*
+ *      Copyright (C) 2000,2001  Fabio Fiorina
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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
+ */
+
+
+/*****************************************************/
+/* File: x509_der.c                                  */
+/* Description: Functions to manage DER encoding     */
+/*****************************************************/
+#include <defines.h>
+#include "der.h"
+#include "asn1.h"
+#include <gstr.h>
+
+#define TAG_BOOLEAN          0x01
+#define TAG_INTEGER          0x02
+#define TAG_SEQUENCE         0x10
+#define TAG_SET              0x11
+#define TAG_OCTET_STRING     0x04
+#define TAG_BIT_STRING       0x03
+#define TAG_UTCTime          0x17
+#define TAG_GENERALIZEDTime  0x18
+#define TAG_OBJECT_ID        0x06
+#define TAG_ENUMERATED       0x0A
+#define TAG_NULL             0x05
+
+
+char *
+_asn1_ltostr(long v,char *str)
+{
+  long d,r;
+  char temp[20];
+  int count,k,start;
+
+  if(v<0){
+    str[0]='-';
+    start=1;
+    v=-v;
+  }
+  else start=0;
+
+  count=0;
+  do{
+    d=v/10;
+    r=v-d*10;
+    temp[start+count]='0'+(char)r;
+    count++;
+    v=d;
+  }while(v);
+
+  for(k=0;k<count;k++) str[k+start]=temp[start+count-k-1];
+  str[count+start]=0;
+  return str;
+}
+
+
+void
+_asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len)
+{
+  int k;
+  unsigned char temp[128];
+
+  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];  
+    }
+  }
+}
+
+  
+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;
+  }
+}
+
+
+void
+_asn1_tag_der(unsigned char class,unsigned int tag_value,unsigned char *ans,int *ans_len)
+{
+  int k;
+  unsigned char temp[128];
+
+  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;  
+  }
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+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 ASN_OK;
+  *str_len=_asn1_get_length_der(der,&len_len);
+  if ( str_size >= *str_len)
+         memcpy(str,der+len_len,*str_len);
+  else {
+       return ASN_MEM_ERROR;
+  }
+  *der_len=*str_len+len_len;
+  
+  return ASN_OK;
+}
+
+
+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);
+}
+*/
+
+
+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_objectid_der(unsigned char *str,unsigned char *der,int *der_len)
+{
+  int len_len,counter,k,first;
+  char temp[128],*n_end,*n_start;
+  unsigned char bit7;
+  unsigned long val,val1;
+
+  if(der==NULL) return;
+
+  _asn1_str_cpy(temp, sizeof(temp), str);
+  _asn1_str_cat(temp, sizeof(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;
+}
+
+
+void
+_asn1_get_objectid_der(unsigned char *der,int *der_len,unsigned char *str, int str_size)
+{
+  int len_len,len,k;
+  char temp[20];
+  unsigned long val,val1;
+
+  if(str==NULL) return;
+  len=_asn1_get_length_der(der,&len_len);
+  
+  val1=der[len_len]/40;
+  val=der[len_len]-val1*40;
+
+  _asn1_str_cpy(str, str_size, _asn1_ltostr(val1,temp));
+  _asn1_str_cat(str, str_size, " ");
+  _asn1_str_cat(str, str_size, _asn1_ltostr(val,temp));
+
+  val=0;
+  for(k=1;k<len;k++){
+    val=val<<7;
+    val|=der[len_len+k]&0x7F;
+    if(!(der[len_len+k]&0x80)){
+      _asn1_str_cat(str, str_size," ");
+      _asn1_str_cat(str, str_size,_asn1_ltostr(val,temp));
+      val=0;
+    }
+  }
+  *der_len=len+len_len;
+}
+
+
+
+char bit_mask[]={0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
+
+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;
+}
+
+
+int
+_asn1_get_bit_der(unsigned char *der,int *der_len,unsigned char *str, int str_size, int *bit_len)
+{
+  int len_len,len_byte;
+
+  if(str==NULL) return ASN_OK;
+  len_byte=_asn1_get_length_der(der,&len_len)-1;
+  
+  if (str_size >= len_byte)
+       memcpy(str,der+len_len+1,len_byte);
+  else {
+       return ASN_MEM_ERROR;
+  }
+  *bit_len=len_byte*8-der[len_len];
+  *der_len=len_byte+len_len+1;
+
+  return ASN_OK;
+}
+
+
+
+
+#define UP    1
+#define DOWN  2
+#define RIGHT 3
+
+
+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[10];
+  
+  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;
+    }
+  }
+}
+
+
+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,temp[10];
+  unsigned long tag_implicit;
+   
+  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 ASN_GENERIC_ERROR;
+    }
+  }
+  
+  *counter+=tag_len;
+
+  return ASN_OK;
+}
+
+
+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;
+  unsigned char class,class2,class_implicit;
+
+  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 ASN_TAG_ERROR;
+         }
+         else{    /* TAG_IMPLICIT */
+           if((class!=class_implicit) || (tag!=tag_implicit))
+             return ASN_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 ASN_TAG_ERROR;
+  }
+  else{
+    if(type_field(node->type)==TYPE_TAG){
+      counter=0;
+      *der_len=counter;
+      return ASN_OK;
+    }
+
+    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    switch(type_field(node->type)){
+    case TYPE_NULL:
+      if((class!=UNIVERSAL) || (tag!=TAG_NULL)) return ASN_DER_ERROR;
+       break;
+    case TYPE_BOOLEAN:
+      if((class!=UNIVERSAL) || (tag!=TAG_BOOLEAN)) return ASN_DER_ERROR;
+       break;
+    case TYPE_INTEGER:
+      if((class!=UNIVERSAL) || (tag!=TAG_INTEGER)) return ASN_DER_ERROR;
+       break;
+    case TYPE_ENUMERATED:
+      if((class!=UNIVERSAL) || (tag!=TAG_ENUMERATED)) return ASN_DER_ERROR;
+       break;
+    case TYPE_OBJECT_ID:
+      if((class!=UNIVERSAL) || (tag!=TAG_OBJECT_ID)) return ASN_DER_ERROR;
+       break;
+    case TYPE_TIME:
+      if(node->type&CONST_UTC){
+         if((class!=UNIVERSAL) || (tag!=TAG_UTCTime)) return ASN_DER_ERROR;
+      }
+      else{
+       if((class!=UNIVERSAL) || (tag!=TAG_GENERALIZEDTime)) 
+         return ASN_DER_ERROR;
+      }
+      break;
+    case TYPE_OCTET_STRING:
+      if((class!=UNIVERSAL) || (tag!=TAG_OCTET_STRING)) return ASN_DER_ERROR;
+      break;
+    case TYPE_BIT_STRING:
+      if((class!=UNIVERSAL) || (tag!=TAG_BIT_STRING)) return ASN_DER_ERROR;
+      break;
+    case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF:
+      if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SEQUENCE)) 
+       return ASN_DER_ERROR;
+      break;
+    case TYPE_SET: case TYPE_SET_OF:
+      if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SET)) 
+       return ASN_DER_ERROR;
+      break;
+    case TYPE_ANY:
+      counter-=len2;
+      break;
+    default:
+      return ASN_DER_ERROR;
+      break;
+    }
+  }
+
+  counter+=len2;
+  *der_len=counter;
+  return ASN_OK;
+}
+
+
+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;
+  }
+}
+
+
+void
+_asn1_ordering_set_of(unsigned char *der,node_asn *node)
+{
+  struct vet{
+    int end;
+    struct vet *next,*prev;
+  };
+
+  int counter,len,len2,change;
+  struct vet *first,*last,*p_vet,*p2_vet;
+  node_asn *p;
+  unsigned char *temp,class;
+  unsigned long k,max;
+
+  counter=0;
+
+  if(type_field(node->type)!=TYPE_SET_OF) return;
+
+  p=node->down;
+  while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
+  p=p->right;
+
+  if((p==NULL) || (p->right==NULL)) return;
+
+  first=last=NULL;
+  while(p){
+    p_vet=(struct vet *)_asn1_alloca(sizeof(struct vet));
+    if (p_vet==NULL) return;
+    
+    p_vet->next=NULL;
+    p_vet->prev=last;
+    if(first==NULL) first=p_vet;
+    else last->next=p_vet;
+    last=p_vet;
+
+    /* extraction of tag and length */
+    _asn1_get_tag_der(der+counter,&class,&len);
+    counter+=len;
+    len2=_asn1_get_length_der(der+counter,&len);
+    counter+=len+len2;
+
+    p_vet->end=counter;
+    p=p->right;
+  }
+
+  p_vet=first;
+
+  while(p_vet){
+    p2_vet=p_vet->next;
+    counter=0;
+    while(p2_vet){
+      if((p_vet->end-counter)>(p2_vet->end-p_vet->end))
+       max=p_vet->end-counter;
+      else
+       max=p2_vet->end-p_vet->end;
+
+      change=-1;
+      for(k=0;k<max;k++) 
+       if(der[counter+k]>der[p_vet->end+k]){change=1;break;}
+       else if(der[counter+k]<der[p_vet->end+k]){change=0;break;}
+
+      if((change==-1) && ((p_vet->end-counter)>(p2_vet->end-p_vet->end)))
+       change=1;
+
+      if(change==1){
+       /* change position */
+       temp=(unsigned char *)_asn1_alloca(p_vet->end-counter);
+       if (temp==NULL) return;
+       
+       memcpy(temp,der+counter,p_vet->end-counter);
+       memmove(der+counter,der+p_vet->end,p2_vet->end-p_vet->end);
+       memcpy(der+p_vet->end,temp,p_vet->end-counter);
+       _asn1_afree(temp);
+       
+       p_vet->end=counter+(p2_vet->end-p_vet->end);
+      }
+      counter=p_vet->end;
+      
+      p2_vet=p2_vet->next;
+      p_vet=p_vet->next;
+    }
+
+    if(p_vet!=first) p_vet->prev->next=NULL;
+    else first=NULL;
+    _asn1_afree(p_vet);
+    p_vet=first;
+  }
+}
+
+/**
+  * asn1_create_der - Creates the DER encoding for the NAME structure
+  * @root: pointer to a structure
+  * @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]
+  * Description:
+  *
+  * Creates the DER encoding for the NAME structure (inside *POINTER structure).
+  * 
+  * Returns:
+  *
+  *   ASN_OK\: DER encoding OK
+  *
+  *   ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element.
+  *
+  *   ASN_VALUE_NOT_FOUND\: there is an element without a value.
+  **/
+int 
+asn1_create_der(node_asn *root,char *name,unsigned char *der,int *len)
+{
+  node_asn *node,*p;
+  char temp[20];
+  int counter,counter_old,len2,len3,move,ris;
+
+  node=_asn1_find_node(root,name);
+  if(node==NULL) return ASN_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{
+       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 ASN_OK;
+}
+
+/**
+  * asn1_get_der - Fill the structure *POINTER with values of a DER encoding string.
+  * @root: pointer to a structure
+  * @der: vector that contains the DER encoding. 
+  * @len: number of bytes of *der: der[0]..der[len-1]
+  * Description:
+  *
+  * Fill the structure *POINTER with values of a DER encoding string. The sructure must just be
+  * created with function 'create_stucture'.
+  * 
+  * Returns:
+  *
+  *   ASN_OK\: DER encoding OK
+  *
+  *   ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element.
+  *
+  *   ASN_TAG_ERROR,ASN_DER_ERROR\: the der encoding doesn't match the structure NAME.  
+  **/
+
+int 
+asn1_get_der(node_asn *root,unsigned char *der,int len)
+{
+  node_asn *node,*p,*p2,*p3;
+  char temp[128];
+  int counter,len2,len3,len4,move,ris;
+  unsigned char class,*temp2;
+  unsigned int tag;
+
+  node=root;
+  if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
+
+  if(node->type&CONST_OPTION) return ASN_GENERIC_ERROR;
+
+  counter=0;
+  move=DOWN;
+  p=node;
+  while(1){
+    ris=ASN_OK;
+
+    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 ASN_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;
+             while(p3){
+               ris=_asn1_extract_tag_der(p3,der+counter,&len2);
+               if(ris==ASN_OK) break;
+               //if(ris==ASN_ERROR_TYPE_ANY) return ASN_ERROR_TYPE_ANY;
+               p3=p3->right;
+             }
+           }
+           if(ris==ASN_OK){
+             p2->type&=~CONST_NOT_USED;
+             p=p2;
+             break;
+           }
+           //else if(ris==ASN_ERROR_TYPE_ANY) return ASN_ERROR_TYPE_ANY;
+         }
+         p2=p2->right;
+       }
+       if(p2==NULL) return ASN_DER_ERROR;
+      }
+
+      if(type_field(p->type)==TYPE_CHOICE){
+       while(p->down){
+         ris=_asn1_extract_tag_der(p->down,der+counter,&len2);
+         if(ris==ASN_OK){
+           while(p->down->right) asn1_delete_structure(p->down->right);
+           break;
+         }
+         else if(ris==ASN_ERROR_TYPE_ANY) return ASN_ERROR_TYPE_ANY;
+         else asn1_delete_structure(p->down);
+       }
+       if(p->down==NULL) return ASN_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=ASN_TAG_ERROR;
+      }
+
+      if(ris==ASN_OK) ris=_asn1_extract_tag_der(p,der+counter,&len2);
+      if(ris!=ASN_OK){
+       //if(ris==ASN_ERROR_TYPE_ANY) return ASN_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)?ASN_TAG_ERROR:ASN_ERROR_TYPE_ANY;
+         return ASN_TAG_ERROR;
+       }
+      } 
+      else counter+=len2;
+    }
+
+    if(ris==ASN_OK){
+      switch(type_field(p->type)){
+      case TYPE_NULL:
+       if(der[counter]) return ASN_DER_ERROR;
+       counter++;
+       move=RIGHT;
+       break;
+      case TYPE_BOOLEAN:
+       if(der[counter++]!=1) return ASN_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) return ASN_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) return ASN_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) return ASN_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(root);
+
+  return (counter==len)?ASN_OK:ASN_DER_ERROR;
+}
+
+
+/**
+  * asn1_get_start_end_der - Find the start and end point of an element in a DER encoding string.
+  * @root: pointer to a structure
+  * @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 "get_der" 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:
+  *
+  *   ASN_OK\: DER encoding OK
+  *
+  *   ASN_ELEMENT_NOT_FOUND\: NAME or NAME_ELEMENT is not a valid element.
+  *
+  *   ASN_TAG_ERROR,ASN_DER_ERROR\: the der encoding doesn't match the structure NAME.
+  *
+  **/
+int 
+asn1_get_start_end_der(node_asn *root,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=root;
+  node_to_find=_asn1_find_node(root,name_element);
+
+  if(node_to_find==NULL) return ASN_ELEMENT_NOT_FOUND;
+
+  if(node_to_find==node){
+    *start=0;
+    *end=len-1;
+    return ASN_OK;
+  }
+
+  if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
+
+  if(node->type&CONST_OPTION) return ASN_GENERIC_ERROR;
+
+  counter=0;
+  move=DOWN;
+  p=node;
+  while(1){
+    ris=ASN_OK;
+    
+    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 ASN_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==ASN_OK){
+             p2->type&=~CONST_NOT_USED;
+             p=p2;
+             break;
+           }
+         }
+         p2=p2->right;
+       }
+       if(p2==NULL) return ASN_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==ASN_OK) ris=_asn1_extract_tag_der(p,der+counter,&len2);
+      if(ris!=ASN_OK){
+       if(p->type&CONST_OPTION){
+         p->type|=CONST_NOT_USED;
+         move=RIGHT;
+       }
+       else if(p->type&CONST_DEFAULT) {
+         move=RIGHT;
+       }
+       else {
+         return ASN_TAG_ERROR;
+       }
+      } 
+      else counter+=len2;
+    }
+
+    if(ris==ASN_OK){
+      switch(type_field(p->type)){
+      case TYPE_NULL:
+       if(der[counter]) return ASN_DER_ERROR;
+       counter++;
+       move=RIGHT;
+       break;
+      case TYPE_BOOLEAN:
+       if(der[counter++]!=1) return ASN_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 ASN_OK;
+    }
+
+    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 ASN_ELEMENT_NOT_FOUND;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/der.h b/lib/der.h
new file mode 100644 (file)
index 0000000..d2a506a
--- /dev/null
+++ b/lib/der.h
@@ -0,0 +1,54 @@
+/*************************************************/
+/* File: x509_der.h                              */
+/* Description: list of exported object by       */
+/*   "x509_der.c"                                */
+/*************************************************/
+
+#ifndef _GNUTLS_DER_H
+#define _GNUTLS_DER_H
+
+#include "asn1.h"
+
+#define UNIVERSAL        0x00
+#define APPLICATION      0x40
+#define CONTEXT_SPECIFIC 0x80
+#define PRIVATE          0xC0
+#define STRUCTURED       0x20
+
+
+void
+_asn1_octet_der(unsigned char *str,int str_len,unsigned char *der,int *der_len);
+
+int
+_asn1_get_octet_der(unsigned char *der,int *der_len,unsigned char *str,int str_size, int *str_len);
+
+void
+_asn1_bit_der(unsigned char *str,int bit_len,unsigned char *der,int *der_len);
+
+int
+_asn1_get_bit_der(unsigned char *der,int *der_len,unsigned char *str, int str_size, int *bit_len);
+
+int 
+asn1_create_der(node_asn *root,char *name,unsigned char *der,int *len);
+
+int 
+asn1_get_der(node_asn *root,unsigned char *der,int len);
+
+int 
+asn1_get_start_end_der(node_asn *root,unsigned char *der,int len,char *name_element,int *start, int *end);
+
+unsigned long
+_asn1_get_length_der(unsigned char *der,int  *len);
+
+void
+_asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len);
+
+char *
+_asn1_ltostr(long v,char *str);
+
+#endif
+
+
+
+
+
diff --git a/lib/gstr.c b/lib/gstr.c
new file mode 100644 (file)
index 0000000..7c86e6e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *      Copyright (C) 2002 Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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
+ */
+
+#include <defines.h>
+
+/* These function are like strcat, strcpy. They only
+ * do bound checking (they shouldn't cause buffer overruns),
+ * and they always produce null terminated strings.
+ *
+ * They should be used only with null terminated strings.
+ */
+void _asn1_str_cat( char* dest, size_t dest_tot_size, const char* src) {
+size_t str_size = strlen(src);
+size_t dest_size = strlen(dest);
+
+       if ( dest_tot_size - dest_size > str_size) {
+               strcat( dest, src);
+       } else {
+               if ( dest_tot_size - dest_size > 0) {
+                       strncat( dest, src, (dest_tot_size - dest_size) -1);
+                       dest[dest_tot_size-1] = 0;
+               }
+       }
+}
+
+void _asn1_str_cpy( char* dest, size_t dest_tot_size, const char* src) {
+size_t str_size = strlen(src);
+
+       if ( dest_tot_size > str_size) {
+               strcpy( dest, src);
+       } else {
+               if ( dest_tot_size > 0) {
+                       strncpy( dest, src, (dest_tot_size) -1);
+                       dest[dest_tot_size-1] = 0;
+               }
+       }
+}
+
+void _asn1_mem_cpy( char* dest, size_t dest_tot_size, const char* src, size_t src_size) 
+{
+
+       if ( dest_tot_size >= src_size) {
+               memcpy( dest, src, src_size);
+       } else {
+               if ( dest_tot_size > 0) {
+                       memcpy( dest, src, dest_tot_size);
+               }
+       }
+}
diff --git a/lib/gstr.h b/lib/gstr.h
new file mode 100644 (file)
index 0000000..dbedcbc
--- /dev/null
@@ -0,0 +1,3 @@
+void _asn1_str_cpy( char* dest, size_t dest_tot_size, const char* src);
+void _asn1_mem_cpy( char* dest, size_t dest_tot_size, const char* src, size_t src_size);
+void _asn1_str_cat( char* dest, size_t dest_tot_size, const char* src);
diff --git a/lib/mem.h b/lib/mem.h
new file mode 100644 (file)
index 0000000..86cdfb5
--- /dev/null
+++ b/lib/mem.h
@@ -0,0 +1,22 @@
+#ifndef MEM_H
+# define MEM_H
+
+/* Use _asn1_afree() when calling alloca, or
+ * memory leaks may occur in systems which do not
+ * support alloca.
+ */
+#ifdef HAVE_ALLOCA
+# define _asn1_alloca alloca
+# define _asn1_afree(x)
+#else
+# define _asn1_alloca _asn1_malloc
+# define _asn1_afree _asn1_free
+#endif /* HAVE_ALLOCA */
+
+#define _asn1_malloc malloc
+#define _asn1_free free
+#define _asn1_calloc calloc
+#define _asn1_realloc realloc
+#define _asn1_strdup strdup
+
+#endif /* MEM_H */
diff --git a/src/CertificateExample.c b/src/CertificateExample.c
new file mode 100644 (file)
index 0000000..516db82
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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
+ */
+
+
+/*****************************************************/
+/* File: CertificateExample.c                        */
+/* Description: An example on how to use the ASN1    */
+/*              parser with the Certificate.txt file */   
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "../lib/asn1.h"
+#include "../lib/der.h"
+
+/******************************************************/
+/* Function : get_name_type                           */
+/* Description: analyze a structure of type Name      */
+/* Parameters:                                        */
+/*   char *root: the structure identifier             */
+/*   char *answer: the string with elements like:     */
+/*                 "C=US O=gov"                       */ 
+/******************************************************/
+void
+get_Name_type(node_asn *cert_def,node_asn *cert,char *root, char *answer)
+{
+  int k,k2,result,len;
+  char name[128],str[1024],str2[1024],name2[128],counter[5],name3[128];
+  node_asn *value;
+
+  answer[0]=0;
+  k=1;
+  do{
+    strcpy(name,root);
+    strcat(name,".rdnSequence.?");
+    _asn1_ltostr(k,counter);
+    strcat(name,counter);
+    len = sizeof(str) - 1;
+    result=asn1_read_value(cert,name,str,&len);
+    if(result==ASN_ELEMENT_NOT_FOUND) break;
+    k2=1;
+    do{
+      strcpy(name2,name);
+      strcat(name2,".?");
+      _asn1_ltostr(k2,counter);
+      strcat(name2,counter);
+      len = sizeof(str) - 1;
+      result=asn1_read_value(cert,name2,str,&len);
+      if(result==ASN_ELEMENT_NOT_FOUND) break;
+      strcpy(name3,name2);
+      strcat(name3,".type");
+      len = sizeof(str) - 1;
+      result=asn1_read_value(cert,name3,str,&len);
+      strcpy(name3,name2);
+      strcat(name3,".value");
+      if(result==ASN_OK){
+       len = sizeof(str2) - 1;
+       result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",
+                         str2,&len);
+       if(!strcmp(str,str2)){
+         asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                          &value,"certificate2-subject-C");
+         len = sizeof(str) - 1;
+         asn1_read_value(cert,name3,str,&len);
+         asn1_get_der(value,str,len);
+         strcpy(name3,"certificate2-subject-C");
+         len = sizeof(str) - 1;
+         asn1_read_value(value,name3,str,&len);  /* CHOICE */
+         strcat(name3,".");
+         strcat(name3,str);
+         len = sizeof(str) - 1;
+         asn1_read_value(value,name3,str,&len);
+         str[len]=0;
+         strcat(answer," C=");
+         strcat(answer,str);
+         asn1_delete_structure(value);
+       }
+       else{
+         len = sizeof(str2) - 1;
+         result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName"
+                           ,str2,&len);
+         if(!strcmp(str,str2)){
+           asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName"
+                            ,&value,"certificate2-subject-O");
+           len = sizeof(str) - 1;
+           asn1_read_value(cert,name3,str,&len);         
+           asn1_get_der(value,str,len);
+           strcpy(name3,"certificate2-subject-O");
+           len = sizeof(str) - 1;
+           asn1_read_value(value,name3,str,&len);  /* CHOICE */
+           strcat(name3,".");
+           strcat(name3,str);
+           len = sizeof(str) - 1;
+           asn1_read_value(value,name3,str,&len);
+           str[len]=0;
+           strcat(answer," O=");
+           strcat(answer,str);
+           asn1_delete_structure(value);
+         }
+         else{
+           len = sizeof(str2) - 1;
+           result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",str2,&len);
+           if(!strcmp(str,str2)){
+             asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"certificate2-subject-OU");
+             len = sizeof(str) - 1;
+             asn1_read_value(cert,name3,str,&len);
+             asn1_get_der(value,str,len);
+             strcpy(name3,"certificate2-subject-OU");
+             len = sizeof(str) - 1;
+             asn1_read_value(value,name3,str,&len);  /* CHOICE */
+             strcat(name3,".");
+             strcat(name3,str);
+             len = sizeof(str) - 1;
+             asn1_read_value(value,name3,str,&len);
+             str[len]=0;
+             strcat(answer," OU=");
+             strcat(answer,str);
+             asn1_delete_structure(value);
+           }
+         }
+       }
+      }
+      k2++;
+    }while(1);
+    k++;
+  }while(1);
+}
+
+
+/******************************************************/
+/* Function : create_certificate                      */
+/* Description: creates a certificate named           */
+/*              "certificate1". Values are the same   */
+/*              as in rfc2459 Appendix D.1            */
+/* Parameters:                                        */
+/*   unsigned char *der: contains the der encoding    */
+/*   int *der_len: number of bytes of der string      */ 
+/******************************************************/
+void
+create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
+{
+  int result,k,len;
+  unsigned char str[1024],*str2;
+  node_asn *cert1,*value,*param,*constr;
+
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.Certificate",&cert1,"certificate1");
+  /* Use the next 3 lines to visit the empty certificate */
+  /* printf("-----------------\n");
+     asn1_visit_tree(cert1,"certificate1");   
+     printf("-----------------\n"); */
+
+  /* version: v3(2) */  
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.version","v3",0); 
+
+  /* serialNumber: 17 */    
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.serialNumber","17",0); 
+
+  /* signature: dsa-with-sha1 */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.signature.algorithm",
+                    str,1);    
+  
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.signature.parameters",
+                    NULL,0);
+
+
+  /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer","rdnSequence",12);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
+  /* C */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520countryName",
+                         &value,"countryName");
+  result=asn1_write_value(value,"countryName","US",2);
+  result=asn1_create_der(value,"countryName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
+  /* O */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                         &value,"OrgName");
+  result=asn1_write_value(value,"OrgName","printableString",1);
+  result=asn1_write_value(value,"OrgName.printableString","gov",3);
+  result=asn1_create_der(value,"OrgName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
+
+  /* OU */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
+                   str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"OrgUnitName");
+  result=asn1_write_value(value,"OrgUnitName","printableString",1);
+  result=asn1_write_value(value,"OrgUnitName.printableString","nist",4);
+  result=asn1_create_der(value,"OrgUnitName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  /* validity */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notBefore","utcTime",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notBefore.utcTime","970630000000Z",1);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notAfter","utcTime",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notAfter.utcTime","971231000000Z",1);
+
+
+
+  /* subject: Country="US" Organization="gov" OrganizationUnit="nist" */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject","rdnSequence",1);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
+  /* C */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520countryName",
+                         &value,"countryName");
+  result=asn1_write_value(value,"countryName","US",2);
+  result=asn1_create_der(value,"countryName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence","NEW",4);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
+  /* O */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                         &value,"OrgName");
+  result=asn1_write_value(value,"OrgName","printableString",1);
+  result=asn1_write_value(value,"OrgName.printableString","gov",3);
+  result=asn1_create_der(value,"OrgName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence","NEW",4);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
+  /* OU */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
+                   str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"OrgUnitName");
+  result=asn1_write_value(value,"OrgUnitName","printableString",1);
+  result=asn1_write_value(value,"OrgUnitName.printableString","nist",4);
+  result=asn1_create_der(value,"OrgUnitName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  /* subjectPublicKeyInfo: dsa with parameters=Dss-Parms */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",str,1); 
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.Dss-Parms",&param,"parameters");
+  str2="\xd4\x38"; /* only an example */
+  result=asn1_write_value(param,"parameters.p",str2,128);
+  str2="\xd4\x38"; /* only an example */
+  result=asn1_write_value(param,"parameters.q",str2,20);
+  str2="\xd4\x38"; /* only an example */
+  result=asn1_write_value(param,"parameters.g",str2,128);
+  result=asn1_create_der(param,"parameters",der,der_len);
+  asn1_delete_structure(param);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der,*der_len); 
+
+
+  /* subjectPublicKey */
+  str2="\x02\x81"; /* only an example */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",str2,1048);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuerUniqueID",NULL,0);  /* NO OPTION */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectUniqueID",NULL,0); /* NO OPTION */
+
+  /* extensions */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions","NEW",1); 
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-basicConstraints",
+                   str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnID",str,1); /*   basicConstraints */  
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.critical","TRUE",1); 
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.BasicConstraints",&constr,
+                         "basicConstraints1");
+  result=asn1_write_value(constr,"basicConstraints1.cA","TRUE",1); 
+  result=asn1_write_value(constr,"basicConstraints1.pathLenConstraint",NULL,0); 
+  result=asn1_create_der(constr,"basicConstraints1",der,der_len);
+  result=asn1_delete_structure(constr);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnValue",der,*der_len); 
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions","NEW",1); 
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-subjectKeyIdentifier",
+                   str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnID",str,1); /* subjectKeyIdentifier */ 
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.critical","FALSE",1); 
+  str2="\x04\x14\xe7\x26\xc5"; /* only an example */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnValue",str2,22); 
+
+
+  /* signatureAlgorithm: dsa-with-sha  */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
+  result=asn1_write_value(cert1,"certificate1.signatureAlgorithm.algorithm",str,1); 
+  result=asn1_write_value(cert1,"certificate1.signatureAlgorithm.parameters",NULL,0); /* NO OPTION */  
+
+
+  /* signature */
+  result=asn1_create_der(cert1,"certificate1.tbsCertificate",der,der_len);
+  if(result!=ASN_OK){
+    printf("\n'tbsCertificate' encoding creation: ERROR\n");
+    //    return;
+  }
+  /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
+  result=asn1_write_value(cert1,"certificate1.signature",str2,368); /* dsa-with-sha */ 
+  
+
+  /* Use the next 3 lines to visit the certificate */
+  /* printf("-----------------\n");   
+     asn1_visit_tree(cert1,"certificate1");  
+     printf("-----------------\n"); */
+
+
+  result=asn1_create_der(cert1,"certificate1",der,der_len);
+  if(result!=ASN_OK){
+    printf("\n'certificate1' encoding creation: ERROR\n");
+    return;
+  }
+
+  /* Print the 'Certificate1' DER encoding */ 
+  printf("-----------------\nCertificate1 Encoding:\nNumber of bytes=%i\n",*der_len);
+  for(k=0;k<*der_len;k++) printf("%02x ",der[k]);  
+  printf("\n-----------------\n");
+
+  /* Clear the "certificate1" structure */
+  asn1_delete_structure(cert1);
+}
+
+
+
+/******************************************************/
+/* Function : get_certificate                         */
+/* Description: creates a certificate named           */
+/*              "certificate2" from a der encoding    */
+/*              string                                */
+/* Parameters:                                        */
+/*   unsigned char *der: the encoding string          */
+/*   int der_len: number of bytes of der string      */ 
+/******************************************************/
+void
+get_certificate(node_asn *cert_def,unsigned char *der,int der_len)
+{
+  int result,len,start,end;
+  unsigned char str[1024],str2[1024];
+  node_asn *cert2;
+
+  asn1_create_structure(cert_def,"PKIX1Implicit88.Certificate",&cert2,"certificate2");
+
+  result=asn1_get_der(cert2,der,der_len);
+
+  if(result!=ASN_OK){
+    printf("Problems with DER encoding\n");
+    return;
+  }
+   
+
+  /* issuer */
+  get_Name_type(cert_def,cert2,"certificate2.tbsCertificate.issuer",str);
+  printf("certificate2:\nissuer =%s\n",str);
+  /* subject */
+  get_Name_type(cert_def,cert2,"certificate2.tbsCertificate.subject",str);
+  printf("subject=%s\n",str);
+
+
+  /* Verify sign */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert2,"certificate2.signatureAlgorithm.algorithm"
+                   ,str,&len);
+
+  len = sizeof(str2) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str2,&len);
+  if(!strcmp(str,str2)){  /* dsa-with-sha */
+
+    result=asn1_get_start_end_der(cert2,der,der_len,
+                            "certificate2.tbsCertificate",&start,&end);
+
+    /* add the lines to calculate the sha on der[start]..der[end] */
+
+    len = sizeof(str) - 1;
+    result=asn1_read_value(cert2,"certificate2.signature",str,&len);
+
+    /* compare the previous value to signature ( with issuer public key) */ 
+  }
+
+  /* Use the next 3 lines to visit the certificate */
+  /*   printf("-----------------\n");   
+     asn1_visit_tree(cert2,"certificate2");  
+     printf("-----------------\n"); */
+
+
+  /* Clear the "certificate2" structure */
+  asn1_delete_structure(cert2);
+}
+
+
+/********************************************************/
+/* Function : main                                      */
+/* Description: reads the certificate description.      */
+/*              Creates a certificate and calculate     */
+/*              the der encoding. After that creates    */  
+/*              another certificate from der string     */
+/********************************************************/
+int
+main(int argc,char *argv[])
+{
+  int result,der_len;
+  unsigned char der[1024];
+  char file_name[128];
+  node_asn *PKIX1Implicit88;
+
+/*  result=asn1_create_tree(pkix_asn1_tab,&PKIX1Implicit88); */
+
+  if(argc==2) strcpy(file_name,argv[1]);
+  else file_name[0]=0;
+      
+  strcat(file_name,"pkix.asn");
+
+  result=asn1_parser_asn1(file_name,&PKIX1Implicit88);
+
+  if(result==ASN_FILE_NOT_FOUND){
+    printf("FILE NOT FOUND\n");
+    return;
+  }
+  else if(result==ASN_SYNTAX_ERROR){
+    printf("PARSE ERROR\n");
+    return;
+  }
+  else if(result==ASN_IDENTIFIER_NOT_FOUND){
+    printf("IDENTIFIER NOT FOUND\n");
+    return;
+  }
+
+  
+  /* Use the following 3 lines to visit the PKIX1Implicit structures */
+  /* printf("-----------------\n");
+     asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");   
+     printf("-----------------\n"); */
+
+
+  create_certificate(PKIX1Implicit88,der,&der_len);
+
+  get_certificate(PKIX1Implicit88,der,der_len);
+
+  /* Clear the "PKIX1Implicit88" structures */
+  asn1_delete_structure(PKIX1Implicit88);
+
+  return;
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/CrlExample.c b/src/CrlExample.c
new file mode 100644 (file)
index 0000000..c2a4635
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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
+ */
+
+
+/*****************************************************/
+/* File: CrlExample.c                                */
+/* Description: An example on how to use the ASN1    */
+/*              parser with the Certificate.txt file */   
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "../lib/asn1.h"
+#include "../lib/der.h"
+
+/******************************************************/
+/* Function : get_name_type                           */
+/* Description: analyze a structure of type Name      */
+/* Parameters:                                        */
+/*   char *root: the structure identifier             */
+/*   char *answer: the string with elements like:     */
+/*                 "C=US O=gov"                       */ 
+/******************************************************/
+void
+get_Name_type(node_asn *cert_def,node_asn *cert,char *root, char *answer)
+{
+  int k,k2,result,len;
+  char name[128],str[1024],str2[1024],name2[128],counter[5],name3[128];
+  node_asn *value;
+
+  answer[0]=0;
+  k=1;
+  do{
+    strcpy(name,root);
+    strcat(name,".rdnSequence.?");
+    _asn1_ltostr(k,counter);
+    strcat(name,counter);
+    
+    len = sizeof(str)-1;
+    result=asn1_read_value(cert,name,str,&len);
+    if(result==ASN_ELEMENT_NOT_FOUND) break;
+    k2=1;
+    do{
+      strcpy(name2,name);
+      strcat(name2,".?");
+      _asn1_ltostr(k2,counter);
+      strcat(name2,counter);
+      
+      len = sizeof(str)-1;
+      result=asn1_read_value(cert,name2,str,&len);
+      if(result==ASN_ELEMENT_NOT_FOUND) break;
+      strcpy(name3,name2);
+      strcat(name3,".type");
+      
+      len = sizeof(str)-1;
+      result=asn1_read_value(cert,name3,str,&len);
+      strcpy(name3,name2);
+      strcat(name3,".value");
+      if(result==ASN_OK){
+       len = sizeof(str2);
+       result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",
+                         str2,&len);
+       if(!strcmp(str,str2)){
+         asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                          &value,"certificate2-subject-C");
+         len = sizeof(str)-1;
+         asn1_read_value(cert,name3,str,&len);
+         asn1_get_der(value,str,len);
+         strcpy(name3,"certificate2-subject-C");
+         
+         len = sizeof(str)-1;
+         asn1_read_value(value,name3,str,&len);  /* CHOICE */
+         strcat(name3,".");
+         strcat(name3,str);
+         
+         len = sizeof(str)-1;
+         asn1_read_value(value,name3,str,&len);
+         str[len]=0;
+         strcat(answer," C=");
+         strcat(answer,str);
+         asn1_delete_structure(value);
+       }
+       else{
+         len = sizeof(str2);
+         result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName"
+                           ,str2,&len);
+         if(!strcmp(str,str2)){
+           asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName"
+                            ,&value,"certificate2-subject-O");
+           
+           len = sizeof(str)-1;
+           asn1_read_value(cert,name3,str,&len);         
+           asn1_get_der(value,str,len);
+           strcpy(name3,"certificate2-subject-O");
+           len = sizeof(str)-1;
+           asn1_read_value(value,name3,str,&len);  /* CHOICE */
+           strcat(name3,".");
+           strcat(name3,str);
+           len = sizeof(str)-1;
+           asn1_read_value(value,name3,str,&len);
+           str[len]=0;
+           strcat(answer," O=");
+           strcat(answer,str);
+           asn1_delete_structure(value);
+         }
+         else{
+           len = sizeof(str2);
+           result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",str2,&len);
+           if(!strcmp(str,str2)){
+             asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"certificate2-subject-OU");
+             len = sizeof(str)-1;
+             asn1_read_value(cert,name3,str,&len);
+             asn1_get_der(value,str,len);
+             strcpy(name3,"certificate2-subject-OU");
+             len = sizeof(str)-1;
+             asn1_read_value(value,name3,str,&len);  /* CHOICE */
+             strcat(name3,".");
+             strcat(name3,str);
+             len = sizeof(str)-1;
+             asn1_read_value(value,name3,str,&len);
+             str[len]=0;
+             strcat(answer," OU=");
+             strcat(answer,str);
+             asn1_delete_structure(value);
+           }
+         }
+       }
+      }
+      k2++;
+    }while(1);
+    k++;
+  }while(1);
+}
+
+
+/******************************************************/
+/* Function : create_certificate                      */
+/* Description: creates a certificate named           */
+/*              "certificate1". Values are the same   */
+/*              as in rfc2459 Appendix D.1            */
+/* Parameters:                                        */
+/*   unsigned char *der: contains the der encoding    */
+/*   int *der_len: number of bytes of der string      */ 
+/******************************************************/
+void
+create_CRL(node_asn *cert_def, unsigned char *der,int *der_len)
+{
+  int result,k,len;
+  unsigned char str[1024],*str2;
+  node_asn *crl,*value;
+
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.CertificateList",&crl,"crl1");
+  /* Use the next 3 lines to visit the empty certificate */ 
+  /*  printf("-----------------\n");
+   asn1_visit_tree(crl,"crl1");   
+   printf("-----------------\n"); */
+   
+
+  /* version: v2(1) */  
+  result=asn1_write_value(crl,"crl1.tbsCertList.version","v2",0); 
+
+  /* signature: dsa-with-sha */
+  len = sizeof(str)-1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
+  result=asn1_write_value(crl,"crl1.tbsCertList.signature.algorithm",str,1);   
+  
+  result=asn1_write_value(crl,"crl1.tbsCertList.signature.parameters",NULL,0);
+
+
+  /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer","rdnSequence",1);
+
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST","NEW",1);
+  /* C */
+  len = sizeof(str)-1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520countryName",
+                         &value,"countryName");
+  result=asn1_write_value(value,"countryName","US",2);
+  result=asn1_create_der(value,"countryName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence","NEW",4);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST","NEW",4);
+  /* O */
+  len = sizeof(str)-1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST.?LAST.type",str,8);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                         &value,"OrgName");
+  result=asn1_write_value(value,"OrgName","printableString",1);
+  result=asn1_write_value(value,"OrgName.printableString","gov",3);
+  result=asn1_create_der(value,"OrgName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST","NEW",1);
+  /* OU */
+  len = sizeof(str)-1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
+                   str,&len);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"OrgUnitName");
+  result=asn1_write_value(value,"OrgUnitName","printableString",1);
+  result=asn1_write_value(value,"OrgUnitName.printableString","nist",4);
+  result=asn1_create_der(value,"OrgUnitName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(crl,"crl1.tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  /* validity */
+  result=asn1_write_value(crl,"crl1.tbsCertList.thisUpdate","utcTime",1);
+  result=asn1_write_value(crl,"crl1.tbsCertList.thisUpdate.utcTime","970801000000Z",1);
+
+  result=asn1_write_value(crl,"crl1.tbsCertList.nextUpdate","utcTime",1);
+  result=asn1_write_value(crl,"crl1.tbsCertList.nextUpdate.utcTime","970808000000Z",1);
+
+
+  /* revokedCertificates */
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates","NEW",1);
+  str[0]=18;
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates.?LAST.userCertificate",str,1);
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates.?LAST.revocationDate","utcTime",1);
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates.?LAST.revocationDate.utcTime","970731000000Z",1);
+
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates.?LAST.crlEntryExtensions","NEW",1);
+  len = sizeof(str)-1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-cRLReasons",
+                   str,&len);
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates.?LAST.crlEntryExtensions.?LAST.extnID",str,1); /* reasonCode */
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates.?LAST.crlEntryExtensions.?LAST.critical","FALSE",1); 
+  str2="\x0a\x01\x01";
+  result=asn1_write_value(crl,"crl1.tbsCertList.revokedCertificates.?LAST.crlEntryExtensions.?LAST.extnValue",str2,3); 
+
+
+  /* crlExtensions */
+  result=asn1_write_value(crl,"crl1.tbsCertList.crlExtensions",NULL,0);
+
+
+  /* signatureAlgorithm: dsa-with-sha  */
+  len = sizeof(str)-1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
+  result=asn1_write_value(crl,"crl1.signatureAlgorithm.algorithm",str,1);  
+  result=asn1_write_value(crl,"crl1.signatureAlgorithm.parameters",NULL,0); /* NO OPTION */  
+
+  /* signature */
+  result=asn1_create_der(crl,"crl1.tbsCertList",der,der_len);
+  if(result!=ASN_OK){
+    printf("\n'tbsCertList' encoding creation: ERROR\n");
+    return;
+  }
+
+  /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
+  result=asn1_write_value(crl,"crl1.signature",str2,46*8);  
+  
+
+  /* Use the next 3 lines to visit the certificate */
+  /* printf("-----------------\n");   
+     asn1_visit_tree(crl,"crl1");  
+     printf("-----------------\n"); */
+
+
+  result=asn1_create_der(crl,"crl1",der,der_len);
+  if(result!=ASN_OK){
+    printf("\n'crl1' encoding creation: ERROR\n");
+    return;
+  }
+
+  /* Print the 'Certificate1' DER encoding */ 
+  printf("-----------------\nCrl1 Encoding:\nNumber of bytes=%i\n",*der_len);
+  for(k=0;k<*der_len;k++) printf("%02x ",der[k]);  
+  printf("\n-----------------\n");
+
+  /* Clear the "certificate1" structure */
+  asn1_delete_structure(crl);
+}
+
+
+
+/******************************************************/
+/* Function : get_certificate                         */
+/* Description: creates a certificate named           */
+/*              "certificate2" from a der encoding    */
+/*              string                                */
+/* Parameters:                                        */
+/*   unsigned char *der: the encoding string          */
+/*   int der_len: number of bytes of der string      */ 
+/******************************************************/
+void
+get_CRL(node_asn *cert_def,unsigned char *der,int der_len)
+{
+  int result,len,start,end;
+  unsigned char str[1024],str2[1024];
+  node_asn *crl2;
+
+
+  asn1_create_structure(cert_def,"PKIX1Implicit88.CertificateList",&crl2,"crl2");
+
+  result=asn1_get_der(crl2,der,der_len);
+  
+  if(result!=ASN_OK){
+    printf("Problems with DER encoding\n");
+    return;
+  }
+   
+
+  /* issuer */
+  get_Name_type(cert_def,crl2,"crl2.tbsCertList.issuer",str);
+  printf("crl2:\nissuer =%s\n",str);
+
+
+  /* Verify sign */
+  len = sizeof(str)-1;
+  result=asn1_read_value(crl2,"crl2.signatureAlgorithm.algorithm",str,&len);
+
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str2,&len);
+  if(!strcmp(str,str2)){  /* dsa-with-sha */
+
+    result=asn1_get_start_end_der(crl2,der,der_len,
+                            "crl2.tbsCertList",&start,&end);
+
+    /* add the lines to calculate the sha on der[start]..der[end] */
+
+    result=asn1_read_value(crl2,"crl2.signature",str,&len);
+
+    /* compare the previous value to signature ( with issuer public key) */ 
+  }
+
+  /* Use the next 3 lines to visit the certificate */
+  /* printf("-----------------\n");   
+     asn1_visit_tree(crl2,"crl2");  
+     printf("-----------------\n"); */
+
+
+  /* Clear the "crl2" structure */
+  asn1_delete_structure(crl2);
+}
+
+
+/********************************************************/
+/* Function : main                                      */
+/* Description: reads the certificate description.      */
+/*              Creates a certificate and calculate     */
+/*              the der encoding. After that creates    */  
+/*              another certificate from der string     */
+/********************************************************/
+int
+main(int argc,char *argv[])
+{
+  int result,der_len;
+  unsigned char der[1024];
+  char file_name[128];
+  node_asn *PKIX1Implicit88;
+
+/*  result=asn1_create_tree(pkix_asn1_tab,&PKIX1Implicit88);*/
+  if(argc==2) strcpy(file_name,argv[1]);
+  else file_name[0]=0;
+  
+  strcat(file_name,"pkix.asn");
+  result=asn1_parser_asn1(file_name,&PKIX1Implicit88);
+
+  if(result==ASN_FILE_NOT_FOUND){
+    printf("FILE NOT FOUND\n");
+    return;
+  }
+  else if(result==ASN_SYNTAX_ERROR){
+    printf("PARSE ERROR\n");
+    return;
+  }
+  else if(result==ASN_IDENTIFIER_NOT_FOUND){
+    printf("IDENTIFIER NOT FOUND\n");
+    return;
+  }
+
+  
+  /* Use the following 3 lines to visit the PKIX1Implicit structures */
+  /* printf("-----------------\n");
+     asn1_visit_tree(cert_def,"PKIX1Implicit88");   
+     printf("-----------------\n"); */
+
+    
+  create_CRL(PKIX1Implicit88,der,&der_len);
+
+  get_CRL(PKIX1Implicit88,der,der_len);
+
+  /* Clear the "PKIX1Implicit88" structures */
+  asn1_delete_structure(PKIX1Implicit88);
+
+  return;
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..a270dd0
--- /dev/null
@@ -0,0 +1,11 @@
+INCLUDES = -I../lib
+
+EXTRA_DIST = pkix.asn
+
+noinst_PROGRAMS = asn1c CertificateExample CrlExample 
+CertificateExample_SOURCES = CertificateExample.c  
+CertificateExample_LDADD = ../lib/libasn1.la
+CrlExample_SOURCES = CrlExample.c  
+CrlExample_LDADD = ../lib/libasn1.la
+asn1c_SOURCES = asn1c.c
+asn1c_LDADD = ../lib/libasn1.la
diff --git a/src/asn1c.c b/src/asn1c.c
new file mode 100644 (file)
index 0000000..b398305
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *
+ * This file is part of GNUTLS.
+ *
+ * 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
+ */
+
+
+/*****************************************************/
+/* File: PkixTabExample.c                            */
+/* Description: An example on how to use the         */
+/*              'asn1_parser_asn1_file_c' function.  */   
+/*****************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "../lib/asn1.h"
+#include "../lib/der.h"
+
+int
+main(int argc,char *argv[])
+{
+  int result;
+  char* outfile;
+  
+  if(argc<2||argc>3) {
+       fprintf(stderr, "Usage: %s: input.asn output.c\n", argv[0]);
+       exit(1);
+  }
+  if (argc==3) outfile=argv[2];
+  else outfile=NULL;
+  
+  result=asn1_parser_asn1_file_c( argv[1], outfile);
+
+  if(result==ASN_SYNTAX_ERROR){
+    printf("PARSE ERROR\n");
+    return;
+  }
+  else if(result==ASN_IDENTIFIER_NOT_FOUND){
+    printf("IDENTIFIER NOT FOUND\n");
+    return;
+  }
+  else if(result==ASN_FILE_NOT_FOUND){
+    printf("FILE NOT FOUND\n");
+    return;
+  }
+
+     return;
+}
+
+
+
+
+
diff --git a/src/pkix.asn b/src/pkix.asn
new file mode 100644 (file)
index 0000000..183345e
--- /dev/null
@@ -0,0 +1,948 @@
+
+PKIX1Implicit88 {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
+
+
+-- ISO arc for standard certificate and CRL extensions
+
+id-ce OBJECT IDENTIFIER  ::=  {joint-iso-ccitt(2) ds(5) 29}
+
+
+-- authority key identifier OID and syntax
+
+id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
+
+AuthorityKeyIdentifier ::= SEQUENCE {
+      keyIdentifier             [0] KeyIdentifier            OPTIONAL,
+      authorityCertIssuer       [1] GeneralNames             OPTIONAL,
+      authorityCertSerialNumber [2] CertificateSerialNumber  OPTIONAL }
+    -- authorityCertIssuer and authorityCertSerialNumber shall both
+    -- be present or both be absgent
+
+KeyIdentifier ::= OCTET STRING
+
+-- subject key identifier OID and syntax
+
+id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 14 }
+
+SubjectKeyIdentifier ::= KeyIdentifier
+
+-- key usage extension OID and syntax
+
+id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
+
+KeyUsage ::= BIT STRING {
+     digitalSignature        (0),
+     nonRepudiation          (1),
+     keyEncipherment         (2),
+     dataEncipherment        (3),
+     keyAgreement            (4),
+     keyCertSign             (5),
+     cRLSign                 (6),
+     encipherOnly            (7),
+     decipherOnly            (8) }
+
+-- private key usage period extension OID and syntax
+
+id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::=  { id-ce 16 }
+
+PrivateKeyUsagePeriod ::= SEQUENCE {
+     notBefore       [0]     GeneralizedTime OPTIONAL,
+     notAfter        [1]     GeneralizedTime OPTIONAL }
+     -- either notBefore or notAfter shall be present
+
+-- certificate policies extension OID and syntax
+
+id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 }
+
+CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+
+PolicyInformation ::= SEQUENCE {
+     policyIdentifier   CertPolicyId,
+     policyQualifiers   SEQUENCE SIZE (1..MAX) OF
+             PolicyQualifierInfo OPTIONAL }
+
+CertPolicyId ::= OBJECT IDENTIFIER
+
+PolicyQualifierInfo ::= SEQUENCE {
+       policyQualifierId  PolicyQualifierId,
+       qualifier        ANY DEFINED BY policyQualifierId }
+
+-- Implementations that recognize additional policy qualifiers shall
+-- augment the following definition for PolicyQualifierId
+
+PolicyQualifierId ::=
+    OBJECT IDENTIFIER  -- ( id-qt-cps | id-qt-unotice )
+
+-- CPS pointer qualifier
+
+CPSuri ::= IA5String
+
+-- user notice qualifier
+
+UserNotice ::= SEQUENCE {
+     noticeRef        NoticeReference OPTIONAL,
+     explicitText     DisplayText OPTIONAL}
+
+NoticeReference ::= SEQUENCE {
+     organization     DisplayText,
+     noticeNumbers    SEQUENCE OF INTEGER }
+
+DisplayText ::= CHOICE {
+     visibleString    VisibleString  (SIZE (1..200)),
+     bmpString        BMPString      (SIZE (1..200)),
+     utf8String       UTF8String     (SIZE (1..200)) }
+
+-- policy mapping extension OID and syntax
+
+id-ce-policyMappings OBJECT IDENTIFIER ::=  { id-ce 33 }
+
+PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+     issuerDomainPolicy      CertPolicyId,
+     subjectDomainPolicy     CertPolicyId }
+
+-- subject alternative name extension OID and syntax
+
+id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 }
+
+SubjectAltName ::= GeneralNames
+
+GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+
+GeneralName ::= CHOICE {
+     otherName                       [0]     AnotherName,
+     rfc822Name                      [1]     IA5String,
+     dNSName                         [2]     IA5String,
+     x400Address                     [3]     ORAddress,
+     directoryName                   [4]     Name,
+     ediPartyName                    [5]     EDIPartyName,
+     uniformResourceIdentifier       [6]     IA5String,
+     iPAddress                       [7]     OCTET STRING,
+     registeredID                    [8]     OBJECT IDENTIFIER }
+
+-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
+-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax
+
+AnotherName ::= SEQUENCE {
+     type-id    OBJECT IDENTIFIER,
+     value      [0] EXPLICIT ANY DEFINED BY type-id }
+
+EDIPartyName ::= SEQUENCE {
+     nameAssigner            [0]     DirectoryString OPTIONAL,
+     partyName               [1]     DirectoryString }
+
+-- issuer alternative name extension OID and syntax
+
+id-ce-issuerAltName OBJECT IDENTIFIER ::=  { id-ce 18 }
+
+IssuerAltName ::= GeneralNames
+
+id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::=  { id-ce 9 }
+
+SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+
+-- basic constraints extension OID and syntax
+
+id-ce-basicConstraints OBJECT IDENTIFIER ::=  { id-ce 19 }
+
+BasicConstraints ::= SEQUENCE {
+     cA                      BOOLEAN DEFAULT FALSE,
+     pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
+
+-- name constraints extension OID and syntax
+
+id-ce-nameConstraints OBJECT IDENTIFIER ::=  { id-ce 30 }
+
+NameConstraints ::= SEQUENCE {
+     permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+     excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+
+GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+
+GeneralSubtree ::= SEQUENCE {
+     base                    GeneralName,
+     minimum         [0]     BaseDistance DEFAULT 0,
+     maximum         [1]     BaseDistance OPTIONAL }
+
+BaseDistance ::= INTEGER (0..MAX)
+
+-- policy constraints extension OID and syntax
+
+id-ce-policyConstraints OBJECT IDENTIFIER ::=  { id-ce 36 }
+
+PolicyConstraints ::= SEQUENCE {
+     requireExplicitPolicy           [0] SkipCerts OPTIONAL,
+     inhibitPolicyMapping            [1] SkipCerts OPTIONAL }
+
+SkipCerts ::= INTEGER (0..MAX)
+
+-- CRL distribution points extension OID and syntax
+
+id-ce-cRLDistributionPoints     OBJECT IDENTIFIER  ::=  {id-ce 31}
+
+CRLDistPointsSyntax ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+
+DistributionPoint ::= SEQUENCE {
+     distributionPoint       [0]     DistributionPointName OPTIONAL,
+     reasons                 [1]     ReasonFlags OPTIONAL,
+     cRLIssuer               [2]     GeneralNames OPTIONAL }
+
+DistributionPointName ::= CHOICE {
+     fullName                [0]     GeneralNames,
+     nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
+
+
+
+ReasonFlags ::= BIT STRING {
+     unused                  (0),
+     keyCompromise           (1),
+     cACompromise            (2),
+     affiliationChanged      (3),
+     superseded              (4),
+     cessationOfOperation    (5),
+     certificateHold         (6) }
+
+-- extended key usage extension OID and syntax
+
+id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}
+
+ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+
+KeyPurposeId ::= OBJECT IDENTIFIER
+
+-- extended key purpose OIDs
+id-kp-serverAuth      OBJECT IDENTIFIER ::= { id-kp 1 }
+id-kp-clientAuth      OBJECT IDENTIFIER ::= { id-kp 2 }
+id-kp-codeSigning     OBJECT IDENTIFIER ::= { id-kp 3 }
+id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
+id-kp-ipsecEndSystem  OBJECT IDENTIFIER ::= { id-kp 5 }
+id-kp-ipsecTunnel     OBJECT IDENTIFIER ::= { id-kp 6 }
+id-kp-ipsecUser       OBJECT IDENTIFIER ::= { id-kp 7 }
+id-kp-timeStamping    OBJECT IDENTIFIER ::= { id-kp 8 }
+
+-- authority info access
+
+id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+
+AuthorityInfoAccessSyntax  ::=
+        SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+AccessDescription  ::=  SEQUENCE {
+        accessMethod          OBJECT IDENTIFIER,
+        accessLocation        GeneralName  }
+
+-- CRL number extension OID and syntax
+
+id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
+
+CRLNumber ::= INTEGER (0..MAX)
+
+-- issuing distribution point extension OID and syntax
+
+id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
+
+IssuingDistributionPoint ::= SEQUENCE {
+     distributionPoint       [0] DistributionPointName OPTIONAL,
+     onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
+     onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
+     onlySomeReasons         [3] ReasonFlags OPTIONAL,
+     indirectCRL             [4] BOOLEAN DEFAULT FALSE }
+
+
+id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 }
+
+-- deltaCRLIndicator ::= BaseCRLNumber
+
+BaseCRLNumber ::= CRLNumber
+
+-- CRL reasons extension OID and syntax
+
+id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
+
+CRLReason ::= ENUMERATED {
+     unspecified             (0),
+     keyCompromise           (1),
+     cACompromise            (2),
+     affiliationChanged      (3),
+     superseded              (4),
+     cessationOfOperation    (5),
+     certificateHold         (6),
+     removeFromCRL           (8) }
+
+-- certificate issuer CRL entry extension OID and syntax
+
+id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 }
+
+CertificateIssuer ::= GeneralNames
+
+-- hold instruction extension OID and syntax
+
+id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }
+
+HoldInstructionCode ::= OBJECT IDENTIFIER
+
+-- ANSI x9 holdinstructions
+
+-- ANSI x9 arc holdinstruction arc
+holdInstruction OBJECT IDENTIFIER ::=
+          {joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2}
+
+-- ANSI X9 holdinstructions referenced by this standard
+id-holdinstruction-none OBJECT IDENTIFIER  ::=
+                {holdInstruction 1} -- deprecated
+id-holdinstruction-callissuer OBJECT IDENTIFIER ::=
+                {holdInstruction 2}
+id-holdinstruction-reject OBJECT IDENTIFIER ::=
+                {holdInstruction 3}
+
+-- invalidity date CRL entry extension OID and syntax
+
+id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }
+
+InvalidityDate ::=  GeneralizedTime
+
+
+-- --------------------------------------
+--  EXPLICIT
+-- --------------------------------------
+
+-- UNIVERSAL Types defined in '93 and '98 ASN.1
+-- but required by this specification
+
+VisibleString ::= [UNIVERSAL 26] IMPLICIT OCTET STRING
+
+NumericString ::= [UNIVERSAL 18] IMPLICIT OCTET STRING
+
+IA5String ::= [UNIVERSAL 22] IMPLICIT OCTET STRING
+
+TeletexString ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
+
+PrintableString ::= [UNIVERSAL 19] IMPLICIT OCTET STRING
+
+UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING
+        -- UniversalString is defined in ASN.1:1993
+
+BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
+      -- BMPString is the subtype of UniversalString and models
+       -- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1
+
+UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
+        -- The content of this type conforms to RFC 2279.
+
+
+-- PKIX specific OIDs
+
+id-pkix  OBJECT IDENTIFIER  ::=
+         { iso(1) identified-organization(3) dod(6) internet(1)
+                    security(5) mechanisms(5) pkix(7) }
+
+-- PKIX arcs
+
+id-pe OBJECT IDENTIFIER  ::=  { id-pkix 1 }
+        -- arc for private certificate extensions
+id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+        -- arc for policy qualifier types
+id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
+        -- arc for extended key purpose OIDS
+id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+        -- arc for access descriptors
+
+-- policyQualifierIds for Internet policy qualifiers
+
+id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
+        -- OID for CPS qualifier
+id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
+        -- OID for user notice qualifier
+
+-- access descriptor definitions
+
+id-ad-ocsp      OBJECT IDENTIFIER ::= { id-ad 1 }
+id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+
+-- attribute data types --
+
+Attribute       ::=     SEQUENCE {
+        type            AttributeType,
+        values  SET OF AttributeValue
+                -- at least one value is required -- 
+}
+
+AttributeType           ::=   OBJECT IDENTIFIER
+
+AttributeValue          ::=   ANY
+
+AttributeTypeAndValue           ::=     SEQUENCE {
+        type    AttributeType,
+        value   AttributeValue }
+
+-- suggested naming attributes: Definition of the following
+--  information object set may be augmented to meet local
+--  requirements.  Note that deleting members of the set may
+--  prevent interoperability with conforming implementations.
+--  presented in pairs: the AttributeType followed by the
+--  type definition for the corresponding AttributeValue
+
+-- Arc for standard naming attributes
+id-at           OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4}
+
+-- Attributes of type NameDirectoryString
+id-at-name              AttributeType   ::=     {id-at 41}
+id-at-surname           AttributeType   ::=     {id-at 4}
+id-at-givenName         AttributeType   ::=     {id-at 42}
+id-at-initials          AttributeType   ::=     {id-at 43}
+id-at-generationQualifier       AttributeType   ::=     {id-at 44}
+
+X520name        ::= CHOICE {
+      teletexString         TeletexString (SIZE (1..ub-name)),
+      printableString       PrintableString (SIZE (1..ub-name)),
+      universalString       UniversalString (SIZE (1..ub-name)),
+      utf8String            UTF8String (SIZE (1..ub-name)),
+      bmpString             BMPString (SIZE(1..ub-name))   }
+
+--
+
+id-at-commonName        AttributeType   ::=     {id-at 3}
+
+X520CommonName  ::=      CHOICE {
+      teletexString         TeletexString (SIZE (1..ub-common-name)),
+      printableString       PrintableString (SIZE (1..ub-common-name)),
+      universalString       UniversalString (SIZE (1..ub-common-name)),
+      utf8String            UTF8String (SIZE (1..ub-common-name)),
+      bmpString             BMPString (SIZE(1..ub-common-name))   }
+
+--
+
+id-at-localityName      AttributeType   ::=     {id-at 7}
+
+X520LocalityName ::= CHOICE {
+      teletexString       TeletexString (SIZE (1..ub-locality-name)),
+      printableString     PrintableString (SIZE (1..ub-locality-name)),
+      universalString     UniversalString (SIZE (1..ub-locality-name)),
+      utf8String          UTF8String (SIZE (1..ub-locality-name)),
+      bmpString           BMPString (SIZE(1..ub-locality-name))   }
+
+--
+
+id-at-stateOrProvinceName       AttributeType   ::=     {id-at 8}
+
+X520StateOrProvinceName         ::= CHOICE {
+      teletexString       TeletexString (SIZE (1..ub-state-name)),
+      printableString     PrintableString (SIZE (1..ub-state-name)),
+      universalString     UniversalString (SIZE (1..ub-state-name)),
+      utf8String          UTF8String (SIZE (1..ub-state-name)),
+      bmpString           BMPString (SIZE(1..ub-state-name))   }
+
+--
+
+id-at-organizationName          AttributeType   ::=     {id-at 10}
+
+X520OrganizationName ::= CHOICE {
+  teletexString     TeletexString (SIZE (1..ub-organization-name)),
+  printableString   PrintableString (SIZE (1..ub-organization-name)),
+  universalString   UniversalString (SIZE (1..ub-organization-name)),
+  utf8String        UTF8String (SIZE (1..ub-organization-name)),
+  bmpString         BMPString (SIZE(1..ub-organization-name))   }
+
+--
+
+id-at-organizationalUnitName    AttributeType   ::=     {id-at 11}
+
+X520OrganizationalUnitName ::= CHOICE {
+ teletexString    TeletexString (SIZE (1..ub-organizational-unit-name)),
+ printableString        PrintableString
+                      (SIZE (1..ub-organizational-unit-name)),
+ universalString        UniversalString
+                      (SIZE (1..ub-organizational-unit-name)),
+ utf8String       UTF8String (SIZE (1..ub-organizational-unit-name)),
+ bmpString        BMPString (SIZE(1..ub-organizational-unit-name))   }
+
+--
+
+id-at-title     AttributeType   ::=     {id-at 12}
+
+X520Title ::=   CHOICE {
+      teletexString         TeletexString (SIZE (1..ub-title)),
+      printableString       PrintableString (SIZE (1..ub-title)),
+      universalString       UniversalString (SIZE (1..ub-title)),
+      utf8String            UTF8String (SIZE (1..ub-title)),
+      bmpString             BMPString (SIZE(1..ub-title))   }
+
+--
+
+id-at-dnQualifier       AttributeType   ::=     {id-at 46}
+X520dnQualifier ::=     PrintableString
+
+id-at-countryName       AttributeType   ::=     {id-at 6}
+X520countryName ::=     PrintableString (SIZE (2)) -- IS 3166 codes
+
+ -- Legacy attributes
+
+pkcs-9 OBJECT IDENTIFIER ::=
+       { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
+
+emailAddress AttributeType      ::= { pkcs-9 1 }
+
+Pkcs9email ::= IA5String (SIZE (1..ub-emailaddress-length))
+
+-- naming data types --
+
+Name            ::=   CHOICE { -- only one possibility for now --
+                                 rdnSequence  RDNSequence }
+
+RDNSequence     ::=   SEQUENCE OF RelativeDistinguishedName
+
+DistinguishedName       ::=   RDNSequence
+
+RelativeDistinguishedName  ::=
+                    SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+
+-- Directory string type --
+
+DirectoryString ::= CHOICE {
+      teletexString             TeletexString (SIZE (1..MAX)),
+      printableString           PrintableString (SIZE (1..MAX)),
+      universalString           UniversalString (SIZE (1..MAX)),
+      utf8String              UTF8String (SIZE (1..MAX)),
+      bmpString               BMPString (SIZE(1..MAX))   }
+
+
+-- --------------------------------------------------------
+-- certificate and CRL specific structures begin here
+-- --------------------------------------------------------
+
+Certificate  ::=  SEQUENCE  {
+     tbsCertificate       TBSCertificate,
+     signatureAlgorithm   AlgorithmIdentifier,
+     signature            BIT STRING  }
+
+TBSCertificate  ::=  SEQUENCE  {
+     version         [0]  EXPLICIT Version DEFAULT v1,
+     serialNumber         CertificateSerialNumber,
+     signature            AlgorithmIdentifier,
+     issuer               Name,
+     validity             Validity,
+     subject              Name,
+     subjectPublicKeyInfo SubjectPublicKeyInfo,
+     issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+                          -- If present, version shall be v2 or v3
+     subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+                          -- If present, version shall be v2 or v3
+     extensions      [3]  EXPLICIT Extensions OPTIONAL
+                          -- If present, version shall be v3 --  
+}
+
+Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+
+CertificateSerialNumber  ::=  INTEGER
+
+Validity ::= SEQUENCE {
+     notBefore      Time,
+     notAfter       Time }
+
+Time ::= CHOICE {
+     utcTime        UTCTime,
+     generalTime    GeneralizedTime }
+
+UniqueIdentifier  ::=  BIT STRING
+
+SubjectPublicKeyInfo  ::=  SEQUENCE  {
+     algorithm            AlgorithmIdentifier,
+     subjectPublicKey     BIT STRING  }
+
+Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+
+Extension  ::=  SEQUENCE  {
+     extnID      OBJECT IDENTIFIER,
+     critical    BOOLEAN DEFAULT FALSE,
+     extnValue   OCTET STRING  }
+
+
+-- ------------------------------------------
+-- CRL structures
+-- ------------------------------------------
+
+CertificateList  ::=  SEQUENCE  {
+     tbsCertList          TBSCertList,
+     signatureAlgorithm   AlgorithmIdentifier,
+     signature            BIT STRING  }
+
+TBSCertList  ::=  SEQUENCE  {
+     version                 Version OPTIONAL,
+                                  -- if present, shall be v2
+     signature               AlgorithmIdentifier,
+     issuer                  Name,
+     thisUpdate              Time,
+     nextUpdate              Time OPTIONAL,
+     revokedCertificates     SEQUENCE OF SEQUENCE  {
+          userCertificate         CertificateSerialNumber,
+          revocationDate          Time,
+          crlEntryExtensions      Extensions OPTIONAL
+                                         -- if present, shall be v2
+                               }  OPTIONAL,
+     crlExtensions           [0] EXPLICIT Extensions OPTIONAL
+                                         -- if present, shall be v2 -- 
+}
+
+-- Version, Time, CertificateSerialNumber, and Extensions were
+-- defined earlier for use in the certificate structure
+
+AlgorithmIdentifier  ::=  SEQUENCE  {
+     algorithm               OBJECT IDENTIFIER,
+     parameters              ANY DEFINED BY algorithm OPTIONAL  }
+                                -- contains a value of the type
+                                -- registered for use with the
+                                -- algorithm object identifier value
+
+-- Algorithm OIDs and parameter structures
+
+pkcs-1 OBJECT IDENTIFIER ::= {
+     iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+
+rsaEncryption OBJECT IDENTIFIER ::=  { pkcs-1 1 }
+
+md2WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 2 }
+
+md5WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 4 }
+
+sha1WithRSAEncryption OBJECT IDENTIFIER  ::=  { pkcs-1 5 }
+
+id-dsa-with-sha1 OBJECT IDENTIFIER ::=  {
+     iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 }
+
+Dss-Sig-Value  ::=  SEQUENCE  {
+     r       INTEGER,
+     s       INTEGER  }
+
+dhpublicnumber OBJECT IDENTIFIER ::= {
+     iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1 }
+
+DomainParameters ::= SEQUENCE {
+     p       INTEGER, -- odd prime, p=jq +1
+     g       INTEGER, -- generator, g
+     q       INTEGER, -- factor of p-1
+     j       INTEGER OPTIONAL, -- subgroup factor, j>= 2
+     validationParms  ValidationParms OPTIONAL }
+
+ValidationParms ::= SEQUENCE {
+     seed             BIT STRING,
+     pgenCounter      INTEGER }
+
+id-dsa OBJECT IDENTIFIER ::= {
+     iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) 1 }
+
+Dss-Parms  ::=  SEQUENCE  {
+     p             INTEGER,
+     q             INTEGER,
+     g             INTEGER  }
+
+-- x400 address syntax starts here
+--      OR Names
+
+ORAddress ::= SEQUENCE {
+   built-in-standard-attributes BuiltInStandardAttributes,
+   built-in-domain-defined-attributes
+                        BuiltInDomainDefinedAttributes OPTIONAL,
+   -- see also teletex-domain-defined-attributes
+   extension-attributes ExtensionAttributes OPTIONAL }
+--      The OR-address is semantically absent from the OR-name if the
+--      built-in-standard-attribute sequence is empty and the
+--      built-in-domain-defined-attributes and extension-attributes are
+--      both omitted.
+
+--      Built-in Standard Attributes
+
+BuiltInStandardAttributes ::= SEQUENCE {
+   country-name CountryName OPTIONAL,
+   administration-domain-name AdministrationDomainName OPTIONAL,
+   network-address      [0] EXPLICIT NetworkAddress OPTIONAL,
+   -- see also extended-network-address
+   terminal-identifier  [1] EXPLICIT TerminalIdentifier OPTIONAL,
+   private-domain-name  [2] EXPLICIT PrivateDomainName OPTIONAL,
+   organization-name    [3] EXPLICIT OrganizationName OPTIONAL,
+   -- see also teletex-organization-name
+   numeric-user-identifier      [4] EXPLICIT NumericUserIdentifier OPTIONAL,
+   personal-name        [5] EXPLICIT PersonalName OPTIONAL,
+   -- see also teletex-personal-name
+   organizational-unit-names    [6] EXPLICIT OrganizationalUnitNames OPTIONAL
+   -- see also teletex-organizational-unit-names -- 
+}
+
+CountryName ::= [APPLICATION 1] CHOICE {
+   x121-dcc-code NumericString
+                (SIZE (ub-country-name-numeric-length)),
+   iso-3166-alpha2-code PrintableString
+                (SIZE (ub-country-name-alpha-length)) }
+
+AdministrationDomainName ::= [APPLICATION 2] EXPLICIT CHOICE {
+   numeric NumericString (SIZE (0..ub-domain-name-length)),
+   printable PrintableString (SIZE (0..ub-domain-name-length)) }
+
+NetworkAddress ::= X121Address  -- see also extended-network-address
+
+X121Address ::= NumericString (SIZE (1..ub-x121-address-length))
+
+TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length))
+
+PrivateDomainName ::= CHOICE {
+   numeric NumericString (SIZE (1..ub-domain-name-length)),
+   printable PrintableString (SIZE (1..ub-domain-name-length)) }
+
+OrganizationName ::= PrintableString
+                            (SIZE (1..ub-organization-name-length))
+-- see also teletex-organization-name
+
+NumericUserIdentifier ::= NumericString
+                            (SIZE (1..ub-numeric-user-id-length))
+
+PersonalName ::= SET {
+   surname [0] PrintableString (SIZE (1..ub-surname-length)),
+   given-name [1] PrintableString
+                        (SIZE (1..ub-given-name-length)) OPTIONAL,
+   initials [2] PrintableString (SIZE (1..ub-initials-length)) OPTIONAL,
+   generation-qualifier [3] PrintableString
+                (SIZE (1..ub-generation-qualifier-length)) OPTIONAL }
+-- see also teletex-personal-name
+
+OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
+                                        OF OrganizationalUnitName
+-- see also teletex-organizational-unit-names
+
+OrganizationalUnitName ::= PrintableString (SIZE
+                        (1..ub-organizational-unit-name-length))
+
+--      Built-in Domain-defined Attributes
+
+BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE
+                                (1..ub-domain-defined-attributes) OF
+                                BuiltInDomainDefinedAttribute
+
+BuiltInDomainDefinedAttribute ::= SEQUENCE {
+   type PrintableString (SIZE
+                        (1..ub-domain-defined-attribute-type-length)),
+   value PrintableString (SIZE
+                        (1..ub-domain-defined-attribute-value-length))}
+
+--      Extension Attributes
+
+ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF
+                        ExtensionAttribute
+
+ExtensionAttribute ::=  SEQUENCE {
+   extension-attribute-type [0] EXPLICIT INTEGER (0..ub-extension-attributes),
+   extension-attribute-value [1] EXPLICIT
+                        ANY DEFINED BY extension-attribute-type }
+
+-- Extension types and attribute values
+--
+
+common-name INTEGER ::= 1
+
+CommonName ::= PrintableString (SIZE (1..ub-common-name-length))
+
+teletex-common-name INTEGER ::= 2
+
+TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))
+
+teletex-organization-name INTEGER ::= 3
+
+TeletexOrganizationName ::=
+                TeletexString (SIZE (1..ub-organization-name-length))
+
+teletex-personal-name INTEGER ::= 4
+
+TeletexPersonalName ::= SET {
+   surname [0] EXPLICIT TeletexString (SIZE (1..ub-surname-length)),
+   given-name [1] EXPLICIT TeletexString
+                (SIZE (1..ub-given-name-length)) OPTIONAL,
+   initials [2] EXPLICIT TeletexString (SIZE (1..ub-initials-length)) OPTIONAL,
+   generation-qualifier [3] EXPLICIT TeletexString (SIZE
+                (1..ub-generation-qualifier-length)) OPTIONAL }
+
+teletex-organizational-unit-names INTEGER ::= 5
+
+TeletexOrganizationalUnitNames ::= SEQUENCE SIZE
+        (1..ub-organizational-units) OF TeletexOrganizationalUnitName
+
+TeletexOrganizationalUnitName ::= TeletexString
+                        (SIZE (1..ub-organizational-unit-name-length))
+
+pds-name INTEGER ::= 7
+
+PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))
+
+physical-delivery-country-name INTEGER ::= 8
+
+PhysicalDeliveryCountryName ::= CHOICE {
+   x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)),
+   iso-3166-alpha2-code PrintableString
+                        (SIZE (ub-country-name-alpha-length)) }
+
+postal-code INTEGER ::= 9
+
+PostalCode ::= CHOICE {
+   numeric-code NumericString (SIZE (1..ub-postal-code-length)),
+   printable-code PrintableString (SIZE (1..ub-postal-code-length)) }
+
+physical-delivery-office-name INTEGER ::= 10
+
+PhysicalDeliveryOfficeName ::= PDSParameter
+
+physical-delivery-office-number INTEGER ::= 11
+
+PhysicalDeliveryOfficeNumber ::= PDSParameter
+
+extension-OR-address-components INTEGER ::= 12
+
+ExtensionORAddressComponents ::= PDSParameter
+
+physical-delivery-personal-name INTEGER ::= 13
+
+PhysicalDeliveryPersonalName ::= PDSParameter
+
+physical-delivery-organization-name INTEGER ::= 14
+
+PhysicalDeliveryOrganizationName ::= PDSParameter
+
+extension-physical-delivery-address-components INTEGER ::= 15
+
+ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter
+
+unformatted-postal-address INTEGER ::= 16
+
+UnformattedPostalAddress ::= SET {
+   printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) OF
+           PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL,
+   teletex-string TeletexString
+         (SIZE (1..ub-unformatted-address-length)) OPTIONAL }
+
+street-address INTEGER ::= 17
+
+StreetAddress ::= PDSParameter
+
+post-office-box-address INTEGER ::= 18
+
+PostOfficeBoxAddress ::= PDSParameter
+
+poste-restante-address INTEGER ::= 19
+
+PosteRestanteAddress ::= PDSParameter
+
+unique-postal-name INTEGER ::= 20
+
+UniquePostalName ::= PDSParameter
+
+local-postal-attributes INTEGER ::= 21
+
+LocalPostalAttributes ::= PDSParameter
+
+PDSParameter ::= SET {
+   printable-string PrintableString
+                (SIZE(1..ub-pds-parameter-length)) OPTIONAL,
+   teletex-string TeletexString
+                (SIZE(1..ub-pds-parameter-length)) OPTIONAL }
+
+extended-network-address INTEGER ::= 22
+
+ExtendedNetworkAddress ::= CHOICE {
+   e163-4-address SEQUENCE {
+        number [0] EXPLICIT NumericString (SIZE (1..ub-e163-4-number-length)),
+        sub-address [1] EXPLICIT NumericString
+                (SIZE (1..ub-e163-4-sub-address-length)) OPTIONAL },
+   psap-address [0] EXPLICIT PresentationAddress }
+
+PresentationAddress ::= SEQUENCE {
+        pSelector       [0] EXPLICIT OCTET STRING OPTIONAL,
+        sSelector       [1] EXPLICIT OCTET STRING OPTIONAL,
+        tSelector       [2] EXPLICIT OCTET STRING OPTIONAL,
+        nAddresses      [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING }
+
+terminal-type  INTEGER ::= 23
+
+TerminalType ::= INTEGER {
+   telex (3),
+   teletex (4),
+   g3-facsimile (5),
+   g4-facsimile (6),
+   ia5-terminal (7),
+   videotex (8) } (0..ub-integer-options)
+
+--      Extension Domain-defined Attributes
+
+teletex-domain-defined-attributes INTEGER ::= 6
+
+TeletexDomainDefinedAttributes ::= SEQUENCE SIZE
+   (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute
+
+TeletexDomainDefinedAttribute ::= SEQUENCE {
+        type TeletexString
+               (SIZE (1..ub-domain-defined-attribute-type-length)),
+        value TeletexString
+               (SIZE (1..ub-domain-defined-attribute-value-length)) }
+
+--  specifications of Upper Bounds shall be regarded as mandatory
+--  from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
+--  Upper Bounds
+
+--      Upper Bounds
+ub-name INTEGER ::=     32768
+ub-common-name  INTEGER ::=     64
+ub-locality-name        INTEGER ::=     128
+ub-state-name   INTEGER ::=     128
+ub-organization-name    INTEGER ::=     64
+ub-organizational-unit-name     INTEGER ::=     64
+ub-title        INTEGER ::=     64
+ub-match        INTEGER ::=     128
+
+ub-emailaddress-length INTEGER ::= 128
+
+ub-common-name-length INTEGER ::= 64
+ub-country-name-alpha-length INTEGER ::= 2
+ub-country-name-numeric-length INTEGER ::= 3
+ub-domain-defined-attributes INTEGER ::= 4
+ub-domain-defined-attribute-type-length INTEGER ::= 8
+ub-domain-defined-attribute-value-length INTEGER ::= 128
+ub-domain-name-length INTEGER ::= 16
+ub-extension-attributes INTEGER ::= 256
+ub-e163-4-number-length INTEGER ::= 15
+ub-e163-4-sub-address-length INTEGER ::= 40
+ub-generation-qualifier-length INTEGER ::= 3
+ub-given-name-length INTEGER ::= 16
+ub-initials-length INTEGER ::= 5
+ub-integer-options INTEGER ::= 256
+ub-numeric-user-id-length INTEGER ::= 32
+ub-organization-name-length INTEGER ::= 64
+ub-organizational-unit-name-length INTEGER ::= 32
+ub-organizational-units INTEGER ::= 4
+ub-pds-name-length INTEGER ::= 16
+ub-pds-parameter-length INTEGER ::= 30
+ub-pds-physical-address-lines INTEGER ::= 6
+ub-postal-code-length INTEGER ::= 16
+ub-surname-length INTEGER ::= 40
+ub-terminal-id-length INTEGER ::= 24
+ub-unformatted-address-length INTEGER ::= 180
+ub-x121-address-length INTEGER ::= 16
+
+-- Note - upper bounds on string types, such as TeletexString, are
+-- measured in characters.  Excepting PrintableString or IA5String, a
+-- significantly greater number of octets will be required to hold
+-- such a value.  As a minimum, 16 octets, or twice the specified upper
+-- bound, whichever is the larger, should be allowed for TeletexString.
+-- For UTF8String or UniversalString at least four times the upper
+-- bound should be allowed.
+
+
+
+END
+
+
+
+
+
+
+
+
+