Initial checking
authorWerner Koch <wk@gnupg.org>
Wed, 10 Oct 2001 17:08:39 +0000 (17:08 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 10 Oct 2001 17:08:39 +0000 (17:08 +0000)
33 files changed:
AUTHORS [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
README-alpha [new file with mode: 0644]
THANKS [new file with mode: 0644]
configure.ac [new file with mode: 0644]
src/CertificateExample.c [new file with mode: 0644]
src/ChangeLog [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/README.asn1 [new file with mode: 0644]
src/asn1-der.c [new file with mode: 0644]
src/asn1-der.h [new file with mode: 0644]
src/asn1-func.c [new file with mode: 0755]
src/asn1-func.h [new file with mode: 0755]
src/asn1-gentables.c [new file with mode: 0644]
src/asn1-parse.h [new file with mode: 0644]
src/asn1-parse.y [new file with mode: 0755]
src/ber-decoder.c [new file with mode: 0644]
src/ber-decoder.h [new file with mode: 0644]
src/ber-dump.c [new file with mode: 0644]
src/cert-get.c [new file with mode: 0644]
src/cert.c [new file with mode: 0644]
src/cert.h [new file with mode: 0644]
src/cms.asn [new file with mode: 0644]
src/cms.c [new file with mode: 0644]
src/ksba.h [new file with mode: 0644]
src/reader.c [new file with mode: 0644]
src/reader.h [new file with mode: 0644]
src/tmttv2.asn [new file with mode: 0644]
src/util.c [new file with mode: 0644]
src/util.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..c0dffe5
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,12 @@
+
+g10 Code GmbH
+Design and most stuff.
+
+
+GNUTLS  Fabio Fiorina   2001-06-19
+[According to CVS log of  August 5, 2001 @ 11:38:
+"renamed cert_* to x509_*" , further more the orginal names
+must have been changed from Fabio's orginal ones to cert_* when 
+Fabio commited them to CVS] We renamed the files further, see ksba/asn1-parser.txt for details. We use these files:
+   (CertificateExample.c, asn1-readme.txt, asn1-parse.y, asn1-func.[ch],
+    asn1-der.[ch])
\ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..2c202f8
--- /dev/null
@@ -0,0 +1,28 @@
+# Makefile.am - main makefile for libksba
+#      Copyright (C) 2001 g10 Code GmbH
+# 
+# This file is part of KSBA.
+# 
+# KSBA 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.
+# 
+# KSBA 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
+
+## Process this file with automake to produce Makefile.in
+
+EXTRA_DIST = README-alpha autogen.sh
+
+SUBDIRS = src
+
+
+
+
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..a3d3901
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+KSBA = rot13(digit_to_letter(x509)) to be pronounced as Kasbah
+
diff --git a/README-alpha b/README-alpha
new file mode 100644 (file)
index 0000000..0f748e3
--- /dev/null
@@ -0,0 +1 @@
+ THIS IS WORK IN PROGRESS !!!!
\ No newline at end of file
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..f7ea752
--- /dev/null
@@ -0,0 +1,97 @@
+# configure.ac - for libksba
+#       Copyright (C) 2001 g10 Code GmbH
+# 
+# This file is part of KSBA
+# 
+# KSBA 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.
+# 
+# KSBA 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
+
+# Process this file with autoconf to produce a configure script.
+
+# Version numbers (Remember to change them just before a release)
+#   (Interfaces removed:    CURRENT++, AGE=0, REVISION=0)
+#   (Interfaces added:      CURRENT++, AGE++, REVISION=0)
+#   (No interfaces changed:                   REVISION++)
+PACKAGE="libksba"
+VERSION="0.0.0"
+# libksba:
+LIBKSBA_LT_CURRENT=0
+LIBKSBA_LT_AGE=0
+LIBKSBA_LT_REVISION=0
+
+AC_INIT($PACKAGE, $VERSION, bug-$PACKAGE@g10code.com)
+AC_CONFIG_SRCDIR([src/ksba.h])
+AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
+AM_CONFIG_HEADER(config.h)
+
+AC_SUBST(LIBKSBA_LT_CURRENT)
+AC_SUBST(LIBKSBA_LT_AGE)
+AC_SUBST(LIBKSBA_LT_REVISION)
+
+AM_MAINTAINER_MODE
+
+# Due to automake/autoconf incompatibilities we need this stuff
+#PACKAGE="$PACKAGE_NAME"
+#VERSION="$PACKAGE_VERSION"
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
+
+
+
+# Checks for programs.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+#AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_PROG_AWK
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+#AC_ARG_PROGRAM
+AC_PROG_YACC
+
+
+# Don't build shared libs for now.
+AM_DISABLE_SHARED
+AM_PROG_LIBTOOL
+
+if test "$GCC" = yes; then
+    CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
+fi
+
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([string.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+# Checks for library functions.
+AC_CHECK_FUNCS([memmove strchr strtol strtoul])
+
+AC_CONFIG_FILES([
+Makefile
+src/Makefile
+])
+AC_OUTPUT
diff --git a/src/CertificateExample.c b/src/CertificateExample.c
new file mode 100644 (file)
index 0000000..9a611db
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *      Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * 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 "asn1-func.h"
+#include "asn1-der.h"
+
+extern static_asn pkix_asn1_tab[];
+
+/******************************************************/
+/* Function : get_name_type                           */
+/* Description: analyze a structure of type Name      */
+/* Parameters:                                        */
+/*   char *root: the structure identifier             */
+/*   char *answer: the string with elements like:     */
+/*                 "C=US O=gov"                       */ 
+/******************************************************/
+void
+get_Name_type(node_asn *cert_def,node_asn *cert,char *root, char *answer)
+{
+  int k,k2,result,len;
+  char name[128],str[1024],str2[1024],name2[128],counter[5],name3[128];
+  node_asn *value;
+
+  answer[0]=0;
+  k=1;
+  do{
+    strcpy(name,root);
+    strcat(name,".rdnSequence.?");
+    _asn1_ltostr(k,counter);
+    strcat(name,counter);
+    len = sizeof(str) - 1;
+    result=asn1_read_value(cert,name,str,&len);
+    if(result==ASN_ELEMENT_NOT_FOUND) break;
+    k2=1;
+    do{
+      strcpy(name2,name);
+      strcat(name2,".?");
+      _asn1_ltostr(k2,counter);
+      strcat(name2,counter);
+      len = sizeof(str) - 1;
+      result=asn1_read_value(cert,name2,str,&len);
+      if(result==ASN_ELEMENT_NOT_FOUND) break;
+      strcpy(name3,name2);
+      strcat(name3,".type");
+      len = sizeof(str) - 1;
+      result=asn1_read_value(cert,name3,str,&len);
+      strcpy(name3,name2);
+      strcat(name3,".value");
+      if(result==ASN_OK){
+       len = sizeof(str2) - 1;
+       result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",
+                               str2,&len);
+       if(!strcmp(str,str2)){
+         asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                                &value,"certificate2-subject-C");
+         len = sizeof(str) - 1;
+         asn1_read_value(cert,name3,str,&len);
+         asn1_get_der(value,str,len);
+         strcpy(name3,"certificate2-subject-C");
+         len = sizeof(str) - 1;
+         asn1_read_value(value,name3,str,&len);  /* CHOICE */
+         strcat(name3,".");
+         strcat(name3,str);
+         len = sizeof(str) - 1;
+         asn1_read_value(value,name3,str,&len);
+         str[len]=0;
+         strcat(answer," C=");
+         strcat(answer,str);
+         asn1_delete_structure(value);
+       }
+       else{
+         len = sizeof(str2) - 1;
+         result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName"
+                                 ,str2,&len);
+         if(!strcmp(str,str2)){
+           asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName"
+                                  ,&value,"certificate2-subject-O");
+           len = sizeof(str) - 1;
+           asn1_read_value(cert,name3,str,&len);         
+           asn1_get_der(value,str,len);
+           strcpy(name3,"certificate2-subject-O");
+           len = sizeof(str) - 1;
+           asn1_read_value(value,name3,str,&len);  /* CHOICE */
+           strcat(name3,".");
+           strcat(name3,str);
+           len = sizeof(str) - 1;
+           asn1_read_value(value,name3,str,&len);
+           str[len]=0;
+           strcat(answer," O=");
+           strcat(answer,str);
+           asn1_delete_structure(value);
+         }
+         else{
+           len = sizeof(str2) - 1;
+           result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",str2,&len);
+           if(!strcmp(str,str2)){
+             asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"certificate2-subject-OU");
+             len = sizeof(str) - 1;
+             asn1_read_value(cert,name3,str,&len);
+             asn1_get_der(value,str,len);
+             strcpy(name3,"certificate2-subject-OU");
+             len = sizeof(str) - 1;
+             asn1_read_value(value,name3,str,&len);  /* CHOICE */
+             strcat(name3,".");
+             strcat(name3,str);
+             len = sizeof(str) - 1;
+             asn1_read_value(value,name3,str,&len);
+             str[len]=0;
+             strcat(answer," OU=");
+             strcat(answer,str);
+             asn1_delete_structure(value);
+           }
+         }
+       }
+      }
+      k2++;
+    }while(1);
+    k++;
+  }while(1);
+}
+
+
+/******************************************************/
+/* Function : create_certificate                      */
+/* Description: creates a certificate named           */
+/*              "certificate1". Values are the same   */
+/*              as in rfc2459 Appendix D.1            */
+/* Parameters:                                        */
+/*   unsigned char *der: contains the der encoding    */
+/*   int *der_len: number of bytes of der string      */ 
+/******************************************************/
+void
+create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
+{
+  int result,k,len;
+  unsigned char str[1024],*str2;
+  node_asn *cert1,*value,*param,*constr;
+
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.Certificate",&cert1,"certificate1");
+  /* Use the next 3 lines to visit the empty certificate */
+  printf("-----------------\n");
+  asn1_visit_tree(cert1,"certificate1");   
+  printf("-----------------\n"); 
+
+  /* version: v3(2) */  
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.version","v3",0); 
+
+  /* serialNumber: 17 */    
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.serialNumber","17",0); 
+
+  /* signature: dsa-with-sha1 */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.signature.algorithm",
+                          str,1);    
+  
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.signature.parameters",
+                          NULL,0);
+
+
+  /* issuer: Country="US" Organization="gov" OrganizationUnit="nist" */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer","rdnSequence",12);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
+  /* C */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520countryName",
+                               &value,"countryName");
+  result=asn1_write_value(value,"countryName","US",2);
+  result=asn1_create_der(value,"countryName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
+  /* O */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                               &value,"OrgName");
+  result=asn1_write_value(value,"OrgName","printableString",1);
+  result=asn1_write_value(value,"OrgName.printableString","gov",3);
+  result=asn1_create_der(value,"OrgName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST","NEW",1);
+
+  /* OU */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
+                         str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"OrgUnitName");
+  result=asn1_write_value(value,"OrgUnitName","printableString",1);
+  result=asn1_write_value(value,"OrgUnitName.printableString","nist",4);
+  result=asn1_create_der(value,"OrgUnitName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  /* validity */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notBefore","utcTime",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notBefore.utcTime","970630000000Z",1);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notAfter","utcTime",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.validity.notAfter.utcTime","971231000000Z",1);
+
+
+
+  /* subject: Country="US" Organization="gov" OrganizationUnit="nist" */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject","rdnSequence",1);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence","NEW",1);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
+  /* C */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-countryName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520countryName",
+                               &value,"countryName");
+  result=asn1_write_value(value,"countryName","US",2);
+  result=asn1_create_der(value,"countryName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence","NEW",4);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
+  /* O */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationName",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationName",
+                               &value,"OrgName");
+  result=asn1_write_value(value,"OrgName","printableString",1);
+  result=asn1_write_value(value,"OrgName.printableString","gov",3);
+  result=asn1_create_der(value,"OrgName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence","NEW",4);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",4);
+  /* OU */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-at-organizationalUnitName",
+                         str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.type",str,1);
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value,"OrgUnitName");
+  result=asn1_write_value(value,"OrgUnitName","printableString",1);
+  result=asn1_write_value(value,"OrgUnitName.printableString","nist",4);
+  result=asn1_create_der(value,"OrgUnitName",der,der_len);
+  asn1_delete_structure(value);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
+
+
+  /* subjectPublicKeyInfo: dsa with parameters=Dss-Parms */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa",str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",str,1); 
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.Dss-Parms",&param,"parameters");
+  str2="\xd4\x38"; /* only an example */
+  result=asn1_write_value(param,"parameters.p",str2,128);
+  str2="\xd4\x38"; /* only an example */
+  result=asn1_write_value(param,"parameters.q",str2,20);
+  str2="\xd4\x38"; /* only an example */
+  result=asn1_write_value(param,"parameters.g",str2,128);
+  result=asn1_create_der(param,"parameters",der,der_len);
+  asn1_delete_structure(param);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der,*der_len); 
+
+
+  /* subjectPublicKey */
+  str2="\x02\x81"; /* only an example */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",str2,1048);
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.issuerUniqueID",NULL,0);  /* NO OPTION */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.subjectUniqueID",NULL,0); /* NO OPTION */
+
+  /* extensions */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions","NEW",1); 
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-basicConstraints",
+                         str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnID",str,1); /*   basicConstraints */  
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.critical","TRUE",1); 
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.BasicConstraints",&constr,
+                               "basicConstraints1");
+  result=asn1_write_value(constr,"basicConstraints1.cA","TRUE",1); 
+  result=asn1_write_value(constr,"basicConstraints1.pathLenConstraint",NULL,0); 
+  result=asn1_create_der(constr,"basicConstraints1",der,der_len);
+  result=asn1_delete_structure(constr);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnValue",der,*der_len); 
+
+
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions","NEW",1); 
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-ce-subjectKeyIdentifier",
+                         str,&len);
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnID",str,1); /* subjectKeyIdentifier */ 
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.critical","FALSE",1); 
+  str2="\x04\x14\xe7\x26\xc5"; /* only an example */
+  result=asn1_write_value(cert1,"certificate1.tbsCertificate.extensions.?LAST.extnValue",str2,22); 
+
+
+  /* signatureAlgorithm: dsa-with-sha  */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str,&len);
+  result=asn1_write_value(cert1,"certificate1.signatureAlgorithm.algorithm",str,1); 
+  result=asn1_write_value(cert1,"certificate1.signatureAlgorithm.parameters",NULL,0); /* NO OPTION */  
+
+
+  /* signature */
+  result=asn1_create_der(cert1,"certificate1.tbsCertificate",der,der_len);
+  if(result!=ASN_OK){
+    printf("\n'tbsCertificate' encoding creation: ERROR\n");
+    //    return;
+  }
+  /* add the lines for the signature on der[0]..der[der_len-1]: result in str2 */
+  result=asn1_write_value(cert1,"certificate1.signature",str2,368); /* dsa-with-sha */ 
+  
+
+  /* Use the next 3 lines to visit the certificate */
+  printf("-----------------\n");   
+  asn1_visit_tree(cert1,"certificate1");  
+  printf("-----------------\n"); 
+
+
+  result=asn1_create_der(cert1,"certificate1",der,der_len);
+  if(result!=ASN_OK){
+    printf("\n'certificate1' encoding creation: ERROR\n");
+    return;
+  }
+
+  /* Print the 'Certificate1' DER encoding */ 
+  printf("-----------------\nCertificate1 Encoding:\nNumber of bytes=%i\n",*der_len);
+  for(k=0;k<*der_len;k++) printf("%02x ",der[k]);  
+  printf("\n-----------------\n");
+
+  /* Clear the "certificate1" structure */
+  asn1_delete_structure(cert1);
+}
+
+
+
+/******************************************************/
+/* Function : get_certificate                         */
+/* Description: creates a certificate named           */
+/*              "certificate2" from a der encoding    */
+/*              string                                */
+/* Parameters:                                        */
+/*   unsigned char *der: the encoding string          */
+/*   int der_len: number of bytes of der string      */ 
+/******************************************************/
+void
+get_certificate(node_asn *cert_def,unsigned char *der,int der_len)
+{
+  int result,len,start,end;
+  unsigned char str[1024],str2[1024];
+  node_asn *cert2;
+
+  asn1_create_structure(cert_def,"PKIX1Implicit88.Certificate",&cert2,"certificate2");
+
+  result=asn1_get_der(cert2,der,der_len);
+
+  if(result!=ASN_OK){
+    printf("Problems with DER encoding\n");
+    return;
+  }
+   
+
+  /* issuer */
+  get_Name_type(cert_def,cert2,"certificate2.tbsCertificate.issuer",str);
+  printf("certificate2:\nissuer =%s\n",str);
+  /* subject */
+  get_Name_type(cert_def,cert2,"certificate2.tbsCertificate.subject",str);
+  printf("subject=%s\n",str);
+
+
+  /* Verify sign */
+  len = sizeof(str) - 1;
+  result=asn1_read_value(cert2,"certificate2.signatureAlgorithm.algorithm"
+                         ,str,&len);
+
+  len = sizeof(str2) - 1;
+  result=asn1_read_value(cert_def,"PKIX1Implicit88.id-dsa-with-sha1",str2,&len);
+  if(!strcmp(str,str2)){  /* dsa-with-sha */
+
+    result=asn1_get_start_end_der(cert2,der,der_len,
+                                  "certificate2.tbsCertificate",&start,&end);
+
+    /* add the lines to calculate the sha on der[start]..der[end] */
+
+    len = sizeof(str) - 1;
+    result=asn1_read_value(cert2,"certificate2.signature",str,&len);
+
+    /* compare the previous value to signature ( with issuer public key) */ 
+  }
+
+  /* Use the next 3 lines to visit the certificate */
+  /*   printf("-----------------\n");   
+       asn1_visit_tree(cert2,"certificate2");  
+       printf("-----------------\n"); */
+
+
+  /* Clear the "certificate2" structure */
+  asn1_delete_structure(cert2);
+}
+
+
+/********************************************************/
+/* Function : main                                      */
+/* Description: reads the certificate description.      */
+/*              Creates a certificate and calculate     */
+/*              the der encoding. After that creates    */  
+/*              another certificate from der string     */
+/********************************************************/
+int
+main(int argc,char *argv[])
+{
+  int result,der_len;
+  unsigned char der[1024];
+  char file_name[128];
+  node_asn *PKIX1Implicit88;
+
+  result=asn1_create_tree(pkix_asn1_tab,&PKIX1Implicit88);
+
+  if(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 */
+#if 0
+   printf("-----------------\n");
+   asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");   
+   printf("-----------------\n"); 
+#endif
+
+  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/ChangeLog b/src/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..5597f55
--- /dev/null
@@ -0,0 +1,59 @@
+# Makefile.am - for the KSBA ASN.1 and X.509 library
+#       Copyright (C) 2001 g10 Code GmbH
+#      
+# This file is part of KSBA.
+# 
+# KSBA 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.
+# 
+# KSBA 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
+
+## Process this file with automake to produce Makefile.in
+
+#EXTRA_DIST = 
+BUILT_SOURCES = asn1-parse.c
+#bin_SCRIPTS = ksba-config
+#m4datadir = $(datadir)/aclocal
+#m4data_DATA = ksba.m4
+
+noinst_PROGRAMS = asn1-gentables ber-dump
+
+#include_HEADERS = ksba.h
+#lib_LTLIBRARIES = libksba.la
+
+#libksba_la_LDFLAGS = -version-info \
+#      @LIBKSBA_LT_CURRENT@:@LIBKSBA_LT_REVISION@:@LIBKSBA_LT_AGE@
+#libksba_la_INCLUDES = -I$(top_srcdir)/foo
+
+#libksba_la_SOURCES = \
+#      ksba.h \
+#      asn1-der.c asn1-der.h
+
+asn1_gentables_SOURCES = \
+       asn1-gentables.c \
+       asn1-parse.y asn1-parse.h \
+       asn1-func.c asn1-func.h \
+       asn1-der.c asn1-der.h \
+       util.c util.h   
+
+ber_dump_SOURCES = \
+       ber-dump.c \
+       ksba.h \
+       ber-decoder.c ber-decoder.h \
+       reader.c reader.h \
+       util.c util.h   
+
+
+
+
+
+
diff --git a/src/README.asn1 b/src/README.asn1
new file mode 100644 (file)
index 0000000..895b9b7
--- /dev/null
@@ -0,0 +1,465 @@
+
+------------------------------------------------
+--   Readme file for ASN1 parser              --
+--                                            --
+--   Originator:  Fabio Fiorina               --
+--   e-mail:      Fabio.Fiorina@alcatel.it    --
+--                fiorinaf@bgonline.it        --
+--   Changed: wk@gnupg.org 
+------------------------------------------------
+
+
+
+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:
+
+- write_value function for type ANY
+- the introduction of ENUMERATED type,
+- negative integer are allowed in ASN.1 syntax files,
+- PKIX1Implicit88.txt instead of Certificate.txt for the
+  Certificate description
+- functions naming 
+- an easier way to set INTEGER and get OBJECT IDENTFIER  
+
+
+
+FILE LIST
+---------
+asn1-readme.txt (ASN.readme.txt) this file
+
+asn1-parse.y    (cert_ASN.y)     bison input file
+
+asn1-func.c (cert_asn1.c)     functions for ASN1 parser and for
+                              reading and setting elements' value
+asn1-func.h (cert_asn1.h)     contains constants for the
+                              gnutls_asn1.c.  Must be included in files 
+                              that use ASN1 parser.
+asn1-der.c (cert_der.c)       functions for der encoding creation and
+                              analysis
+asn1-der.h (cert_der.h)       contains constants for the gnutls_der.c.
+                              Must be included in files 
+                              that use ASN1 parser.
+
+CertificateExample.c          example based on Appendix D.1 of rfc2459
+
+
+These files are not used:
+CrlExample.c         example based on Appendix D.4 of rfc2459
+PkixTabExample.c     the program used to create pkix_asn1_tab.c
+pkix.asn             certificate and CRL structures 
+pkix_asn1_tab.c      C vector to use with 'asn1_create_tree' function. 
+                     It was created from pkix.asn file.
+
+
+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:
+      
+      object_name {<object definition>}
+
+      DEFINITIONS <EXPLICIT or IMPLICIT> TAGS ::=
+
+      BEGIN 
+
+      <type and constants definitions>
+
+      END
+
+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:
+
+     INTEGER
+     ENUMERATED
+     BOOLEAN
+     OBJECT IDENTIFIER
+     NULL
+     BIT STRING
+     OCTET STRING
+     UTCTime
+     GeneralizedTime
+     SEQUENCE
+     SEQUENCE OF
+     SET 
+     SET OF
+     CHOICE
+     ANY
+     ANY DEFINED BY
+
+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.
+
+
+
+NAMING
+--------
+If you have this definitions:
+
+      Example { 1 2 3 4 }
+
+      DEFINITIONS EXPLICIT TAGS ::=
+
+      BEGIN 
+
+      Group ::= SEQUENCE {
+        id   OBJECT IDENTIFIER,
+        value  Value
+      }
+
+      Value ::= SEQUENCE {
+           value1  INTEGER,
+           value2  BOOLEAN 
+      }
+
+      END
+
+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.
+
+
+
+FUNCTIONS
+---------
+
+  int asn1_parser_asn1(char *file_name,node_asn **pointer);
+  --------------------------------------------------------
+
+Creates the structures needed to manage the definitions included in
+*FILE_NAME file.
+
+Input Parameter: 
+
+  char *file_name: specify the path and the name of file that
+                   contains ASN.1 declarations.
+
+Output Parameter:
+
+  node_asn **pointer : return the pointer to the structure created from 
+                       "file_name" ASN.1 declarations.  
+
+Return Value:
+
+  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);
+   --------------------------------------------
+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".
+
+Input Parameter: 
+  char *file_name: specify the path and the name of file that contains
+  ASN.1 declarations.
+
+Return Value:
+  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_create_tree(static_asn *root,node_asn **pointer);
+  --------------------------------------------------------- 
+Creates the structures needed to manage the ASN1 definitions. ROOT is
+a vector created by 'asn1_parser_asn1_file_c' function.
+
+Input Parameter: 
+  
+  static_asn *root: specify vector that contains ASN.1 declarations.
+
+Output Parameter:
+
+  node_asn **pointer : return the pointer to the structure created by
+  *ROOT ASN.1 declarations.
+
+Return Value:
+  ASN_OK: structure created correctly. 
+  ASN_GENERIC_ERROR: an error occured while structure creation.
+
+
+
+   int asn1_create_structure(node_asn *p_structure, char *source_name,
+                             node_asn **pointer,  char *dest_name);
+   ----------------------------------------------------------------
+Creates a structure called DEST_NAME of type SOURCE_NAME.
+
+Input Parameters:
+
+  node_asn *p_structure: pointer to the structure returned by
+                         "parser_asn1" function
+  char *source_name: the name of the type of the new structure (must
+  be inside p_structure).
+  char *dest_name: the name of the new structure.
+
+Output Parameter:
+
+  node_asn **pointer : pointer to the structure created. 
+
+Return Value:
+
+  ASN_OK: creation OK
+  ASN_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
+
+Example: using "pkix.asn"
+
+  result=asn1_create_structure(cert_def,"PKIX1Implicit88.Certificate",
+                               &cert,"certificate1");
+
+
+   int asn1_write_value(node_asn *pointer,char *name,
+                        unsigned char *value,int len);
+   --------------------------------------------------
+Set the value of one element inside a structure.
+
+Input Parameters:
+
+  node_asn *pointer: pointer to a structure
+
+  char *name: the name of the element inside the structure that you
+              want to set.
+
+  unsigned char *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.
+
+  int 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
+
+Return Value:
+
+  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="\x01\x02\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="\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_read_value(node_asn *pointer,char *name,unsigned char *value,int *len);
+   --------------------------------------------------------
+Returns the value of one element inside a structure.
+Input Parameters:
+  node_asn *pointer: pointer to a structure
+  char *name: the name of the element inside a structure that you want to read.
+Output Parameters:
+  unsigned char *value: vector that will contain the element's content. 
+                        VALUE must be a pointer to memory cells already allocated.
+  int *len: number of bytes of *value: value[0]..value[len-1]
+Return Value:
+  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_create_der(node_asn *pointer,char *name,unsigned char *der,int *len);
+   ------------------------------------------------------
+Creates the DER encoding for the NAME structure (inside *POINTER structure).
+Input Parameters:
+  node_asn *pointer: pointer to a structure
+  char *name: the name of the structure you want to encode (it must be inside *POINTER).
+Output Parameters:
+  unsigned char *der: vector that will contain the DER encoding. 
+                      DER must be a pointer to memory cells already allocated.
+  int *len: number of bytes of *der: der[0]..der[len-1]
+Return Value:
+  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_get_der(node_asn *pointer,char *name,unsigned char *der,int len);
+   --------------------------------------------------------------------------
+
+Fill the structure *POINTER with values of a DER encoding string. The
+sructure must just be created with function 'create_stucture'.
+
+Input Parameters:
+  node_asn *pointer:  Pointer to the structure that you want to fill.
+  unsigned char *der: Vector that contains the DER encoding. 
+  int len:            Number of bytes of *der: der[0]..der[len-1]
+
+Return Value:
+  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_start_end_der(node_asn *pointer,
+                              unsigned char *der, int len,
+                              char *name_element, int *start, int *end)
+   --------------------------------------------------------------------
+
+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.
+
+Input Parameters:
+
+  node_asn *pointer:  The pointer to the structure that is already
+                      setted with DER string.
+  unsigned char *der: Vector that contains the DER encoding. 
+  int len:            Number of bytes of *der: der[0]..der[len-1]
+  char *name_element: An element of NAME structure.
+
+Output Parameters:
+
+  int *start: The position of the first byte of NAME_ELEMENT
+              decoding (der[*start]) 
+  int *end:   The position of the last byte of NAME_ELEMENT
+              decoding (der[*end])
+
+Return Value:
+
+  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_delete_structure(node_asn *pointer);
+   ---------------------------------
+Deletes the structure *POINTER. 
+Input Parameters:
+  node_asn *pointer: pointer to the structure that you want to delete.
+Return Value:
+  ASN_OK: everything OK
+  ASN_ELEMENT_NOT_FOUND: pointer==NULL.
+
+
+   void asn1_visit_tree(node_asn *pointer,char *name);
+   ---------------------------------------------------
+
+Prints on the standard output the structure's tree starting from the
+NAME element inside the structure *POINTER.
+
+
+
+FUTURE DEVELOPMENTS
+-------------------
+1. type REAL 
+2. 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.
+3. improve the 'visit_tree' function and change the output from stdout
+   to a null terminated string.  
+
+
+
+
+
+
diff --git a/src/asn1-der.c b/src/asn1-der.c
new file mode 100644 (file)
index 0000000..1a93bea
--- /dev/null
@@ -0,0 +1,1649 @@
+/* asn1-der.c - Manage DER encoding
+ *      Copyright (C) 2000,2001  Fabio Fiorina
+ *      Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * 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 <config.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "asn1-der.h"
+#include "util.h"
+#include "reader.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, v2;
+  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)
+{
+  unsigned long ans;
+  int punt, ris;
+
+  /* tag format:  CCFTTTTT
+   *      C = class: 00 = universal
+   *                 01 = application
+   *                 10 = context specific
+   *                 11 = private
+   *      F = form: 0 = primitive
+   *                1 = constructed
+   *      T = tag value
+   * For tags 0..30 the length is one byte
+   * For tags >= 31 the last octect is is marked by a cleared bit 7.
+   */
+  *class = der[0] & 0xE0;  /* class includes the form */
+  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;
+
+  strcpy (temp, str);
+  strcat (temp, " ");
+
+  counter = 0;
+  n_start = temp;
+  while ((n_end = strchr (n_start, ' ')))
+    {
+      *n_end = 0;
+      val = strtoul (n_start, NULL, 10);
+      counter++;
+
+      if (counter == 1)
+       val1 = val;
+      else if (counter == 2)
+       {
+         der[0] = 40 * val1 + val;
+         *der_len = 1;
+       }
+      else
+       {
+         first = 0;
+         for (k = 4; k >= 0; k--)
+           {
+             bit7 = (val >> (k * 7)) & 0x7F;
+             if (bit7 || first || !k)
+               {
+                 if (k)
+                   bit7 |= 0x80;
+                 der[*der_len] = bit7;
+                 (*der_len)++;
+                 first = 1;
+               }
+           }
+
+       }
+      n_start = n_end + 1;
+    }
+
+  _asn1_length_der (*der_len, NULL, &len_len);
+  memmove (der + len_len, der, *der_len);
+  _asn1_length_der (*der_len, der, &len_len);
+  *der_len += len_len;
+}
+
+
+void
+_asn1_get_objectid_der (unsigned char *der, int *der_len, unsigned char *str)
+{
+  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;
+
+  strcpy (str, _asn1_ltostr (val1, temp));
+  strcat (str, " ");
+  strcat (str, _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))
+       {
+         strcat (str, " ");
+         strcat (str, _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 tag_len, is_tag_implicit, len2, len3;
+  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_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, len2, len3;
+  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 = xmalloc (sizeof (struct vet));
+      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 = xmalloc (p_vet->end - counter);
+             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);
+             xfree (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;
+      xfree (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 = xmalloc (sizeof (struct vet));
+      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 = xmalloc (p_vet->end - counter);
+             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);
+             xfree (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;
+      xfree (p_vet);
+      p_vet = first;
+    }
+}
+
+
+int
+asn1_create_der (node_asn * root, char *name, unsigned char *der, int *len)
+{
+  node_asn *node, *p, *p2, *p3;
+  char temp[20];
+  int counter, counter_old, len2, len3, len4, 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:
+ * @root: Pointer to the structure that you want to fill.
+ * @der:  Buffer that contains the DER encoding. 
+ * @len:  Length of this buffer
+ * 
+ * Fill the structure @root with the DER encoded buffer @der of
+ * length @len. The structure must have been created
+ * using asn1_create_stucture().
+ * 
+ * Return value: 
+ *   ASN_OK:                 DER encoding OK
+ *   ASN_ELEMENT_NOT_FOUND:  NAME is not a valid element.
+ *   ASN_TAG_ERROR:          Encoding does not match the structure
+ *   ASN_DER_ERROR:          Ditto.
+ **/
+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;
+  long val;
+
+  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;
+       } /* move != UP */
+
+      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);
+             _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 = xmalloc (len2 + len3 + len4);
+             _asn1_octet_der (der + counter, len2 + len3, temp2, &len4);
+             _asn1_set_value (p, temp2, len4);
+             xfree (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;
+}
+
+
+
+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;
+  char temp[128];
+  int counter, len2, len3, move, ris;
+  unsigned char class;
+  unsigned int tag;
+  long val;
+
+  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 ((p == node_to_find) && (move != UP))
+       *start = counter;
+
+      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 (type_field (p->type) == TYPE_CHOICE)
+           {
+             p = p->down;
+             ris = _asn1_extract_tag_der (p, der + counter, &len2);
+           }
+
+         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/src/asn1-der.h b/src/asn1-der.h
new file mode 100644 (file)
index 0000000..3971d40
--- /dev/null
@@ -0,0 +1,61 @@
+/* asn1-der.h - definitions for DER parsing
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *      Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * 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 ASN1_DER_H
+#define ASN1_DER_H
+
+#include "asn1-func.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);
+
+
+#endif /*ASN1_DER_H*/
+
+
+
+
+
diff --git a/src/asn1-func.c b/src/asn1-func.c
new file mode 100755 (executable)
index 0000000..7fd940a
--- /dev/null
@@ -0,0 +1,2023 @@
+/* asn1-func.c - Manage ASN.1 definitions
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *      Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "asn1-func.h"
+#include "asn1-der.h"
+#include "util.h"
+
+
+#define UP     1
+#define RIGHT  2
+#define DOWN   3
+
+
+int parse_mode;
+
+
+/******************************************************/
+/* Function : add_node                                */
+/* Description: adds an element to the list of nodes. */
+/* Parameters:                                        */
+/*   unsigned int type: node description (see TYPE_   */
+/*                      and CONST_ constants)         */
+/* Return: node_asn                                   */
+/*   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 = xmalloc (sizeof (node_asn));
+
+  punt->left = NULL;
+  punt->name = NULL;
+  punt->type = type;
+  punt->value = NULL;
+  punt->down = NULL;
+  punt->right = NULL;
+
+  return punt;
+}
+
+
+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)
+    {
+      xfree (node->value);
+      node->value = NULL;
+    }
+  if (!len)
+    return node;
+  node->value = xmalloc (len);
+  memcpy (node->value, value, len);
+  return node;
+}
+
+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)
+    {
+      xfree (node->name);
+      node->name = NULL;
+    }
+
+  if (name == NULL)
+    return node;
+
+  if (strlen (name))
+    {
+      node->name = xmalloc (strlen (name) + 1);
+      strcpy (node->name, name);
+    }
+  else
+    node->name = NULL;
+  return 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;
+}
+
+
+node_asn *
+_asn1_get_right (node_asn * node)
+{
+  if (parse_mode == PARSE_MODE_CHECK)
+    return NULL;
+
+  if (node == NULL)
+    return NULL;
+  return node->right;
+}
+
+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;
+}
+
+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;
+}
+
+node_asn *
+_asn1_get_down (node_asn * node)
+{
+  if (parse_mode == PARSE_MODE_CHECK)
+    return NULL;
+
+  if (node == NULL)
+    return NULL;
+  return node->down;
+}
+
+char *
+_asn1_get_name (node_asn * node)
+{
+  if (parse_mode == PARSE_MODE_CHECK)
+    return NULL;
+
+  if (node == NULL)
+    return NULL;
+  return node->name;
+}
+
+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;
+}
+
+void
+_asn1_remove_node (node_asn * node)
+{
+  node_asn *punt, *punt_prev;
+
+  if (node == NULL)
+    return;
+
+  xfree (node->name);
+  xfree (node->value);
+  xfree (node);
+}
+
+
+
+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, '.');
+  if (n_end)
+    {
+      memcpy (n, n_start, n_end - n_start);
+      n[n_end - n_start] = 0;
+      n_start = n_end;
+      n_start++;
+    }
+  else
+    {
+      strcpy (n, n_start);
+      n_start = NULL;
+    }
+
+  p = pointer;
+  while (p)
+    {
+      if ((p->name) && (!strcmp (p->name, n)))
+       break;
+      else
+       p = p->right;
+    }
+
+  if (p == NULL)
+    return NULL;
+
+  while (n_start)
+    {
+      n_end = strchr (n_start, '.');
+      if (n_end)
+       {
+         memcpy (n, n_start, n_end - n_start);
+         n[n_end - n_start] = 0;
+         n_start = n_end;
+         n_start++;
+       }
+      else
+       {
+         strcpy (n, n_start);
+         n_start = NULL;
+       }
+
+      if (p->down == NULL)
+       return NULL;
+
+      p = p->down;
+
+      if (!strcmp (n, "?LAST"))
+       {
+         if (p == NULL)
+           return NULL;
+         while (p->right)
+           p = p->right;
+       }
+      else
+       {
+         while (p)
+           {
+             if ((p->name) && (!strcmp (p->name, n)))
+               break;
+             else
+               p = p->right;
+           }
+         if (p == NULL)
+           return NULL;
+       }
+    }
+
+  return p;
+}
+
+
+node_asn *
+_asn1_find_left (node_asn * node)
+{
+  if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
+    return NULL;
+
+  return node->left;
+}
+
+
+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;
+}
+
+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[k2 - k] = val[k2];
+    }
+  *len = 4 - k;
+
+  return ASN_OK;
+}
+
+
+/**
+ * Creates the structures needed to manage the ASN1 definitions. ROOT is
+ * a vector created by 'asn1_parser_asn1_file_c' function.
+ * 
+ * Input Parameter: 
+ *   
+ *   static_asn *root: specify vector that contains ASN.1 declarations.
+ * 
+ * Output Parameter:
+ * 
+ *   node_asn **pointer : return the pointer to the structure created by
+ *   *ROOT ASN.1 declarations.
+ * 
+ * Return Value:
+ *   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;
+               }
+           }
+       }
+      k++;
+    }
+
+  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;
+  strcat (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;
+      strcat (file_out_name, "_asn1_tab.c");
+    }
+  else
+    {
+      strncpy (file_out_name, out_name, sizeof (file_out_name));
+    }
+  file = fopen (file_out_name, "w");
+
+  if (file == NULL)
+    return ASN_FILE_NOT_FOUND;
+
+  fprintf (file, "\n#include \"asn1-func.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;
+}
+
+
+void
+asn1_visit_tree (node_asn * pointer, char *name)
+{
+  node_asn *p, *root;
+  int k, indent = 0, len, len2, len3;
+  unsigned char class;
+  unsigned long tag;
+
+  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)
+           {
+             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)
+           {
+             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)
+           {
+             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)
+           {
+             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)
+           {
+             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;
+               }
+           }
+       }
+    }
+}
+
+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:
+                 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);
+
+}
+
+
+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
+    {
+      strcpy (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;
+  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);
+  temp = xmalloc (10);
+  if (p->name == NULL)
+    strcpy (temp, "?1");
+  else
+    {
+      n = strtol (p->name + 1, NULL, 0);
+      n++;
+      temp[0] = '?';
+      _asn1_ltostr (n, temp + 1);
+    }
+  _asn1_set_name (p2, temp);
+  xfree (temp);
+
+  return ASN_OK;
+}
+
+
+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, val[4];
+  int len2, k, k2, negative;
+  unsigned char *root, *n_end;
+
+  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 = xmalloc (4);
+             _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 = xmalloc (4);
+                         _asn1_convert_integer (p->value, value_temp, 4,
+                                                &len);
+                         break;
+                       }
+                   }
+                 p = p->right;
+               }
+             if (p == NULL)
+               return ASN_VALUE_NOT_VALID;
+           }
+       }
+      else
+       {
+         value_temp = xmalloc (len);
+         memcpy (value_temp, value, len);
+       }
+
+
+      if (value_temp[0] & 0x80)
+       negative = 1;
+      else
+       negative = 0;
+
+      if (negative && (type_field (node->type) == TYPE_ENUMERATED))
+       {
+         xfree (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 = xmalloc (len - k + len2);
+      _asn1_octet_der (value_temp + k, len - k, temp, &len2);
+      _asn1_set_value (node, temp, len2);
+
+      xfree (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 = xmalloc (4);
+             _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 = xmalloc (4);
+                         _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);
+           }
+         xfree (default_temp);
+       }
+      xfree (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 = xmalloc (len + len2);
+      _asn1_octet_der (value, len, temp, &len2);
+      _asn1_set_value (node, temp, len2);
+      xfree (temp);
+      break;
+    case TYPE_BIT_STRING:
+      _asn1_length_der ((len >> 3) + 2, NULL, &len2);
+      temp = xmalloc ((len >> 3) + 2 + len2);
+      _asn1_bit_der (value, len, temp, &len2);
+      _asn1_set_value (node, temp, len2);
+      xfree (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 = xmalloc (len + len2);
+      _asn1_octet_der (value, len, temp, &len2);
+      _asn1_set_value (node, temp, len2);
+      xfree (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) \
+       if (ptr_size < data_size) { \
+               return ASN_MEM_ERROR; \
+       } else { \
+               memcpy( ptr, data, data_size); \
+               *len = data_size; \
+       }
+
+#define PUT_STR_VALUE( ptr, ptr_size, data) \
+       if (ptr_size <= strlen(data)) { \
+               return ASN_MEM_ERROR; \
+       } else { \
+               strcpy( ptr, data); \
+               *len = strlen(ptr)+1; \
+       }
+
+#define ADD_STR_VALUE( ptr, ptr_size, data) \
+       if (ptr_size <= strlen(data)+strlen(ptr)) { \
+               return ASN_MEM_ERROR; \
+       } else { \
+               strcat( ptr, data); \
+               *len = strlen(ptr)+1; \
+       }
+
+
+int
+asn1_read_value (node_asn * root, char *name, unsigned char *value, int *len)
+{
+  node_asn *node, *p;
+  int len2, len3;
+  unsigned long tag;
+  unsigned char class;
+  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
+       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)
+       {
+         strcpy (value, "");
+         p = node->down;
+         while (p)
+           {
+             if (type_field (p->type) == TYPE_CONSTANT)
+               {
+                 ADD_STR_VALUE (value, value_size, p->value);
+                 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:
+      if (_asn1_get_octet_der (node->value, &len2, value, value_size, len) !=
+         ASN_OK)
+       return ASN_MEM_ERROR;
+      break;
+    case TYPE_BIT_STRING:
+      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:
+      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;
+}
+
+
+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)
+       {
+         strcpy (name2, node->name);
+         strcat (name2, ".");
+         strcat (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]))
+               {
+                 strcpy (name2, node->name);
+                 strcat (name2, ".");
+                 strcat (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, *p2;
+  char negative;
+  unsigned char val[4], val2[5], temp;
+  int len, k, force_exit;
+
+  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)
+           {
+             strcpy (name2, root->name);
+             strcat (name2, ".");
+             strcat (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], *c;
+  int move;
+
+  if (node == NULL)
+    return ASN_ELEMENT_NOT_FOUND;
+
+  strcpy (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]))
+                   {
+                     strcpy (name2, name_root);
+                     strcat (name2, ".");
+                     strcat (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/src/asn1-func.h b/src/asn1-func.h
new file mode 100755 (executable)
index 0000000..9c3b499
--- /dev/null
@@ -0,0 +1,210 @@
+/* asn1-func.h - definitions for asn1-func.c
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *      Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * 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 ASN1_FUNC_H
+#define ASN1_FUNC_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
+
+/******************************************************/
+/* Structure definition used for the node of the tree */
+/* that rappresent an ASN.1 DEFINITION.               */
+/******************************************************/
+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 */ 
+}; 
+typedef struct node_asn_struct node_asn; /* fixme: replace by below */
+typedef struct node_asn_struct *AsnNode; 
+
+
+
+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_create_static_structure(node_asn *pointer,
+                                  char *file_name, char* out_name);
+
+int _asn1_set_default_tag(node_asn *node);
+int _asn1_check_identifier(node_asn *node);
+int _asn1_change_integer_value(node_asn *node);
+int _asn1_delete_not_used(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_expand_object_id(node_asn *node);
+
+
+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);
+
+#endif /*ASN1_FUNC_H*/
+
diff --git a/src/asn1-gentables.c b/src/asn1-gentables.c
new file mode 100644 (file)
index 0000000..98d53c2
--- /dev/null
@@ -0,0 +1,110 @@
+/* asn1-gentables.c - Tool to create required ASN tables
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "asn1-parse.h"
+#include "asn1-func.h"
+
+#define PGMNAME "asn1-gentables"
+
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
+# define  ATTR_PRINTF(a,b)  __attribute__ ((format (printf,a,b)))
+#else
+# define  ATTR_PRINTF(a,b) 
+#endif
+
+/* keep track of parsing error */
+static int error_counter;
+
+
+static void print_error (const char *fmt, ... )  ATTR_PRINTF(1,2);
+
+
+
+static void
+print_error (const char *fmt, ... )  
+{
+  va_list arg_ptr ;
+
+  va_start (arg_ptr, fmt);
+  fputs (PGMNAME ": ", stderr);
+  vfprintf (stderr, fmt, arg_ptr);
+  va_end (arg_ptr);
+  error_counter++;
+  
+}
+
+
+static void
+one_file (FILE *fp, const char *fname)
+{
+  int rc;
+  
+  rc = asn1_parser_asn1_file_c (fname);
+  if (rc==ASN_SYNTAX_ERROR)
+      print_error ("error parsing `%s': syntax error\n", fname);
+  else if (rc==ASN_IDENTIFIER_NOT_FOUND)
+      print_error ("error parsing `%s': identifier not found\n", fname);
+  else if (rc==ASN_FILE_NOT_FOUND)
+      print_error ("error parsing `%s': file not found\n", fname);
+  else if (rc)
+      print_error ("error parsing `%s': unknown error %d\n", fname, rc);
+  
+}
+
+
+int
+main (int argc, char **argv)
+{
+  if (!argc || (argc > 1 &&
+                (!strcmp (argv[1],"--help") || !strcmp (argv[1],"-h"))) )
+    {
+      fputs ("usage: asn1-gentables [files.asn]\n", stderr);
+      return 0;
+    }
+  
+  argc--; argv++;
+  
+  if (!argc)
+    one_file (stdin, "-");
+  else
+    {
+      for (; argc; argc--, argv++) 
+        {
+          FILE *fp;
+          
+          fp = fopen (*argv, "r");
+          if (!fp)
+              print_error ("can't open `%s': %s\n", *argv, strerror (errno));
+          else
+            {
+              one_file (fp, *argv);
+              fclose (fp);
+            }
+        }
+    }
+  return error_counter? 1:0;
+}
diff --git a/src/asn1-parse.h b/src/asn1-parse.h
new file mode 100644 (file)
index 0000000..02a89eb
--- /dev/null
@@ -0,0 +1,30 @@
+/* asn1-parse.h - definitions for asn1-parse.y
+ *      Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * 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 ASN1_PARSE_H
+#define ASN1_PARSE_H
+
+int asn1_parser_asn1_file_c (char *file_name);
+
+
+
+
+#endif /*ASN1_PARSE_H*/
+
diff --git a/src/asn1-parse.y b/src/asn1-parse.y
new file mode 100755 (executable)
index 0000000..961846e
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ *      Copyright (C) 2000,2001 Fabio Fiorina
+ *      Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * 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 <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "asn1-parse.h"
+#include "asn1-func.h"
+
+#define YYERROR_VERBOSE = 1
+
+#define MAX_STRING_LENGTH 129
+
+FILE *file_asn1;  /* Pointer to file to parse */
+extern int parse_mode;
+int result_parse;
+node_asn *p_tree;
+
+int yylex(void);
+void yyerror (const char *s);
+
+%}
+
+
+%union {
+  unsigned int constant;
+  char str[MAX_STRING_LENGTH];
+  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)}
+;
+
+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};
+
+static int lineno = 1;  /* keep track of input linenumbers */
+
+/*************************************************************/
+/*  Function: yylex                                          */
+/*  Description: looks for tokens in file_asn1 pointer file. */
+/*  Return: int                                              */
+/*    Token identifier or ASCII code or 0(zero: End Of File) */
+/*************************************************************/
+int 
+yylex() 
+{
+  int c,counter=0,k;
+  char string[MAX_STRING_LENGTH];  
+
+  while (1)
+    {
+      while ( (c=fgetc(file_asn1))==' ' || c=='\t')
+        ;
+      if (c =='\n')
+        {
+          lineno++;
+          continue;
+        }
+      if(c==EOF)
+        return 0;
+
+      if ( c=='(' || c==')' || c=='[' || c==']' 
+           || c=='{' || c=='}' || c==',' || c=='.' || c=='+')
+        return c;
+
+      if (c=='-')
+        {
+          if ( (c=fgetc(file_asn1))!='-')
+            {
+              ungetc(c,file_asn1);
+              return '-';
+            }
+          else
+            {
+              /* A comment finishes at the end of line */
+              counter=0;
+              while ( (c=fgetc(file_asn1))!=EOF && c != '\n' )
+                ;
+              if (c==EOF)
+                return 0;
+              else 
+                continue; /* repeat the search */
+            }
+        }
+      if (counter==sizeof (string))
+        {
+          fprintf (stderr,"%s:%d: token too long\n", "myfile:", lineno);
+          return 0; /* EOF */
+        }
+      
+      string[counter++]=c;
+      while ( !((c=fgetc(file_asn1))==EOF
+                || c==' '|| c=='\t' || c=='\n' 
+                || c=='(' || c==')' || c=='[' || c==']' 
+                || c=='{' || c=='}' || c==',' || c=='.'))
+        { 
+          if (counter==sizeof (string))
+            {
+              fprintf (stderr,"%s:%d: token too long\n", "myfile:", lineno);
+              return 0; /* EOF */
+            }
+          string[counter++]=c;
+        }
+      ungetc(c,file_asn1);
+      string[counter]=0;
+      /*fprintf (stderr, "yylex token `%s'\n", string);*/
+
+      /* Is STRING a number? */
+      for (k=0; k<counter; k++) 
+        {
+          if(!isdigit(string[k])) 
+            break;
+        }
+      if (k>=counter)
+        {
+          strcpy (yylval.str,string);  
+          return NUM;
+        }
+      
+      /* Is STRING a keyword? */
+      for (k=0; k<(sizeof(key_word)/sizeof(char*));k++ )
+        {
+          if (!strcmp(string,key_word[k])) 
+            return key_word_token[k]; 
+        }
+      
+      /* STRING is an IDENTIFIER */
+      strcpy(yylval.str,string);
+      return IDENTIFIER;
+    }
+}
+
+
+/*************************************************************/
+/*  Function: parser_asn1                                    */
+/*  Description: function used to start the parse algorithm. */
+/*  Parameters:                                              */
+/*    char *file_name : file name to parse                   */
+/*  Return: int                                              */
+/*                                                           */
+/*************************************************************/
+int 
+asn1_parser_asn1(char *file_name,node_asn **pointer)
+{
+  /*  yydebug=1;  */
+
+  p_tree=NULL;
+  *pointer=NULL;
+  
+  file_asn1=fopen(file_name,"r");
+
+  if(file_asn1==NULL) return ASN_FILE_NOT_FOUND;
+
+  result_parse=ASN_OK;
+
+  parse_mode=PARSE_MODE_CHECK;
+  yyparse();
+
+  if(result_parse==ASN_OK){
+    fclose(file_asn1);
+    file_asn1=fopen(file_name,"r");
+
+    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;
+}
+
+
+
+/*************************************************************/
+/*  Function: parser_asn1_file_c                             */
+/*  Description: function that generates a C structure from  */
+/*               an ASN1 file                                */
+/*  Parameters:                                              */
+/*    char *file_name : file name to parse                   */
+/*  Return: int                                              */
+/*                                                           */
+/*************************************************************/
+int 
+asn1_parser_asn1_file_c(char *file_name)
+{
+  int result;
+
+  /*  yydebug=1;  */
+
+  p_tree=NULL;
+    
+  file_asn1=fopen(file_name,"r");
+
+  if(file_asn1==NULL) return ASN_FILE_NOT_FOUND;
+
+  result_parse=ASN_OK;
+
+  parse_mode=PARSE_MODE_CHECK;
+  yyparse();
+
+  if(result_parse==ASN_OK){
+    fclose(file_asn1);
+    file_asn1=fopen(file_name,"r");
+
+    parse_mode=PARSE_MODE_CREATE;
+    yyparse();
+
+    result=_asn1_create_static_structure(p_tree,file_name, NULL);
+
+    asn1_delete_structure(p_tree);
+   }
+
+  fclose(file_asn1);
+
+  parse_mode=PARSE_MODE_CREATE;
+
+  return result_parse;
+}
+
+
+/*************************************************************/
+/*  Function: yyerror                                        */
+/*  Description: function used with syntax errors            */
+/*  Parameters:                                              */
+/*    char *s : error description                            */
+/*  Return: int                                              */
+/*                                                           */
+/*************************************************************/
+void 
+yyerror (const char *s)
+{
+  /* Sends the error description to stdout */
+  fprintf (stderr, "%s:%d: %s\n","myfile", lineno, s); 
+  result_parse = ASN_SYNTAX_ERROR;
+}
diff --git a/src/ber-decoder.c b/src/ber-decoder.c
new file mode 100644 (file)
index 0000000..b1c4a62
--- /dev/null
@@ -0,0 +1,383 @@
+/* ber-decoder.c - Basic Encoding Rules Decoder
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "util.h"
+
+#include "ksba.h"
+#include "asn1-func.h"
+#include "ber-decoder.h"
+
+struct ber_decoder_s {
+  AsnNode module;    /* the ASN.1 structure */
+  KsbaReader reader;
+  const char *last_errdesc; /* string with the error description */
+  int non_der; /* set if the encoding is not DER conform */
+};
+
+
+static int
+set_error (BerDecoder d, AsnNode node, const char *text)
+{
+  fprintf (stderr,"ber-decoder: node `%s': %s\n", 
+           node? node->name:"?", text);
+  d->last_errdesc = text;
+  return KSBA_BER_Error;
+}
+
+
+static int
+eof_or_error (BerDecoder d, int premature)
+{
+  if (ksba_reader_error (d->reader))
+    {
+      set_error (d, NULL, "read error");
+      return KSBA_Read_Error;
+    }
+  if (premature)
+    return set_error (d, NULL, "premature EOF");
+  return -1;
+}
+
+static const char *
+universal_tag_name (unsigned long no)
+{
+  static const char *names[31] = {
+    "[End Tag]",
+    "BOOLEAN",
+    "INTEGER",
+    "BIT STRING",
+    "OCTECT STRING",
+    "NULL",
+    "OBJECT IDENTIFIER",
+    "ObjectDescriptor",
+    "EXTERNAL",
+    "REAL",
+    "ENUMERATED",
+    "EMBEDDED PDV",
+    "UTF8String",
+    "RELATIVE-OID",
+    "[UNIVERSAL 14]",
+    "[UNIVERSAL 15]",
+    "SEQUENCE",
+    "SET",
+    "NumericString",
+    "PrintableString",
+    "TeletexString",
+    "VideotexString",
+    "IA4String",
+    "UTCTime",
+    "GeneralizedTime",
+    "GraphicString",
+    "VisibleString",
+    "GeneralString",
+    "UniversalString",
+    "CHARACTER STRING",
+    "BMPString"
+  };
+
+  return no < DIM(names)? names[no]:NULL;
+}
+
+
+
+\f
+BerDecoder
+_ksba_ber_decoder_new (void)
+{
+  BerDecoder d;
+
+  d = xtrycalloc (1, sizeof *d);
+  if (!d)
+    return NULL;
+
+  return d;
+}
+
+void
+_ksba_ber_decoder_release (BerDecoder d)
+{
+  xfree (d);
+}
+
+/**
+ * _ksba_ber_decoder_set_module:
+ * @d: Decoder object 
+ * @module: Modul structure
+ * 
+ * Initialize the decoder with the ASN.1 module.  Note, that this is a
+ * shallow copy of the module.  FIXME: What about ref-counting of
+ * AsnNodes?
+ * 
+ * Return value: 0 on success or an error code
+ **/
+KsbaError
+_ksba_ber_decoder_set_module (BerDecoder d, AsnNode module)
+{
+  if (!d || !module)
+    return KSBA_Invalid_Value;
+  if (d->module)
+    return KSBA_Conflict; /* module already set */
+
+  d->module = module;
+  return 0;
+}
+
+
+KsbaError
+_ksba_ber_decoder_set_reader (BerDecoder d, KsbaReader r)
+{
+  if (!d || !r)
+    return KSBA_Invalid_Value;
+  if (d->reader)
+    return KSBA_Conflict; /* reader already set */
+  
+  d->reader = r;
+  return 0;
+}
+
+\f
+/**********************************************
+ ***********  decoding machinery  *************
+ **********************************************/
+enum tag_class {
+  CLASS_UNIVERSAL = 0,
+  CLASS_APPLICATION = 1,
+  CLASS_CONTEXT = 2,
+  CLASS_PRIVATE =3
+};
+
+struct tag_info {
+  enum tag_class class;
+  int is_constructed;
+  unsigned long tag;
+};
+
+
+static int
+read_byte (KsbaReader reader)
+{
+  unsigned char buf;
+  size_t nread;
+  int rc;
+
+  do
+    rc = ksba_reader_read (reader, &buf, 1, &nread);
+  while (!rc && !nread);
+  return rc? -1: buf;
+}
+
+/*
+ * Read the tag and the length part from the TLV triplet. 
+ */
+static KsbaError
+read_tl (BerDecoder d, struct tag_info *r_tag, 
+         unsigned long *r_length, int *r_indefinite, size_t *r_nread)
+{
+  int c;
+  unsigned long tag;
+
+  *r_length = 0;
+  *r_indefinite = 0;
+  *r_nread = 0;
+  /* Get the tag */
+  c = read_byte (d->reader);
+  if (c==-1)
+    return eof_or_error (d, 0);
+  ++*r_nread;
+  r_tag->class = (c & 0xc0) >> 6;
+  r_tag->is_constructed = !!(c & 0x20);
+  tag = c & 0x1f;
+  if (tag == 0x1f)
+    {
+      tag = 0;
+      do
+        {
+          /* fixme: check for overflow of out datatype */
+          tag <<= 7;
+          c = read_byte (d->reader);
+          if (c == -1)
+            return eof_or_error (d, 1);
+          ++*r_nread;
+          tag |= c & 0x7f;
+        }
+      while (c & 0x80);
+    }
+  r_tag->tag = tag;
+
+  /* Get the length */
+  c = read_byte (d->reader);
+  if (c == -1)
+    return eof_or_error (d, 1);
+  ++*r_nread;
+  if ( !(c & 0x80) )
+    *r_length = c;
+  else if (c == 0x80)
+    {
+      *r_indefinite = 1;
+      d->non_der = 1;
+    }
+  else if (c == 0xff)
+      return set_error (d, NULL, "forbidden length value");
+  else
+    {
+      unsigned long len = 0;
+      int count = c & 0x7f;
+
+      /* fixme: check for overflow of our length type */
+      for (; count; count--)
+        {
+          len <<= 8;
+          c = read_byte (d->reader);
+          if (c == -1)
+            return eof_or_error (d, 1);
+          ++*r_nread;
+          len |= c & 0xff;
+        }
+      *r_length = len;
+    }
+
+  return 0;
+}
+
+
+
+KsbaError
+_ksba_ber_decoder_decode (BerDecoder d)
+{
+  
+  
+  return -1;
+}
+
+/**
+ * _ksba_ber_decoder_dump:
+ * @d: Decoder object
+ * 
+ * Dump a textual representation of the encoding to the given stream.
+ * 
+ * Return value: 
+ **/
+KsbaError
+_ksba_ber_decoder_dump (BerDecoder d, FILE *fp)
+{
+  struct tag_info ti;
+  int rc;
+  unsigned long length, tlvlen;
+  int is_indefinite;
+  int depth = 0;
+  size_t nread;
+  struct {
+    unsigned long nleft;
+    unsigned long length;
+    int ndef;
+  } stack[100];
+
+  while ( !(rc = read_tl (d, &ti, &length, &is_indefinite, &nread)) )
+    {
+      const char *tagname = NULL;
+
+      /* Without thsi kludge some example certs can't be parsed */
+      if (ti.class == CLASS_UNIVERSAL && !ti.tag)
+        length = 0;
+
+      tlvlen = length + nread;
+      if (ti.class == CLASS_UNIVERSAL)
+        tagname = universal_tag_name (ti.tag);
+
+      fprintf (fp, "%*s", depth*2, "");
+      if (tagname)
+        fputs (tagname, fp);
+      else
+        fprintf (fp, "[%s %lu]", 
+                 ti.class == CLASS_UNIVERSAL? "UNIVERSAL" :
+                 ti.class == CLASS_APPLICATION? "APPLICATION" :
+                 ti.class == CLASS_CONTEXT? "CONTEXT-SPECIFIC" : "PRIVATE",
+                 ti.tag);
+      fprintf (fp, " %c n=%u", ti.is_constructed? 'c':'p', nread);
+      if (is_indefinite)
+        fputs (" indefinite length\n", fp);
+      else
+        fprintf (fp, " %lu octets\n", length);
+
+      if (!ti.is_constructed)
+        { /* primitive: skip value */
+          int n;
+
+          for (n=0; n < length; n++)
+            if (read_byte (d->reader) == -1)
+              return eof_or_error (d, 1);
+        }
+
+      if (depth && !ti.is_constructed)
+        {
+          if (stack[depth-1].ndef)
+            {
+              if (ti.class == CLASS_UNIVERSAL && !ti.tag && !length)
+                depth--;
+            }
+          else
+            {
+              if (tlvlen > stack[depth-1].nleft)
+                {
+                  fprintf (fp, "error: "
+                           "object length field %lu octects too large\n",
+                           (tlvlen - stack[depth-1].nleft) );
+                  stack[depth-1].nleft = 0;
+                }
+              else
+                stack[depth-1].nleft -= tlvlen;
+/*                fprintf (fp, "depth %d %lu bytes of %lu left\n", */
+/*                         depth, stack[depth-1].nleft, stack[depth-1].length); */
+              if (depth && !stack[depth-1].nleft)
+                  depth--;
+            }
+        }
+
+      if (ti.is_constructed)
+        {  /* constructed */
+          if (depth == DIM(stack))
+            {
+              fprintf (fp, "error: objects nested too deep\n");
+              rc = KSBA_General_Error;
+              break;
+            }
+          stack[depth].nleft  = length; 
+          stack[depth].length = length;
+          stack[depth].ndef = is_indefinite;
+          depth++;
+        }
+
+
+
+    }
+
+  if (rc==-1 && !d->last_errdesc)
+    rc = 0;
+
+  return rc;
+}
+
+
+
diff --git a/src/ber-decoder.h b/src/ber-decoder.h
new file mode 100644 (file)
index 0000000..a8cbc33
--- /dev/null
@@ -0,0 +1,41 @@
+/* ber-decoder.h - Definitions for the Basic Encoding Rules Decoder
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 BER_DECODER_H
+#define BER_DECODER_H 1
+
+#include "asn1-func.h"
+
+struct ber_decoder_s;
+typedef struct ber_decoder_s *BerDecoder;
+
+BerDecoder _ksba_ber_decoder_new (void);
+void       _ksba_ber_decoder_release (BerDecoder d);
+
+KsbaError _ksba_ber_decoder_set_module (BerDecoder d, AsnNode module);
+KsbaError _ksba_ber_decoder_set_reader (BerDecoder d, KsbaReader r);
+
+KsbaError _ksba_ber_decoder_dump (BerDecoder d, FILE *fp);
+
+
+
+
+
+#endif /*BER_DECODER_H*/
diff --git a/src/ber-dump.c b/src/ber-dump.c
new file mode 100644 (file)
index 0000000..7b14a35
--- /dev/null
@@ -0,0 +1,133 @@
+/* ber-dump.c - Tool to dump BER encoded data
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "ksba.h"
+#include "ber-decoder.h"
+
+#define PGMNAME "ber-dump"
+
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
+# define  ATTR_PRINTF(a,b)  __attribute__ ((format (printf,a,b)))
+#else
+# define  ATTR_PRINTF(a,b) 
+#endif
+
+/* keep track of parsing error */
+static int error_counter;
+
+
+static void print_error (const char *fmt, ... )  ATTR_PRINTF(1,2);
+
+
+
+static void
+print_error (const char *fmt, ... )  
+{
+  va_list arg_ptr ;
+
+  va_start (arg_ptr, fmt);
+  fputs (PGMNAME ": ", stderr);
+  vfprintf (stderr, fmt, arg_ptr);
+  va_end (arg_ptr);
+  error_counter++;
+}
+
+static void
+fatal (const char *fmt, ... )  
+{
+  va_list arg_ptr ;
+
+  va_start (arg_ptr, fmt);
+  fputs (PGMNAME ": fatal: ", stderr);
+  vfprintf (stderr, fmt, arg_ptr);
+  va_end (arg_ptr);
+  exit (1);
+}
+
+
+static void
+one_file (FILE *fp, const char *fname)
+{
+  KsbaError err;
+  KsbaReader r;
+  BerDecoder d;
+
+  r = ksba_reader_new ();
+  if (!r)
+    fatal ("out of core\n");
+  err = ksba_reader_set_file (r, fp);
+  if (err)
+    fatal ("ksba_reader_set_file failed: rc=%d\n", err);
+
+  d = _ksba_ber_decoder_new ();
+  if (!d)
+    fatal ("out of core\n");
+  err = _ksba_ber_decoder_set_reader (d, r);
+  if (err)
+    fatal ("ksba_ber_decoder_set_reader failed: rc=%d\n", err);
+  
+  err = _ksba_ber_decoder_dump (d, stdout);
+  if (err)
+    print_error ("ksba_ber_decoder_dump failed: rc=%d\n", err);
+  
+  _ksba_ber_decoder_release (d);
+  ksba_reader_release (r);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  if (!argc || (argc > 1 &&
+                (!strcmp (argv[1],"--help") || !strcmp (argv[1],"-h"))) )
+    {
+      fputs ("usage: ber-dump [files]\n", stderr);
+      return 0;
+    }
+  
+  argc--; argv++;
+  
+  if (!argc)
+    one_file (stdin, "-");
+  else
+    {
+      for (; argc; argc--, argv++) 
+        {
+          FILE *fp;
+          
+          fp = fopen (*argv, "r");
+          if (!fp)
+              print_error ("can't open `%s': %s\n", *argv, strerror (errno));
+          else
+            {
+              one_file (fp, *argv);
+              fclose (fp);
+            }
+        }
+    }
+  return error_counter? 1:0;
+}
diff --git a/src/cert-get.c b/src/cert-get.c
new file mode 100644 (file)
index 0000000..a0dd0fc
--- /dev/null
@@ -0,0 +1,67 @@
+/* cert-get.c - Get attributes from a certificate
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "util.h"
+
+#include "ksba.h"
+#include "cert.h"
+
+
+KsbaError
+ksba_cert_get_string_attr (KsbaCert cert, KsbaAttr what, int idx,
+                           const char **ret)
+{
+  *ret = NULL; /* set a default value */
+  if (!cert || idx < 0 )
+    return KSBA_Invalid_Value;
+
+  switch (what)
+    {
+      
+    default:
+      return KSBA_Invalid_Attr;
+    }
+  
+  return 0;
+}
+
+
+KsbaError
+ksba_cert_get_time_attr (KsbaCert cert, KsbaAttr what, int idx, time_t *ret)
+{
+  *ret = 0; /* set a default value */
+  if (!cert || idx < 0 )
+    return KSBA_Invalid_Value;
+
+  switch (what)
+    {
+      
+    default:
+      return KSBA_Invalid_Attr;
+    }
+  
+  return 0;
+}
+
diff --git a/src/cert.c b/src/cert.c
new file mode 100644 (file)
index 0000000..2ab692f
--- /dev/null
@@ -0,0 +1,74 @@
+/* cert.c - main function for the certificate handling
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "util.h"
+
+#include "ksba.h"
+#include "cert.h"
+
+
+/**
+ * ksba_cert_new:
+ * 
+ * Create a new and empty certificate object
+ * 
+ * Return value: A cert object or NULL in case of memory problems.
+ **/
+KsbaCert
+ksba_cert_new (void)
+{
+  KsbaCert cert;
+
+  cert = xtrycalloc (1, sizeof *cert);
+  if (!cert)
+    return NULL;
+
+
+  return cert;
+}
+
+void
+ksba_cert_release (KsbaCert cert)
+{
+  xfree (cert);
+}
+
+
+KsbaError
+ksba_cert_read_der (KsbaCert cert, KsbaReader reader)
+{
+  if (!cert || !reader)
+    return KSBA_Invalid_Value;
+  if (cert->initialized)
+    return KSBA_Conflict;
+
+  /* FIXME: parse it and store it in our internal format */
+
+
+}
+
+
+
+
diff --git a/src/cert.h b/src/cert.h
new file mode 100644 (file)
index 0000000..041e4bb
--- /dev/null
@@ -0,0 +1,33 @@
+/* cert.h - Internal definitions for cert.c
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 CERT_H
+#define CERT_H 1
+
+
+struct ksba_cert_s {
+  int initialized;
+};
+
+
+
+
+#endif /*CERT_H*/
+
diff --git a/src/cms.asn b/src/cms.asn
new file mode 100644 (file)
index 0000000..d0e4fc4
--- /dev/null
@@ -0,0 +1,401 @@
+-- cms.asn - CryptographicMessageSyntax ASN.1 Module
+--      Copyright (C) 2001 g10 Code GmbH
+--
+-- This file is part of KSBA.
+--
+-- KSBA 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.
+--
+-- KSBA 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
+--
+-----------------------------------------------------------------------
+-- This module is based on the one given in appendix A of RFC2630 which
+-- exhibits this copyright notice:
+--
+-- Copyright (C) The Internet Society (1999).  All Rights Reserved.
+--
+-- This document and translations of it may be copied and furnished to
+-- others, and derivative works that comment on or otherwise explain it
+-- or assist in its implementation may be prepared, copied, published
+-- and distributed, in whole or in part, without restriction of any
+-- kind, provided that the above copyright notice and this paragraph are
+-- included on all such copies and derivative works.  However, this
+-- document itself may not be modified in any way, such as by removing
+-- the copyright notice or references to the Internet Society or other
+-- Internet organizations, except as needed for the purpose of
+-- developing Internet standards in which case the procedures for
+-- copyrights defined in the Internet Standards process must be
+-- followed, or as required to translate it into languages other than
+-- English.
+--
+-- The limited permissions granted above are perpetual and will not be
+-- revoked by the Internet Society or its successors or assigns.
+--
+-- This document and the information contained herein is provided on an
+-- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+-- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+-- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+-- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+-- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+------------------------------------------------------------------------
+
+
+CryptographicMessageSyntax
+    { iso(1) member-body(2) us(840) rsadsi(113549)
+      pkcs(1) pkcs-9(9) smime(16) modules(0) cms(1) }
+
+DEFINITIONS IMPLICIT TAGS ::=
+BEGIN
+
+-- EXPORTS All
+-- The types and values defined in this module are exported for use in
+-- the other ASN.1 modules.  Other applications may use them for their
+-- own purposes.
+
+IMPORTS
+
+  -- Directory Information Framework (X.501)
+        Name
+           FROM InformationFramework { joint-iso-itu-t ds(5) modules(1)
+                informationFramework(1) 3 }
+
+  -- Directory Authentication Framework (X.509)
+        AlgorithmIdentifier, AttributeCertificate, Certificate,
+        CertificateList, CertificateSerialNumber
+           FROM AuthenticationFramework { joint-iso-itu-t ds(5)
+                module(1) authenticationFramework(7) 3 } ;
+
+
+-- Cryptographic Message Syntax
+
+ContentInfo ::= SEQUENCE {
+  contentType ContentType,
+  content [0] EXPLICIT ANY DEFINED BY contentType }
+
+ContentType ::= OBJECT IDENTIFIER
+
+SignedData ::= SEQUENCE {
+  version CMSVersion,
+  digestAlgorithms DigestAlgorithmIdentifiers,
+  encapContentInfo EncapsulatedContentInfo,
+  certificates [0] IMPLICIT CertificateSet OPTIONAL,
+  crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+  signerInfos SignerInfos }
+
+DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
+
+SignerInfos ::= SET OF SignerInfo
+
+
+EncapsulatedContentInfo ::= SEQUENCE {
+  eContentType ContentType,
+  eContent [0] EXPLICIT OCTET STRING OPTIONAL }
+
+SignerInfo ::= SEQUENCE {
+  version CMSVersion,
+  sid SignerIdentifier,
+  digestAlgorithm DigestAlgorithmIdentifier,
+  signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
+  signatureAlgorithm SignatureAlgorithmIdentifier,
+  signature SignatureValue,
+  unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
+
+SignerIdentifier ::= CHOICE {
+  issuerAndSerialNumber IssuerAndSerialNumber,
+  subjectKeyIdentifier [0] SubjectKeyIdentifier }
+
+SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+
+UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
+
+Attribute ::= SEQUENCE {
+  attrType OBJECT IDENTIFIER,
+  attrValues SET OF AttributeValue }
+
+AttributeValue ::= ANY
+
+SignatureValue ::= OCTET STRING
+
+EnvelopedData ::= SEQUENCE {
+  version CMSVersion,
+  originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+  recipientInfos RecipientInfos,
+  encryptedContentInfo EncryptedContentInfo,
+  unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+
+OriginatorInfo ::= SEQUENCE {
+  certs [0] IMPLICIT CertificateSet OPTIONAL,
+  crls [1] IMPLICIT CertificateRevocationLists OPTIONAL }
+
+RecipientInfos ::= SET OF RecipientInfo
+
+EncryptedContentInfo ::= SEQUENCE {
+  contentType ContentType,
+  contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+  encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
+
+EncryptedContent ::= OCTET STRING
+
+
+UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute
+
+RecipientInfo ::= CHOICE {
+  ktri KeyTransRecipientInfo,
+  kari [1] KeyAgreeRecipientInfo,
+  kekri [2] KEKRecipientInfo }
+
+EncryptedKey ::= OCTET STRING
+
+KeyTransRecipientInfo ::= SEQUENCE {
+  version CMSVersion,  -- always set to 0 or 2
+  rid RecipientIdentifier,
+  keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+  encryptedKey EncryptedKey }
+
+RecipientIdentifier ::= CHOICE {
+  issuerAndSerialNumber IssuerAndSerialNumber,
+  subjectKeyIdentifier [0] SubjectKeyIdentifier }
+
+KeyAgreeRecipientInfo ::= SEQUENCE {
+  version CMSVersion,  -- always set to 3
+  originator [0] EXPLICIT OriginatorIdentifierOrKey,
+  ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+  keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+  recipientEncryptedKeys RecipientEncryptedKeys }
+
+OriginatorIdentifierOrKey ::= CHOICE {
+  issuerAndSerialNumber IssuerAndSerialNumber,
+  subjectKeyIdentifier [0] SubjectKeyIdentifier,
+  originatorKey [1] OriginatorPublicKey }
+
+OriginatorPublicKey ::= SEQUENCE {
+  algorithm AlgorithmIdentifier,
+  publicKey BIT STRING }
+
+RecipientEncryptedKeys ::= SEQUENCE OF RecipientEncryptedKey
+
+RecipientEncryptedKey ::= SEQUENCE {
+  rid KeyAgreeRecipientIdentifier,
+  encryptedKey EncryptedKey }
+
+KeyAgreeRecipientIdentifier ::= CHOICE {
+  issuerAndSerialNumber IssuerAndSerialNumber,
+  rKeyId [0] IMPLICIT RecipientKeyIdentifier }
+
+
+RecipientKeyIdentifier ::= SEQUENCE {
+  subjectKeyIdentifier SubjectKeyIdentifier,
+  date GeneralizedTime OPTIONAL,
+  other OtherKeyAttribute OPTIONAL }
+
+SubjectKeyIdentifier ::= OCTET STRING
+
+KEKRecipientInfo ::= SEQUENCE {
+  version CMSVersion,  -- always set to 4
+  kekid KEKIdentifier,
+  keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+  encryptedKey EncryptedKey }
+
+KEKIdentifier ::= SEQUENCE {
+  keyIdentifier OCTET STRING,
+  date GeneralizedTime OPTIONAL,
+  other OtherKeyAttribute OPTIONAL }
+
+DigestedData ::= SEQUENCE {
+  version CMSVersion,
+  digestAlgorithm DigestAlgorithmIdentifier,
+  encapContentInfo EncapsulatedContentInfo,
+  digest Digest }
+
+Digest ::= OCTET STRING
+
+EncryptedData ::= SEQUENCE {
+  version CMSVersion,
+  encryptedContentInfo EncryptedContentInfo,
+  unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+
+AuthenticatedData ::= SEQUENCE {
+  version CMSVersion,
+  originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+  recipientInfos RecipientInfos,
+  macAlgorithm MessageAuthenticationCodeAlgorithm,
+  digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+  encapContentInfo EncapsulatedContentInfo,
+  authenticatedAttributes [2] IMPLICIT AuthAttributes OPTIONAL,
+  mac MessageAuthenticationCode,
+  unauthenticatedAttributes [3] IMPLICIT UnauthAttributes OPTIONAL }
+
+AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+
+UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+
+MessageAuthenticationCode ::= OCTET STRING
+
+
+DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+
+SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
+
+KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+
+ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+
+MessageAuthenticationCodeAlgorithm ::= AlgorithmIdentifier
+
+CertificateRevocationLists ::= SET OF CertificateList
+
+CertificateChoices ::= CHOICE {
+  certificate Certificate,  -- See X.509
+  extendedCertificate [0] IMPLICIT ExtendedCertificate,  -- Obsolete
+  attrCert [1] IMPLICIT AttributeCertificate }  -- See X.509 & X9.57
+
+CertificateSet ::= SET OF CertificateChoices
+
+IssuerAndSerialNumber ::= SEQUENCE {
+  issuer Name,
+  serialNumber CertificateSerialNumber }
+
+CMSVersion ::= INTEGER  { v0(0), v1(1), v2(2), v3(3), v4(4) }
+
+UserKeyingMaterial ::= OCTET STRING
+
+OtherKeyAttribute ::= SEQUENCE {
+  keyAttrId OBJECT IDENTIFIER,
+  keyAttr ANY DEFINED BY keyAttrId OPTIONAL }
+
+
+-- CMS Attributes
+
+MessageDigest ::= OCTET STRING
+
+SigningTime  ::= Time
+
+Time ::= CHOICE {
+  utcTime UTCTime,
+  generalTime GeneralizedTime }
+
+Countersignature ::= SignerInfo
+
+
+-- Algorithm Identifiers
+
+sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+    oiw(14) secsig(3) algorithm(2) 26 }
+
+md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+    rsadsi(113549) digestAlgorithm(2) 5 }
+
+id-dsa-with-sha1 OBJECT IDENTIFIER ::=  { iso(1) member-body(2)
+    us(840) x9-57 (10040) x9cm(4) 3 }
+
+rsaEncryption OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 1 }
+
+dh-public-number OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) ansi-x942(10046) number-type(2) 1 }
+
+id-alg-ESDH OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+    rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 5 }
+
+id-alg-CMS3DESwrap OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 6 }
+
+id-alg-CMSRC2wrap OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 7 }
+
+des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) encryptionAlgorithm(3) 7 }
+
+rc2-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+    rsadsi(113549) encryptionAlgorithm(3) 2 }
+
+hMAC-SHA1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+    dod(6) internet(1) security(5) mechanisms(5) 8 1 2 }
+
+
+-- Algorithm Parameters
+
+KeyWrapAlgorithm ::= AlgorithmIdentifier
+
+RC2wrapParameter ::= RC2ParameterVersion
+
+RC2ParameterVersion ::= INTEGER
+
+CBCParameter ::= IV
+
+IV ::= OCTET STRING  -- exactly 8 octets
+
+
+RC2CBCParameter ::= SEQUENCE {
+  rc2ParameterVersion INTEGER,
+  iv OCTET STRING  }  -- exactly 8 octets
+
+
+-- Content Type Object Identifiers
+
+id-ct-contentInfo OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16)
+    ct(1) 6 }
+
+id-data OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 }
+
+id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
+
+id-envelopedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 }
+
+id-digestedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs7(7) 5 }
+
+id-encryptedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs7(7) 6 }
+
+id-ct-authData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16)
+    ct(1) 2 }
+
+
+-- Attribute Object Identifiers
+
+id-contentType OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs9(9) 3 }
+
+id-messageDigest OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs9(9) 4 }
+
+id-signingTime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs9(9) 5 }
+
+id-countersignature OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    us(840) rsadsi(113549) pkcs(1) pkcs9(9) 6 }
+
+
+-- Obsolete Extended Certificate syntax from PKCS#6
+
+ExtendedCertificate ::= SEQUENCE {
+  extendedCertificateInfo ExtendedCertificateInfo,
+  signatureAlgorithm SignatureAlgorithmIdentifier,
+  signature Signature }
+
+ExtendedCertificateInfo ::= SEQUENCE {
+  version CMSVersion,
+  certificate Certificate,
+  attributes UnauthAttributes }
+
+Signature ::= BIT STRING
+
+
+END -- of CryptographicMessageSyntax
+
+
diff --git a/src/cms.c b/src/cms.c
new file mode 100644 (file)
index 0000000..5e32fda
--- /dev/null
+++ b/src/cms.c
@@ -0,0 +1,28 @@
+/* cms.c - cryptographic message syntax main functions
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "util.h"
+
+#include "ksba.h"
diff --git a/src/ksba.h b/src/ksba.h
new file mode 100644 (file)
index 0000000..4de8446
--- /dev/null
@@ -0,0 +1,96 @@
+/* ksba.h - X509 library for the Aegypten project
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 KSBA_H
+#define KSBA_H 1
+#ifdef __cplusplus
+extern "C" { 
+#if 0
+ }
+#endif
+#endif
+
+typedef enum {
+  KSBA_No_Error = 0,
+  KSBA_General_Error = 1,
+  KSBA_Out_Of_Core = 2,
+  KSBA_Invalid_Value = 3,
+  KSBA_Not_Implemented = 4,
+  KSBA_Conflict = 5,
+  KSBA_Read_Error = 6,
+  KSBA_Write_Error = 7,
+  KSBA_Invalid_Attr = 8,
+  KSBA_No_Data = 9,
+  KSBA_No_Value = 10,
+  KSBA_Bug = 11,
+  KSBA_BER_Error = 12,
+} KsbaError;
+
+typedef enum {
+  KSBA_ATTR_NONE = 0,
+  KSBA_ATTR_FOO = 1,
+} KsbaAttr;
+
+#define KSBA_SYM(a) ((sym_ ## a)? sym_ ## a:(sym_ ## a = ksba_make_sym (#a)))
+
+
+/* X.509 certificates are represented by this object.
+ * ksba_cert_new() creates such an object */
+struct ksba_cert_s;
+typedef struct ksba_cert_s *KsbaCert;
+
+
+/* This is a reader object vor various purposes
+   see ksba_reader_new et al. */
+struct ksba_reader_s;
+typedef struct ksba_reader_s *KsbaReader;
+
+
+
+/*-- cert.c --*/
+KsbaCert ksba_cert_new (void);
+void     ksba_cert_release (KsbaCert cert);
+
+
+/*-- reader.c --*/
+KsbaReader ksba_reader_new (void);
+void       ksba_reader_release (KsbaReader r);
+int        ksba_reader_error (KsbaReader r);
+
+KsbaError ksba_reader_set_mem (KsbaReader r,
+                               const void *buffer, size_t length);
+KsbaError ksba_reader_set_fd (KsbaReader r, int fd);
+KsbaError ksba_reader_set_file (KsbaReader r, FILE *fp);
+KsbaError ksba_reader_set_cb (KsbaReader r, 
+                              int (*cb)(void*,char *,size_t,size_t*),
+                              void *cb_value );
+
+KsbaError ksba_reader_read (KsbaReader r,
+                            char *buffer, size_t length, size_t *nread);
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*KSBA_H*/
+
diff --git a/src/reader.c b/src/reader.c
new file mode 100644 (file)
index 0000000..0808bd8
--- /dev/null
@@ -0,0 +1,306 @@
+/* reader.c - provides the Reader object
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include "util.h"
+
+#include "ksba.h"
+#include "reader.h"
+
+/**
+ * ksba_reader_new:
+ * 
+ * Create a new but uninitialized KsbaReader Object.  Using this
+ * reader object in unitialized state does always yield eof.
+ * 
+ * Return value: KsbaReader Object or NULL in case of memory shortage.
+ **/
+KsbaReader
+ksba_reader_new (void)
+{
+  KsbaReader r;
+
+  r = xtrycalloc (1, sizeof *r);
+  if (!r)
+    return NULL;
+
+  return r;
+}
+
+
+/**
+ * ksba_reader_release:
+ * @r: Reader Object (or NULL)
+ * 
+ * Release this object
+ **/
+void
+ksba_reader_release (KsbaReader r)
+{
+  xfree (r);
+}
+
+int
+ksba_reader_error (KsbaReader r)
+{
+  return r? r->error : -1;
+}
+
+
+/**
+ * ksba_reader_set_mem:
+ * @r: Reader object
+ * @buffer: Data
+ * @length: Length of Data (bytes)
+ * 
+ * Intialize the reader object with @length bytes from @buffer and set
+ * the read position to the beginning.  It is possible to reuse this
+ * reader object with another buffer if the reader object has
+ * already been initialized using this function.
+ * 
+ * Return value: 0 on success or an error code.
+ **/
+KsbaError
+ksba_reader_set_mem (KsbaReader r, const void *buffer, size_t length)
+{
+  if (!r || !buffer)
+    return KSBA_Invalid_Value;
+  if (r->type == READER_TYPE_MEM)
+    { /* Reuse this reader */
+      xfree (r->u.mem.buffer);
+      r->type = 0;
+    }
+  if (r->type)
+    return KSBA_Conflict;
+
+  r->u.mem.buffer = xtrymalloc (length);
+  if (!r->u.mem.buffer)
+    return KSBA_Out_Of_Core;
+  memcpy (r->u.mem.buffer, buffer, length);
+  r->u.mem.size = length;
+  r->u.mem.readpos = 0;
+  r->type = READER_TYPE_MEM;
+  r->eof = 0;
+
+  return 0;
+}
+
+
+/**
+ * ksba_reader_set_fd:
+ * @r: Reader object
+ * @fd: file descriptor
+ * 
+ * Initialize the Reader object with a file descriptor, so that read
+ * operations on this object are excuted on this file descriptor.
+ * 
+ * Return value: 
+ **/
+KsbaError
+ksba_reader_set_fd (KsbaReader r, int fd)
+{
+  if (!r || fd == -1)
+    return KSBA_Invalid_Value;
+  if (r->type)
+    return KSBA_Conflict;
+
+  r->eof = 0;
+  r->type = READER_TYPE_FD;
+  r->u.fd = fd;
+
+  return 0;
+}
+
+/**
+ * ksba_reader_set_file:
+ * @r: Reader object
+ * @fp: file pointer
+ * 
+ * Initialize the Reader object with a stdio file pointer, so that read
+ * operations on this object are excuted on this stream
+ * 
+ * Return value: 
+ **/
+KsbaError
+ksba_reader_set_file (KsbaReader r, FILE *fp)
+{
+  if (!r || !fp)
+    return KSBA_Invalid_Value;
+  if (r->type)
+    return KSBA_Conflict;
+
+  r->eof = 0;
+  r->type = READER_TYPE_FILE;
+  r->u.file = fp;
+  return 0;
+}
+
+
+
+/**
+ * ksba_reader_set_cb:
+ * @r: Reader object
+ * @cb: Callback function
+ * @cb_value: Value passed to the callback function
+ * 
+ * Initialize the reader object with a callback function.
+ * This callback function is defined as:
+ * <literal>
+ * typedef int (*cb) (void *cb_value, 
+ *                    char *buffer, size_t count,
+ *                    size_t *nread);
+ * </literal>
+ *
+ * The callback should return a maximium of @count bytes in @buffer
+ * and the number actually read in @nread.  It may return 0 in @nread
+ * if there are no bytes currently available.  To indicate EOF the
+ * callback should return with an error code of %-1 and set @nread to
+ * 0.  The callback may support passing %NULL for @buffer and @nread
+ * and %0 for count as an indication to reset its internal read
+ * pointer.
+ * 
+ * Return value: 0 on success or an error code
+ **/
+KsbaError
+ksba_reader_set_cb (KsbaReader r, 
+                    int (*cb)(void*,char *,size_t,size_t*), void *cb_value )
+{
+  if (!r || !cb)
+    return KSBA_Invalid_Value;
+  if (r->type)
+    return KSBA_Conflict;
+  
+  r->eof = 0;
+  r->type = READER_TYPE_CB;
+  r->u.cb.fnc = cb;
+  r->u.cb.value = cb_value;
+
+  return 0;
+}
+
+
+/**
+ * ksba_reader_read:
+ * @r: Readder object
+ * @buffer: A buffer for returning the data
+ * @length: The length of this buffer
+ * @nread:  Number of bytes actually read.
+ * 
+ * Read data from the current read position to the supplied @buffer,
+ * max. @length bytes are read and the actual number of bytes read are
+ * returned in @nread.  If there are no more bytes available %-1 is
+ * returned and @nread is set to 0.
+ *
+ * If a @buffer of NULL is specified, the function does only return
+ * the number of bytes available and does not move the read pointer.
+ * This does only work for objects initialized from memory; if the
+ * object is not capable of this it will return the error
+ * %KSBA_Not_Implemented
+ * 
+ * Return value: 0 on success, -1 on EOF or an error code
+ **/
+KsbaError
+ksba_reader_read (KsbaReader r, char *buffer, size_t length, size_t *nread)
+{
+  size_t nbytes;
+
+  if (!r || !nread)
+    return KSBA_Invalid_Value;
+
+  if (!buffer)
+    {
+      if (r->type != READER_TYPE_MEM)
+        return KSBA_Not_Implemented;
+      *nread = r->u.mem.size - r->u.mem.readpos;
+      return *nread? 0 :-1;
+    }
+
+  *nread = 0;
+  if (!r->type)
+    {
+      r->eof = 1;
+      return -1;
+    }
+  else if (r->type == READER_TYPE_MEM)
+    {
+      nbytes = r->u.mem.size - r->u.mem.readpos;
+      if (!nbytes)
+        {
+          r->eof = 1;
+          return -1;
+        }
+      
+      if (nbytes > length)
+        nbytes = length;
+      memcpy (buffer, r->u.mem.buffer + r->u.mem.readpos, nbytes);
+      *nread = nbytes;
+      r->u.mem.readpos += nbytes;
+    }
+  else if (r->type == READER_TYPE_FILE)
+    {
+      int n;
+
+      if (r->eof)
+        return -1;
+      
+      if (!length)
+        {
+          *nread = 0;
+          return 0;
+        }
+
+      n = fread (buffer, 1, length, r->u.file);
+      *nread = n > 0? n: 0;
+      if (n < length)
+        {
+          if (ferror(r->u.file))
+              r->error = errno;
+          r->eof = 1;
+          if (n <= 0)
+            return -1;
+        }
+    }
+  else if (r->type == READER_TYPE_CB)
+    {
+      if (r->eof)
+        return -1;
+      
+      if (r->u.cb.fnc (r->u.cb.value, buffer, length, nread))
+        {
+          *nread = 0;
+          r->eof = 1;
+          return -1;
+        }
+    }
+    else 
+      return KSBA_Bug;
+
+    return 0;
+} 
+
+
+
+
+
diff --git a/src/reader.h b/src/reader.h
new file mode 100644 (file)
index 0000000..114b1df
--- /dev/null
@@ -0,0 +1,58 @@
+/* reader.h - internl definitions for the reder object.
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 READER_H
+#define READER_H 1
+
+#include <stdio.h>
+
+enum reader_type {
+  READER_TYPE_NONE = 0,
+  READER_TYPE_MEM,
+  READER_TYPE_FD,
+  READER_TYPE_FILE,
+  READER_TYPE_CB
+};
+
+
+struct ksba_reader_s {
+  int eof;
+  int error;
+  enum reader_type type;
+  union {
+    struct {
+      unsigned char *buffer;
+      size_t size;
+      size_t readpos;
+    } mem;   /* for READER_TYPE_MEM */
+    int fd;  /* for READER_TYPE_FD */
+    FILE *file; /* for READER_TYPE_FILE */
+    struct {
+      int (*fnc)(void*,char *,size_t,size_t*);
+      void *value;
+    } cb;   /* for READER_TYPE_CB */
+  } u;
+};
+
+
+
+
+#endif /*READER_H*/
+
diff --git a/src/tmttv2.asn b/src/tmttv2.asn
new file mode 100644 (file)
index 0000000..df02f62
--- /dev/null
@@ -0,0 +1,468 @@
+-- tmttv2.asn - X.509v3 profile for the BSI Sphinx project
+--      Copyright (C) 2001 g10 Code GmbH
+--
+-- This file is part of KSBA.
+--
+-- KSBA 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.
+--
+-- KSBA 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
+--
+
+
+TMTTv2 {iso(1) identified-organization(3) dod(6) internet(1)
+        security(5) mechanisms(5) }
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+-- standard object identifiers
+id-ce OBJECT IDENTIFIER  ::=  {joint-iso-ccitt(2) ds(5) 29}
+
+
+
+-- (TMTTv2 3.1)
+Certificate ::= SEQUENCE {
+  tbsCertificate       TBSCertificate,
+  signatureAlgorithm   AlgorithmIdentifier,
+  signature            BIT STRING 
+}
+
+AlgorithmIdentifier ::= SEQUENCE {
+  algorithm    OBJECT IDENTIFIER,
+  parameters   ANY DEFINED BY algorithm OPTIONAL
+  -- should be used but set to NULL
+}
+
+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,
+  subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+  extensions      [3] EXPLICIT Extensions OPTIONAL
+}
+
+-- (TMTTv2 3.1.1)
+Version ::= INTEGER { v1(0), v2(1), v3(2) } 
+-- Ony v3 is used which is the default anyway
+
+-- (TMTTv2 3.1.2)
+CertificateSerialNumber ::= INTEGER
+-- Must support length of up to 15 byte
+
+-- (TMTTv2 3.1.4)
+Name ::= CHOICE {
+  rdnSequence RDNSequence
+}
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
+-- pkix defines a SIZE (1 .. MAX), we use a maximum of 1 to avoid
+-- problems with some LDAP implementations.
+
+Attribute ::= SEQUENCE {  -- not specified bt TMTT
+  type    AttributeType,
+  values  SET OF AttributeValue
+}
+
+AttributeTypeAndValue ::= SEQUENCE {
+  type    AttributeType,
+  value   AttributeValue
+}
+
+AttributeType ::= OBJECT IDENTIFIER
+
+AttributeValue ::= ANY
+
+DirectoryString ::= CHOICE {
+  printableString   PrintableString (SIZE (1..maxSize)),
+  teletexString     TeletexString (SIZE (1..maxSize)),
+  utf8String        UTF8String (SIZE (1..maxSize)),
+  bmpString         BMPString (SIZE(1..maxSize)),
+  universalString   UniversalString (SIZE (1..maxSize))
+}
+  -- For Sphinx conformity maxSize must be:
+  -- BusinessCategory  128  LocalityName       128  StateOrProvince  128
+  -- CommonName        128  PostalCode          40  SurName           64
+  -- CountryName         2  OrganizationalUnit  64  Title             64
+  -- GivenName          64  OrganizationalName  64
+
+-- (TMTTv2 3.1.5)
+Validity ::= SEQUENCE {
+  notBefore  Time,
+  notAfter   Time 
+}
+
+Time ::= CHOICE {
+  utcTime      UTCTime,
+  generalTime  GeneralizedTime 
+}
+-- fixme: explain constraints
+
+--(TMTTv2 3.1.7)
+SubjectPublicKeyInfo ::= SEQUENCE {
+  algorithm         AlgorithmIdentifier,
+  subjectPublicKey  BIT STRING 
+}
+
+--(TMTTv2 3.1.9)
+Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+
+Extension ::= SEQUENCE {
+  extnID     OBJECT IDENTIFIER,
+  critical   BOOLEAN DEFAULT FALSE,
+  extnValue  OCTET STRING  
+}
+
+
+UniqueIdentifier  ::=  BIT STRING
+
+-- (TMTTv2 3.2.1)
+AuthorityKeyIdentifier ::= SEQUENCE {
+  keyIdentifier              [0] KeyIdentifier OPTIONAL,
+  authorityCertIssuer        [1] GeneralNames OPTIONAL,
+  authorityCertSerialNumber  [2] CertificateSerialNumber OPTIONAL 
+}
+-- Fixme: our parser cant handle this:
+--   ( WITH COMPONENTS   { ..., authorityCertIssuer PRESENT,
+--                         authorityCertSerialNumber PRESENT}
+--     | WITH COMPONENTS { ..., authorityCertIssuer ABSENT,
+--                         authorityCertSerialNumber ABSENT }
+--   )
+
+KeyIdentifier ::= OCTET STRING
+
+-- (TMTTv2 3.2.3)
+KeyUsage ::= BIT STRING {
+  digitalSignature (0),
+  nonRepudiation   (1),
+  keyEncipherment  (2),
+  dataEncipherment (3),
+  keyAgreement     (4),
+  keyCertSign      (5),
+  cRLSign          (6),
+  encipherOnly     (7),
+  decipherOnly     (8)
+}
+
+
+-- (TMTTv2 3.2.5)
+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 
+}
+
+PolicyQualifierId ::= OBJECT IDENTIFIER  -- missing in TMTTv2 document
+
+-- (TMTTv2 3.2.6)
+PolicyMappingsSyntax ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+  issuerDomainPolicy      CertPolicyId,
+  subjectDomainPolicy     CertPolicyId
+}
+
+
+-- (TMTTv2 3.2.7)
+SubjectAltName ::= GeneralNames
+
+GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+
+GeneralName ::= CHOICE {
+  otherName                  [0] OtherName, -- INSTANCE OF OTHER-NAME
+  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 
+}
+
+OtherName ::= SEQUENCE {
+  type-id  OBJECT IDENTIFIER,
+  value    [0] EXPLICIT ANY DEFINED BY type-id
+}
+
+EDIPartyName ::= SEQUENCE {
+  nameAssigner  [0] DirectoryString OPTIONAL,
+  partyName     [1] DirectoryString 
+}
+
+-- (TMTTv2 3.2.9)
+SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+
+-- (TMTTv2 3.2.10)
+-- id-biometricData OBJECT IDENTIFIE ::= { fixme 1 }
+
+BiometricData ::= SET OF SEQUENCE {
+  typeId  OBJECT IDENTIFIER,
+  value   ANY DEFINED BY typeId
+}
+
+
+-- (TMTTv2 3.2.11)
+BasicConstraints ::= SEQUENCE {
+  cA                 BOOLEAN DEFAULT FALSE,
+  pathLenConstraint  INTEGER (0..MAX) OPTIONAL 
+}
+
+-- (TMTTv2 3.2.12)
+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)
+
+-- (TMTTv2 3.2.13)
+PolicyConstraintsSyntax ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+  requireExplicitPolicy  [0] SkipCerts OPTIONAL,
+  inhibitPolicyMapping   [1] SkipCerts OPTIONAL
+}
+
+SkipCerts ::= INTEGER (0..MAX)
+
+
+-- (TMTTv2 3.2.14)
+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) 
+}
+
+
+-- (TMTTv2 3.2.15)
+-- id-issuerCertDistributionPoint OBJECT IDENTIFIER ::= { fixme 28 }
+
+IssuerCertDistributionPoint ::= IA5String
+
+
+-- (TMTTv2 3.2.16)
+-- id-subjectCertDistributionPoint OBJECT IDENTIFIER ::= { fixme 3 }
+
+SubjectCertDistributionPoint ::= IA5String
+
+
+-- (TMTTv2 3.2.17)
+-- id-policyDistributionPoint OBJECT IDENTIFIER ::= { fixme 4 }
+
+PolicyDistributionPoint ::= IA5String
+
+
+-- (TMTTv2 3.2.18)
+-- id-testIdentifier OBECJT IDENTIFIER ::= { fixme 5 }
+
+TestIdentifier ::= UTF8String
+
+
+--\f
+-- (TMTTv2 4.1)
+CertificateList ::= SEQUENCE {
+  tbsCertList         TBSCertList,
+  signatureAlgorithm  AlgorithmIdentifier,
+  signatureValue      BIT STRING 
+}
+
+TBSCertList ::= SEQUENCE {
+  version              Version OPTIONAL,  -- should be v2 if present
+  signature            AlgorithmIdentifier,
+  issuer               Name,
+  thisUpdate           Time,
+  nextUpdate           Time OPTIONAL,  -- must be used in TMTT
+  revokedCertificates  SEQUENCE OF SEQUENCE {
+    userCertificate      CertificateSerialNumber,
+    revocationDate       Time,
+    crlEntryExtensions   Extensions OPTIONAL  -- should be v2 if present
+  } OPTIONAL,
+  crlExtensions        [0] EXPLICIT Extensions OPTIONAL -- v2 is present
+}
+
+
+-- (TMTTv2 4.2.1)
+CRLReason ::= ENUMERATED {
+  unspecified           (0),  -- not allowed in TMTT
+  keyCompromise         (1),
+  cACompromise          (2),
+  affiliationChanged    (3),
+  superseded            (4),
+  cessationOfOperation  (5),
+  certificateHold       (6),
+  removeFromCRL         (8)  -- should not be used because 
+                             -- Delta-CRLs are not supported
+}
+
+-- (TMTTv2 4.2.3)
+InvalidityDate ::= GeneralizedTime
+
+
+-- (TMTTv2 4.2.4)
+CertificateIssuer ::= GeneralNames
+
+-- (TMTTv2 4.3.3)
+cRLNumber ::= INTEGER (1..MAX)
+
+-- (TMTTv2 4.3.4)
+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 
+}
+
+
+
+
+
+
+
+
+
+--\f
+-------------------------
+-- x400 address syntax --
+-------------------------
+ORAddress ::= SEQUENCE {
+  built-in-standard-attributes        BuiltInStandardAttributes,
+  built-in-domain-defined-attributes  BuiltInDomainDefinedAttributes OPTIONAL,
+  extension-attributes                ExtensionAttributes OPTIONAL 
+}
+
+BuiltInStandardAttributes ::= SEQUENCE {
+  country-name               CountryName OPTIONAL,
+  administration-domain-name AdministrationDomainName OPTIONAL,
+  network-address            [0] EXPLICIT NetworkAddress OPTIONAL,
+  terminal-identifier        [1] EXPLICIT TerminalIdentifier OPTIONAL,
+  private-domain-name        [2] EXPLICIT PrivateDomainName OPTIONAL,
+  organization-name          [3] EXPLICIT OrganizationName OPTIONAL,
+  numeric-user-identifier    [4] EXPLICIT NumericUserIdentifier OPTIONAL,
+  personal-name              [5] EXPLICIT PersonalName OPTIONAL,
+  organizational-unit-names  [6] EXPLICIT OrganizationalUnitNames OPTIONAL
+}
+
+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 { -- see also teletex-personal-name
+  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 
+}
+                        
+
+OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
+                                        OF OrganizationalUnitName
+                            -- see also teletex-organizational-unit-names
+
+OrganizationalUnitName ::= PrintableString 
+                           (SIZE (1..ub-organizational-unit-name-length))
+
+
+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))
+}
+
+
+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
+}
+
+
+--\f
+-- UNIVERSAL Types defined in '93 and '98 ASN.1
+UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING 
+NumericString ::= [UNIVERSAL 18] IMPLICIT OCTET STRING
+PrintableString ::= [UNIVERSAL 19] IMPLICIT OCTET STRING
+TeletexString ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
+IA5String ::= [UNIVERSAL 22] IMPLICIT OCTET STRING
+UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING  
+BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
+
+
+END
+
diff --git a/src/util.c b/src/util.c
new file mode 100644 (file)
index 0000000..4f21453
--- /dev/null
@@ -0,0 +1,113 @@
+/* util.c
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "util.h"
+
+/* Wrapper for the common memory allocation functions.  These are here
+   so that we can add hooks.  The corresponding macros shoudl be used.
+   These macros are not named xfoo() because this name is commonly
+   used for function which die on errror.  We use macronames like
+   xtryfoo() instead. */
+
+void *
+_ksba_malloc (size_t n )
+{
+  return malloc (n);
+}
+
+void *
+_ksba_calloc (size_t n, size_t m )
+{
+  return calloc (n, m);
+}
+
+void *
+_ksba_realloc (void *p, size_t n)
+{
+  return realloc (p, n );
+}
+
+
+char *
+_ksba_strdup (const char *p)
+{
+  return strdup (p);
+}
+
+
+void 
+_ksba_free ( void *a )
+{
+  free (a);
+}
+
+
+static void
+out_of_core(void)
+{
+  fputs ("\nfatal: out of memory\n", stderr );
+  exit (2);
+}
+
+\f
+/* Implementations of the common xfoo() memory allocation functions */
+void *
+_ksba_xmalloc (size_t n )
+{
+  void *p = _ksba_malloc (n);
+  if (!p)
+    out_of_core();
+  return p;
+}
+
+void *
+_ksba_xcalloc (size_t n, size_t m )
+{
+  void *p = _ksba_calloc (n,m);
+  if (!p)
+    out_of_core();
+  return p;
+}
+
+void *
+_ksba_xrealloc (void *p, size_t n)
+{
+  void *p = _ksba_realloc (p,n);
+  if (!p)
+    out_of_core();
+  return p;
+}
+
+
+char *
+_ksba_xstrdup (const char *p)
+{
+  char *p = _ksba_strdup (p);
+  if (!p)
+    out_of_core();
+  return p;
+}
+
diff --git a/src/util.h b/src/util.h
new file mode 100644 (file)
index 0000000..8da893e
--- /dev/null
@@ -0,0 +1,77 @@
+/* util.h 
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of KSBA.
+ *
+ * KSBA 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.
+ *
+ * KSBA 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 UTIL_H
+#define UTIL_H
+
+void *_ksba_malloc (size_t n );
+void *_ksba_calloc (size_t n, size_t m );
+void *_ksba_realloc (void *p, size_t n);
+char *_ksba_strdup (const char *p);
+void  _ksba_free ( void *a );
+void *_ksba_xmalloc (size_t n );
+void *_ksba_xcalloc (size_t n, size_t m );
+void *_ksba_xrealloc (void *p, size_t n);
+char *_ksba_xstrdup (const char *p);
+
+#define xtrymalloc(a)    _ksba_malloc((a))
+#define xtrycalloc(a,b)  _ksba_calloc((a),(b))
+#define xtryrealloc(a,b) _ksba_realloc((a),(b))
+#define xtrystrdup(a)    _ksba_strdup((a))
+#define xfree(a)         _ksba_free((a))
+#define xmalloc(a)       _ksba_xmalloc((a))
+#define xcalloc(a,b)     _ksba_xcalloc((a),(b))
+#define xrealloc(a,b)    _ksba_xrealloc((a),(b))
+#define xstrdup(a)       _ksba_xstrdup((a))
+
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+#define DIMof(type,member)   DIM(((type *)0)->member)
+#ifndef STR
+  #define STR(v) #v
+#endif
+#define STR2(v) STR(v)
+
+
+#define return_if_fail(expr) do {                        \
+    if (!(expr)) {                                       \
+        fprintf (stderr, "%s:%d: assertion `%s' failed", \
+                 __FILE__, __LINE__, #expr );            \
+        return;                                                 \
+    } } while (0)
+#define return_null_if_fail(expr) do {                   \
+    if (!(expr)) {                                       \
+        fprintf (stderr, "%s:%d: assertion `%s' failed", \
+                 __FILE__, __LINE__, #expr );            \
+        return NULL;                                    \
+    } } while (0)
+#define return_val_if_fail(expr,val) do {                \
+    if (!(expr)) {                                       \
+        fprintf (stderr, "%s:%d: assertion `%s' failed", \
+                 __FILE__, __LINE__, #expr );            \
+        return (val);                                   \
+    } } while (0)
+
+
+#endif /* UTIL_H */
+
+
+
+