summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2002-04-05 19:57:55 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2002-04-05 19:57:55 +0000
commitc379ce7b913aaaa136c3f3ac4542770068fc2ddc (patch)
tree397dce26cda49d25909964c68cb65b302a26c8e9
downloadlibtasn1-c379ce7b913aaaa136c3f3ac4542770068fc2ddc.tar.gz
libtasn1-c379ce7b913aaaa136c3f3ac4542770068fc2ddc.tar.bz2
libtasn1-c379ce7b913aaaa136c3f3ac4542770068fc2ddc.zip
Initial revision
-rw-r--r--AUTHORS3
-rw-r--r--COPYING340
-rw-r--r--ChangeLog0
-rw-r--r--INSTALL182
-rw-r--r--Makefile.am7
-rw-r--r--NEWS2
-rw-r--r--README7
-rw-r--r--THANKS0
-rw-r--r--acconfig.h13
-rw-r--r--acinclude.m42
-rwxr-xr-xbuildconf9
-rw-r--r--configure.in111
-rw-r--r--doc/Makefile.am19
-rw-r--r--doc/TODO0
-rw-r--r--doc/asn1.tex142
-rw-r--r--doc/fdl.tex367
-rw-r--r--doc/scripts/Makefile.am3
-rwxr-xr-xdoc/scripts/gdoc703
-rw-r--r--lib/ASN.c1997
-rw-r--r--lib/ASN.y600
-rw-r--r--lib/Makefile.am22
-rw-r--r--lib/asn1.c1954
-rw-r--r--lib/asn1.h204
-rw-r--r--lib/defines.h94
-rw-r--r--lib/der.c1417
-rw-r--r--lib/der.h54
-rw-r--r--lib/gstr.c66
-rw-r--r--lib/gstr.h3
-rw-r--r--lib/mem.h22
-rw-r--r--src/CertificateExample.c505
-rw-r--r--src/CrlExample.c423
-rw-r--r--src/Makefile.am11
-rw-r--r--src/asn1c.c68
-rw-r--r--src/pkix.asn948
34 files changed, 10298 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
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
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.
+
+ 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.)
+
+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.
+
+ 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.
+
+ 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
+
+ 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
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/INSTALL b/INSTALL
new file mode 100644
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
index 0000000..60f3825
--- /dev/null
+++ b/Makefile.am
@@ -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
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
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
index 0000000..e69de29
--- /dev/null
+++ b/THANKS
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 0000000..a29dd8e
--- /dev/null
+++ b/acconfig.h
@@ -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
index 0000000..aad539d
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,2 @@
+
+dnl *-*wedit:notab*-* Please keep this as the last line.
diff --git a/buildconf b/buildconf
new file mode 100755
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
index 0000000..0723bbe
--- /dev/null
+++ b/configure.in
@@ -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
index 0000000..a257afb
--- /dev/null
+++ b/doc/Makefile.am
@@ -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
index 0000000..e69de29
--- /dev/null
+++ b/doc/TODO
diff --git a/doc/asn1.tex b/doc/asn1.tex
new file mode 100644
index 0000000..1ef06ed
--- /dev/null
+++ b/doc/asn1.tex
@@ -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
index 0000000..c0fcbe3
--- /dev/null
+++ b/doc/fdl.tex
@@ -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
index 0000000..7deb104
--- /dev/null
+++ b/doc/scripts/Makefile.am
@@ -0,0 +1,3 @@
+EXTRA_DIST = gdoc
+
+
diff --git a/doc/scripts/gdoc b/doc/scripts/gdoc
new file mode 100755
index 0000000..9597148
--- /dev/null
+++ b/doc/scripts/gdoc
@@ -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
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
+
+#if ! defined (yyoverflow) && ! defined (yymemcpy)
+# if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+# define yymemcpy __builtin_memcpy
+# else /* not GNU C or C++ */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+# if defined (__STDC__) || defined (__cplusplus)
+yymemcpy (char *yyto, const char *yyfrom, YYSIZE_T yycount)
+# else
+yymemcpy (yyto, yyfrom, yycount)
+ char *yyto;
+ const char *yyfrom;
+ YYSIZE_T yycount;
+# endif
+{
+ register const char *yyf = yyfrom;
+ register char *yyt = yyto;
+ register YYSIZE_T yyi = yycount;
+
+ while (yyi-- != 0)
+ *yyt++ = *yyf++;
+}
+# endif
+#endif
+
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+#endif
+
+#line 341 "/usr/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"
+
+
+ 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
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
index 0000000..5ca829d
--- /dev/null
+++ b/lib/Makefile.am
@@ -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
index 0000000..5221955
--- /dev/null
+++ b/lib/asn1.c
@@ -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
index 0000000..2890b9d
--- /dev/null
+++ b/lib/asn1.h
@@ -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
index 0000000..3b8acdc
--- /dev/null
+++ b/lib/defines.h
@@ -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
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
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
index 0000000..7c86e6e
--- /dev/null
+++ b/lib/gstr.c
@@ -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
index 0000000..dbedcbc
--- /dev/null
+++ b/lib/gstr.h
@@ -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
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
index 0000000..516db82
--- /dev/null
+++ b/src/CertificateExample.c
@@ -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
index 0000000..c2a4635
--- /dev/null
+++ b/src/CrlExample.c
@@ -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
index 0000000..a270dd0
--- /dev/null
+++ b/src/Makefile.am
@@ -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
index 0000000..b398305
--- /dev/null
+++ b/src/asn1c.c
@@ -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
index 0000000..183345e
--- /dev/null
+++ b/src/pkix.asn
@@ -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
+
+
+
+
+
+
+
+
+