diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-04-05 19:57:55 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-04-05 19:57:55 +0000 |
commit | c379ce7b913aaaa136c3f3ac4542770068fc2ddc (patch) | |
tree | 397dce26cda49d25909964c68cb65b302a26c8e9 | |
download | libtasn1-c379ce7b913aaaa136c3f3ac4542770068fc2ddc.tar.gz libtasn1-c379ce7b913aaaa136c3f3ac4542770068fc2ddc.tar.bz2 libtasn1-c379ce7b913aaaa136c3f3ac4542770068fc2ddc.zip |
Initial revision
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | ChangeLog | 0 | ||||
-rw-r--r-- | INSTALL | 182 | ||||
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | README | 7 | ||||
-rw-r--r-- | THANKS | 0 | ||||
-rw-r--r-- | acconfig.h | 13 | ||||
-rw-r--r-- | acinclude.m4 | 2 | ||||
-rwxr-xr-x | buildconf | 9 | ||||
-rw-r--r-- | configure.in | 111 | ||||
-rw-r--r-- | doc/Makefile.am | 19 | ||||
-rw-r--r-- | doc/TODO | 0 | ||||
-rw-r--r-- | doc/asn1.tex | 142 | ||||
-rw-r--r-- | doc/fdl.tex | 367 | ||||
-rw-r--r-- | doc/scripts/Makefile.am | 3 | ||||
-rwxr-xr-x | doc/scripts/gdoc | 703 | ||||
-rw-r--r-- | lib/ASN.c | 1997 | ||||
-rw-r--r-- | lib/ASN.y | 600 | ||||
-rw-r--r-- | lib/Makefile.am | 22 | ||||
-rw-r--r-- | lib/asn1.c | 1954 | ||||
-rw-r--r-- | lib/asn1.h | 204 | ||||
-rw-r--r-- | lib/defines.h | 94 | ||||
-rw-r--r-- | lib/der.c | 1417 | ||||
-rw-r--r-- | lib/der.h | 54 | ||||
-rw-r--r-- | lib/gstr.c | 66 | ||||
-rw-r--r-- | lib/gstr.h | 3 | ||||
-rw-r--r-- | lib/mem.h | 22 | ||||
-rw-r--r-- | src/CertificateExample.c | 505 | ||||
-rw-r--r-- | src/CrlExample.c | 423 | ||||
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/asn1c.c | 68 | ||||
-rw-r--r-- | src/pkix.asn | 948 |
34 files changed, 10298 insertions, 0 deletions
@@ -0,0 +1,3 @@ + +Fabio Fiorina <Fabio.Fiorina@alcatel.it> + @@ -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 @@ -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 @@ -0,0 +1,2 @@ +Version 0.1.0 +- Initial release @@ -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/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'} . "\"> </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",¶m,"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 + + + + + + + + + |