add vector length check
authorFabio Fiorina <fiorinaf@gnutls.org>
Tue, 25 Feb 2003 22:07:40 +0000 (22:07 +0000)
committerFabio Fiorina <fiorinaf@gnutls.org>
Tue, 25 Feb 2003 22:07:40 +0000 (22:07 +0000)
14 files changed:
NEWS
configure.in
lib/coding.c
lib/decoding.c
lib/element.c
lib/int.h
lib/libtasn1.h
lib/parser_aux.c
src/CertificateExample.c
src/CrlExample.c
src/asn1Coding.c
tests/Test_tree.asn
tests/Test_tree.c
tests/Test_tree_asn1_tab.c

diff --git a/NEWS b/NEWS
index 39ebade..3bbff87 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Version 0.2.2
+- Add vector length check in asn1_der_coding function
+- Add vector length check in asn1_read_value function
+- Add asn1_check_version function
+
 Version 0.2.1
 - Add asn1_find_structure_from_oid function
 - Add asn1_read_tag function
index e0e2e2e..2c94553 100644 (file)
@@ -12,7 +12,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os")
 dnl libtasn1 Version
 ASN1_MAJOR_VERSION=0
 ASN1_MINOR_VERSION=2
-ASN1_MICRO_VERSION=1
+ASN1_MICRO_VERSION=2
 ASN1_VERSION=$ASN1_MAJOR_VERSION.$ASN1_MINOR_VERSION.$ASN1_MICRO_VERSION
 
 AC_DEFINE_UNQUOTED(ASN1_VERSION, "$ASN1_VERSION")
index 3f6fdef..ea21141 100644 (file)
@@ -32,6 +32,8 @@
 #include <gstr.h>
 #include "element.h"
 
+#define MAX_TAG_LEN 16
+
 /******************************************************/
 /* Function : _asn1_error_description_value_not_found */
 /* Description: creates the ErrorDescription string   */
@@ -159,18 +161,29 @@ _asn1_octet_der(const unsigned char *str,int str_len,unsigned char *der,int *der
 /*   str: TIME null-terminated string.                */
 /*   der: string returned.                            */
 /*   der_len: number of meanful bytes of DER          */
-/*            (der[0]..der[ans_len-1]).               */
+/*            (der[0]..der[ans_len-1]). Initially it  */
+/*            if must store the lenght of DER.        */
 /* Return:                                            */
+/*   ASN1_MEM_ERROR when DER isn't big enough         */
+/*   ASN1_SUCCESS otherwise                           */
 /******************************************************/
-void
+asn1_retCode
 _asn1_time_der(unsigned char *str,unsigned char *der,int *der_len)
 {
   int len_len;
+  int max_len;
 
-  if(der==NULL) return;
+  max_len=*der_len;
+
+  if(der==NULL) return ASN1_SUCCESS;
   _asn1_length_der(strlen(str),der,&len_len);
-  memcpy(der+len_len,str,strlen(str));
+  if((len_len+strlen(str))<=max_len)
+    memcpy(der+len_len,str,strlen(str));
   *der_len=len_len+strlen(str);
+
+  if((*der_len)>max_len) return ASN1_MEM_ERROR;
+
+  return ASN1_SUCCESS;
 }
 
 
@@ -217,18 +230,23 @@ _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
 /*   str: OBJECT IDENTIFIER null-terminated string.   */
 /*   der: string returned.                            */
 /*   der_len: number of meanful bytes of DER          */
-/*            (der[0]..der[ans_len-1]).               */
+/*            (der[0]..der[ans_len-1]). Initially it  */
+/*            if must store the lenght of DER.        */
 /* Return:                                            */
+/*   ASN1_MEM_ERROR when DER isn't big enough         */
+/*   ASN1_SUCCESS otherwise                           */
 /******************************************************/
-void
+asn1_retCode
 _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len)
 {
-  int len_len,counter,k,first;
+  int len_len,counter,k,first,max_len;
   char *temp,*n_end,*n_start;
   unsigned char bit7;
   unsigned long val,val1=0;
 
-  if(der==NULL) return;
+  if(der==NULL) return ASN1_SUCCESS;
+
+  max_len=*der_len;
 
   temp=(char *) malloc(strlen(str)+2);
 
@@ -244,7 +262,8 @@ _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len)
 
     if(counter==1) val1=val;
     else if(counter==2){
-      der[0]=40*val1+val;
+      if(max_len>0)
+       der[0]=40*val1+val;
       *der_len=1;
     }
     else{
@@ -253,7 +272,8 @@ _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len)
        bit7=(val>>(k*7))&0x7F;
        if(bit7 || first || !k){
          if(k) bit7|=0x80;
-         der[*der_len]=bit7;
+         if(max_len>(*der_len))
+           der[*der_len]=bit7;
          (*der_len)++;
          first=1;
        }
@@ -264,11 +284,17 @@ _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len)
   }
 
   _asn1_length_der(*der_len,NULL,&len_len);
-  memmove(der+len_len,der,*der_len);
-  _asn1_length_der(*der_len,der,&len_len);
+  if(max_len>=(*der_len+len_len)){
+    memmove(der+len_len,der,*der_len);
+    _asn1_length_der(*der_len,der,&len_len);
+  }
   *der_len+=len_len;
 
   free(temp);
+
+  if(max_len<(*der_len)) return ASN1_MEM_ERROR;
+
+  return ASN1_SUCCESS;
 }
 
 
@@ -313,10 +339,13 @@ _asn1_bit_der(const unsigned char *str,int bit_len,unsigned char *der,int *der_l
 /*   der: string with the DER coding of the whole tree*/
 /*   counter: number of meanful bytes of DER          */
 /*            (der[0]..der[*counter-1]).              */
+/*   max_len: size of der vector                      */
 /* Return:                                            */
+/*   ASN1_MEM_ERROR if der vector isn't big enough,   */
+/*   otherwise ASN1_SUCCESS.                          */
 /******************************************************/
-void
-_asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter)
+asn1_retCode
+_asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter,int *max_len)
 {
   node_asn *p;
   int is_tag_implicit,len2,len3;
@@ -339,8 +368,11 @@ _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter)
          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);
+         if(len3<=(*max_len)){ 
+           memmove(der+len2+len3,der+len2,*counter-len2);
+           memcpy(der+len2,temp,len3);
+         }
+         *max_len -= len3;
          *counter+=len3;         
          is_tag_implicit=0;
        }
@@ -353,6 +385,10 @@ _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter)
       p=p->left;
     }
   }
+
+  if(*max_len<0) return ASN1_MEM_ERROR;
+
+  return ASN1_SUCCESS;
 }
 
 
@@ -365,17 +401,20 @@ _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter)
 /*   der: string returned                             */
 /*   counter: number of meanful bytes of DER          */
 /*            (counter[0]..der[*counter-1]).          */
+/*   max_len: size of der vector                      */
 /* Return:                                            */
 /*   ASN1_GENERIC_ERROR if the type is unknown,       */
+/*   ASN1_MEM_ERROR if der vector isn't big enough,   */
 /*   otherwise ASN1_SUCCESS.                          */
 /******************************************************/
-int
-_asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter)
+asn1_retCode
+_asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter,int *max_len)
 {
   node_asn *p;
   int tag_len,is_tag_implicit;
   unsigned char class,class_implicit=0,temp[SIZEOF_UNSIGNED_INT*3+1];
   unsigned long tag_implicit=0;
+  char tag_der[MAX_TAG_LEN];
    
   is_tag_implicit=0;
 
@@ -390,10 +429,15 @@ _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter)
        
        if(p->type&CONST_EXPLICIT){
          if(is_tag_implicit)
-           _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len);
+           _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len);
          else
-           _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),der+*counter,&tag_len);
+           _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),tag_der,&tag_len);
+
+         *max_len -= tag_len;
+         if(*max_len>=0)
+           memcpy(der+*counter,tag_der,tag_len);
          *counter+=tag_len;
+
          _asn1_ltostr(*counter,temp);
          _asn1_set_name(p,temp);
 
@@ -416,45 +460,45 @@ _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter)
   }
   
   if(is_tag_implicit){
-    _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len);
+    _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len);
   }
   else{
     switch(type_field(node->type)){
     case TYPE_NULL:
-      _asn1_tag_der(UNIVERSAL,TAG_NULL,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_NULL,tag_der,&tag_len);
       break;
     case TYPE_BOOLEAN:
-      _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,tag_der,&tag_len);
       break;
     case TYPE_INTEGER:
-      _asn1_tag_der(UNIVERSAL,TAG_INTEGER,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_INTEGER,tag_der,&tag_len);
       break;
     case TYPE_ENUMERATED:
-      _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,tag_der,&tag_len);
       break;
     case TYPE_OBJECT_ID:
-      _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,tag_der,&tag_len);
       break;
     case TYPE_TIME:
       if(node->type&CONST_UTC){
-       _asn1_tag_der(UNIVERSAL,TAG_UTCTime,der+*counter,&tag_len);
+       _asn1_tag_der(UNIVERSAL,TAG_UTCTime,tag_der,&tag_len);
       }
-      else _asn1_tag_der(UNIVERSAL,TAG_GENERALIZEDTime,der+*counter,&tag_len);
+      else _asn1_tag_der(UNIVERSAL,TAG_GENERALIZEDTime,tag_der,&tag_len);
       break;
     case TYPE_OCTET_STRING:
-      _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,tag_der,&tag_len);
       break;
     case TYPE_GENERALSTRING:
-      _asn1_tag_der(UNIVERSAL,TAG_GENERALSTRING,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_GENERALSTRING,tag_der,&tag_len);
       break;
     case TYPE_BIT_STRING:
-      _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,tag_der,&tag_len);
       break;
     case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF:
-      _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,tag_der,&tag_len);
       break;
     case TYPE_SET: case TYPE_SET_OF:
-      _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,der+*counter,&tag_len);
+      _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,tag_der,&tag_len);
       break;
     case TYPE_TAG:
       tag_len=0;
@@ -469,9 +513,14 @@ _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter)
       return ASN1_GENERIC_ERROR;
     }
   }
-  
+
+  *max_len -= tag_len;
+  if(*max_len>=0)
+    memcpy(der+*counter,tag_der,tag_len);
   *counter+=tag_len;
 
+  if(*max_len<0) return ASN1_MEM_ERROR;
+
   return ASN1_SUCCESS;
 }
 
@@ -670,7 +719,7 @@ _asn1_ordering_set_of(unsigned char *der,node_asn *node)
   * @element: pointer to an ASN1 element
   * @name: the name of the structure you want to encode (it must be inside *POINTER).
   * @der: vector that will contain the DER encoding. DER must be a pointer to memory cells already allocated.
-  * @len: number of bytes of *der: der[0]..der[len-1]
+  * @len: number of bytes of *der: der[0]..der[len-1], Initialy holds the sizeof of der vector.
   * @errorDescription : return the error description or an empty string if success.
   * Description:
   *
@@ -683,6 +732,10 @@ _asn1_ordering_set_of(unsigned char *der,node_asn *node)
   *   ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element.
   *
   *   ASN1_VALUE_NOT_FOUND\: there is an element without a value.
+  *
+  *   ASN1_MEM_ERROR\: der vector isn't big enough. Also in this case LEN
+  *   will contain the length needed.
+  *
   **/
 asn1_retCode 
 asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len,
@@ -690,72 +743,123 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len,
 {
   node_asn *node,*p;
   char temp[SIZEOF_UNSIGNED_LONG_INT*3+1];
-  int counter,counter_old,len2,len3,move,ris;
+  int counter,counter_old,len2,len3,move,max_len,max_len_old;
+  asn1_retCode ris;
 
   node=_asn1_find_node(element,name);
   if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
 
+  max_len=*len;
+
   counter=0;
   move=DOWN;
   p=node;
   while(1){
     
     counter_old=counter;
-    if(move!=UP) ris=_asn1_insert_tag_der(p,der,&counter);
-
+    max_len_old=max_len;
+    if(move!=UP){
+      ris=_asn1_insert_tag_der(p,der,&counter,&max_len);
+    }
     switch(type_field(p->type)){
     case TYPE_NULL:
-      der[counter]=0;
-      counter++;
+      max_len--;
+      if(max_len>=0)
+       der[counter++]=0;
       move=RIGHT;
       break;
     case TYPE_BOOLEAN:
-      if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old;
+      if((p->type&CONST_DEFAULT) && (p->value==NULL)){
+       counter=counter_old;
+       max_len=max_len_old;
+      }
       else{
-       der[counter++]=1;
-       if(p->value[0]=='F') der[counter++]=0;
-       else der[counter++]=0xFF;
+       if(p->value==NULL){
+         _asn1_error_description_value_not_found(p,ErrorDescription);
+         return ASN1_VALUE_NOT_FOUND;
+       }
+       max_len -= 2;
+       if(max_len>=0){
+         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;
+      if((p->type&CONST_DEFAULT) && (p->value==NULL)){
+       counter=counter_old;
+       max_len=max_len_old;
+      }
       else{
        if(p->value==NULL){
          _asn1_error_description_value_not_found(p,ErrorDescription);
          return ASN1_VALUE_NOT_FOUND;
        }
        len2=_asn1_get_length_der(p->value,&len3);
-       memcpy(der+counter,p->value,len3+len2);
+       max_len -= len2+len3;
+       if(max_len>=0)
+         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);
+      if(p->value==NULL){
+         _asn1_error_description_value_not_found(p,ErrorDescription);
+         return ASN1_VALUE_NOT_FOUND;
+      }
+      len2=max_len;
+      ris=_asn1_objectid_der(p->value,der+counter,&len2);
+      max_len-=len2;
       counter+=len2;
       move=RIGHT;
       break;
     case TYPE_TIME:
-      _asn1_time_der(p->value,der+counter,&len2);
+      if(p->value==NULL){
+       _asn1_error_description_value_not_found(p,ErrorDescription);
+       return ASN1_VALUE_NOT_FOUND;
+      }
+      len2=max_len;
+      ris=_asn1_time_der(p->value,der+counter,&len2);
+      max_len-=len2;
       counter+=len2;
       move=RIGHT;
       break;
     case TYPE_OCTET_STRING:
+      if(p->value==NULL){
+       _asn1_error_description_value_not_found(p,ErrorDescription);
+       return ASN1_VALUE_NOT_FOUND;
+      }
       len2=_asn1_get_length_der(p->value,&len3);
-      memcpy(der+counter,p->value,len3+len2);
+      max_len-=len2+len3;
+      if(max_len>=0)
+       memcpy(der+counter,p->value,len3+len2);
       counter+=len3+len2;
       move=RIGHT;
       break;
     case TYPE_GENERALSTRING:
+      if(p->value==NULL){
+       _asn1_error_description_value_not_found(p,ErrorDescription);
+       return ASN1_VALUE_NOT_FOUND;
+      }
       len2=_asn1_get_length_der(p->value,&len3);
-      memcpy(der+counter,p->value,len3+len2);
+      max_len-=len2+len3;
+      if(max_len>=0)
+       memcpy(der+counter,p->value,len3+len2);
       counter+=len3+len2;
       move=RIGHT;
       break;
     case TYPE_BIT_STRING:
+      if(p->value==NULL){
+       _asn1_error_description_value_not_found(p,ErrorDescription);
+       return ASN1_VALUE_NOT_FOUND;
+      }
       len2=_asn1_get_length_der(p->value,&len3);
-      memcpy(der+counter,p->value,len3+len2);
+      max_len-=len2+len3;
+      if(max_len>=0)
+       memcpy(der+counter,p->value,len3+len2);
       counter+=len3+len2;
       move=RIGHT;
       break;
@@ -768,10 +872,14 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len,
       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);
+       if((type_field(p->type)==TYPE_SET) && (max_len>=0))
+         _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);
+       max_len-=len3;
+       if(max_len>=0){
+         memmove(der+len2+len3,der+len2,counter-len2);
+         memcpy(der+len2,temp,len3);
+       }
        counter+=len3;
        move=RIGHT;
       }
@@ -793,17 +901,27 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len,
       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);
+       if((type_field(p->type)==TYPE_SET_OF) && (max_len>=0))
+         _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);
+       max_len-=len3;
+       if(max_len>=0){
+         memmove(der+len2+len3,der+len2,counter-len2);
+         memcpy(der+len2,temp,len3);
+       }
        counter+=len3;
        move=RIGHT;
       }
       break;
     case TYPE_ANY:
+      if(p->value==NULL){
+       _asn1_error_description_value_not_found(p,ErrorDescription);
+       return ASN1_VALUE_NOT_FOUND;
+      }
       len2=_asn1_get_length_der(p->value,&len3);
-      memcpy(der+counter,p->value+len3,len2);
+      max_len-=len2;
+      if(max_len>=0)
+       memcpy(der+counter,p->value+len3,len2);
       counter+=len2;
       move=RIGHT;
       break;
@@ -812,8 +930,9 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len,
       break;
     }
 
-    if((move!=DOWN) && (counter!=counter_old))
-      _asn1_complete_explicit_tag(p,der,&counter);
+    if((move!=DOWN) && (counter!=counter_old)){
+      ris=_asn1_complete_explicit_tag(p,der,&counter,&max_len);
+    }
 
     if(p==node && move!=DOWN) break;
 
@@ -829,6 +948,9 @@ asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,int *len,
   }
 
   *len=counter;
+
+  if(max_len<0) return ASN1_MEM_ERROR;
+
   return ASN1_SUCCESS;
 }
 
index 811a476..0001388 100644 (file)
@@ -102,14 +102,15 @@ _asn1_get_octet_der(const unsigned char *der,int *der_len,unsigned char *str,int
 {
   int len_len;
 
-  if(str==NULL) return ASN1_SUCCESS;
+  /* if(str==NULL) return ASN1_SUCCESS; */
   *str_len=_asn1_get_length_der(der,&len_len);
+
+  *der_len=*str_len+len_len;
   if ( str_size >= *str_len)
          memcpy(str,der+len_len,*str_len);
   else {
        return ASN1_MEM_ERROR;
   }
-  *der_len=*str_len+len_len;
   
   return ASN1_SUCCESS;
 }
@@ -171,14 +172,14 @@ _asn1_get_bit_der(const unsigned char *der,int *der_len,unsigned char *str, int
 
   if(str==NULL) return ASN1_SUCCESS;
   len_byte=_asn1_get_length_der(der,&len_len)-1;
-  
+
+  *der_len=len_byte+len_len+1;  
   if (str_size >= len_byte)
        memcpy(str,der+len_len+1,len_byte);
   else {
        return ASN1_MEM_ERROR;
   }
   *bit_len=len_byte*8-der[len_len];
-  *der_len=len_byte+len_len+1;
 
   return ASN1_SUCCESS;
 }
index c38c8b9..8b71d05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2000,2001 Fabio Fiorina
+ *      Copyright (C) 2000,2001,2002,2003 Fabio Fiorina
  *
  * This file is part of LIBASN1.
  *
@@ -69,7 +69,7 @@ _asn1_hierarchical_name(node_asn *node,char *name,int name_size)
 /*              allocated).                                       */
 /*   value_out_size: number of bytes of value_out.                */
 /*   len: number of significant byte of value_out.                */
-/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS                                */
+/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS                         */
 /******************************************************************/
 asn1_retCode
 _asn1_convert_integer(const char *value,unsigned char *value_out,int value_out_size, int *len)
@@ -87,7 +87,7 @@ _asn1_convert_integer(const char *value,unsigned char *value_out,int value_out_s
 
   if(val[0]&0x80) negative=1;
   else negative=0;
-  
+
   for(k=0;k<SIZEOF_UNSIGNED_LONG_INT-1;k++){
     if(negative && (val[k]!=0xFF)) break;
     else if(!negative && val[k]) break;
@@ -96,6 +96,8 @@ _asn1_convert_integer(const char *value,unsigned char *value_out,int value_out_s
   if((negative && !(val[k]&0x80)) ||
      (!negative && (val[k]&0x80))) k--; 
 
+  *len=SIZEOF_UNSIGNED_LONG_INT-k;  
+
   if (SIZEOF_UNSIGNED_LONG_INT-k> value_out_size)
     /* VALUE_OUT is too short to contain the value convertion */
     return ASN1_MEM_ERROR;
@@ -103,8 +105,6 @@ _asn1_convert_integer(const char *value,unsigned char *value_out,int value_out_s
   for(k2=k;k2<SIZEOF_UNSIGNED_LONG_INT;k2++)
     value_out[k2-k]=val[k2];
 
-  *len=SIZEOF_UNSIGNED_LONG_INT-k;
-
 
 #ifdef LIBTASN1_DEBUG_INTEGER
   _libtasn1_log("_asn1_convert_integer: valueIn=%s, lenOut=%d",value,*len);
@@ -540,6 +540,9 @@ asn1_write_value(node_asn *node_root,const char *name,
   *   ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element.
   *
   *   ASN1_VALUE_NOT_FOUND\: there isn't any value for the element selected.
+  *
+  *   ASN1_MEM_ERROR\: the value vector isn't big enough to store the result.
+  *   In this case LEN will contain the number of bytes needed.
   * 
   * Examples: 
   *   a description for each type
@@ -585,7 +588,7 @@ asn1_write_value(node_asn *node_root,const char *name,
 asn1_retCode 
 asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len)
 {
-  node_asn *node,*p;
+  node_asn *node,*p,*p2;
   int len2,len3;
   int value_size = *len;
 
@@ -623,7 +626,25 @@ asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len)
     if((node->type&CONST_DEFAULT) && (node->value==NULL)){
       p=node->down;
       while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
-      if (_asn1_convert_integer(p->value,value,value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+      if((isdigit(p->value[0])) || (p->value[0]=='-') || (p->value[0]=='+')){
+       if (_asn1_convert_integer(p->value,value,value_size, len) != 
+           ASN1_SUCCESS) 
+         return ASN1_MEM_ERROR;
+      }
+      else{ /* is an identifier like v1 */
+       p2=node->down;
+       while(p2){
+         if(type_field(p2->type)==TYPE_CONSTANT){
+           if((p2->name) && (!strcmp(p2->name,p->value))){
+             if (_asn1_convert_integer(p2->value,value,value_size, len) != 
+                 ASN1_SUCCESS) 
+               return ASN1_MEM_ERROR;
+             break;
+           }
+         }
+         p2=p2->right;
+       }
+      }
     }
     else{
       len2=-1;
@@ -636,11 +657,9 @@ asn1_read_value(node_asn *root,const char *name,unsigned char *value, int *len)
       p=node->down;
       while(p){
        if(type_field(p->type)==TYPE_CONSTANT){
-         value_size-=strlen(p->value)+1;
-         if(value_size<1) return ASN1_MEM_ERROR;
-         strcat(value,p->value); 
+         ADD_STR_VALUE(value,value_size,p->value);       
          if(p->right) {
-           strcat(value,".");
+         ADD_STR_VALUE(value,value_size,".");
          }
        }
        p=p->right;
index f9c62b3..2c37e27 100644 (file)
--- a/lib/int.h
+++ b/lib/int.h
@@ -32,6 +32,8 @@
 
 #include <mem.h>
 
+#define LIBTASN1_VERSION "0.2.2"
+
 #define MAX32 4294967295
 #define MAX24 16777215
 #define MAX16 65535
index 31ceee3..b687ece 100644 (file)
@@ -28,7 +28,7 @@
 extern "C" {
 #endif
 
-#define LIBASN1_VERSION "0.2.1"
+#define LIBTASN1_VERSION "0.2.2"
 
 #include <sys/types.h>
 #include <time.h>
@@ -176,6 +176,8 @@ asn1_retCode asn1_read_tag(node_asn *root,const char *name,int *tag,
 asn1_retCode asn1_find_structure_from_oid(ASN1_TYPE definitions,
                    const char *oidValue,char *structureName);
 
+const char *asn1_check_version( const char *req_version );
+
 const char* libtasn1_strerror(asn1_retCode error);
 
 void libtasn1_perror(asn1_retCode error);
index a0f7775..2444f3d 100644 (file)
@@ -768,4 +768,79 @@ _asn1_set_default_tag(ASN1_TYPE node)
 
 
 
+static const char*
+parse_version_number( const char *s, int *number )
+{
+    int val = 0;
+
+    if( *s == '0' && isdigit(s[1]) )
+       return NULL; /* leading zeros are not allowed */
+    for ( ; isdigit(*s); s++ ) {
+       val *= 10;
+       val += *s - '0';
+    }
+    *number = val;
+    return val < 0? NULL : s;
+}
+
+/* The parse version functions were copied from libgcrypt.
+ */
+static const char *
+parse_version_string( const char *s, int *major, int *minor, int *micro )
+{
+    s = parse_version_number( s, major );
+    if( !s || *s != '.' )
+       return NULL;
+    s++;
+    s = parse_version_number( s, minor );
+    if( !s || *s != '.' )
+       return NULL;
+    s++;
+    s = parse_version_number( s, micro );
+    if( !s )
+       return NULL;
+    return s; /* patchlevel */
+}
+
+/**
+  * asn1_check_version - This function checks the library's version
+  * @req_version: the version to check
+  *
+  * Check that the the version of the library is at minimum the requested one
+  * and return the version string; return NULL if the condition is not
+  * satisfied.  If a NULL is passed to this function, no check is done,
+  * but the version string is simply returned.
+  *
+  **/
+const char *
+asn1_check_version( const char *req_version )
+{
+    const char *ver = LIBTASN1_VERSION;
+    int my_major, my_minor, my_micro;
+    int rq_major, rq_minor, rq_micro;
+    const char *my_plvl, *rq_plvl;
+
+    if ( !req_version )
+       return ver;
+
+    my_plvl = parse_version_string( ver, &my_major, &my_minor, &my_micro );
+    if ( !my_plvl )
+       return NULL;  /* very strange our own version is bogus */
+    rq_plvl = parse_version_string( req_version, &rq_major, &rq_minor,
+                                                               &rq_micro );
+    if ( !rq_plvl )
+       return NULL;  /* req version string is invalid */
+
+    if ( my_major > rq_major
+       || (my_major == rq_major && my_minor > rq_minor)
+       || (my_major == rq_major && my_minor == rq_minor
+                                && my_micro > rq_micro)
+       || (my_major == rq_major && my_minor == rq_minor
+                                && my_micro == rq_micro
+                                && strcmp( my_plvl, rq_plvl ) >= 0) ) {
+       return ver;
+    }
+    return NULL;
+}
+
 
index 2f3bf96..fc60cf9 100644 (file)
@@ -186,6 +186,9 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
   ASN1_TYPE param=ASN1_TYPE_EMPTY;
   ASN1_TYPE constr=ASN1_TYPE_EMPTY;
   char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
+  int max_len;
+
+  max_len=*der_len;
 
   result=asn1_create_element(cert_def,"PKIX1Implicit88.Certificate",&cert1);
  
@@ -222,6 +225,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
   result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
                          &value);
   result=asn1_write_value(value,"","US",2);
+  *der_len = max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -237,6 +241,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
                          &value);
   result=asn1_write_value(value,"","printableString",1);
   result=asn1_write_value(value,"printableString","gov",3);
+  *der_len = max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -253,6 +258,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
   result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
   result=asn1_write_value(value,"","printableString",1);
   result=asn1_write_value(value,"printableString","nist",4);
+  *der_len = max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(cert1,"tbsCertificate.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -279,6 +285,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
   result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
                          &value);
   result=asn1_write_value(value,"","US",2);
+  *der_len = max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -294,6 +301,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
                          &value);
   result=asn1_write_value(value,"","printableString",1);
   result=asn1_write_value(value,"printableString","gov",3);
+  *der_len = max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -309,6 +317,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
   result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
   result=asn1_write_value(value,"","printableString",1);
   result=asn1_write_value(value,"printableString","nist",4);
+  *der_len = max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(cert1,"tbsCertificate.subject.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -325,6 +334,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
   result=asn1_write_value(param,"q",str2,20);
   str2="\xd4\x38"; /* only an example */
   result=asn1_write_value(param,"g",str2,128);
+  *der_len = max_len;
   result=asn1_der_coding(param,"",der,der_len,errorDescription);
   asn1_delete_structure(&param);
   result=asn1_write_value(cert1,"tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",der,*der_len); 
@@ -347,6 +357,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
   result=asn1_create_element(cert_def,"PKIX1Implicit88.BasicConstraints",&constr);
   result=asn1_write_value(constr,"cA","TRUE",1); 
   result=asn1_write_value(constr,"pathLenConstraint",NULL,0); 
+  *der_len = max_len; 
   result=asn1_der_coding(constr,"",der,der_len,errorDescription);
   result=asn1_delete_structure(&constr);
   result=asn1_write_value(cert1,"tbsCertificate.extensions.?LAST.extnValue",der,*der_len); 
@@ -370,6 +381,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
 
 
   /* signature */
+  *der_len = max_len;
   result=asn1_der_coding(cert1,"tbsCertificate",der,der_len
                          ,errorDescription);
   if(result!=ASN1_SUCCESS){
@@ -384,7 +396,7 @@ create_certificate(node_asn *cert_def,unsigned char *der,int *der_len)
      asn1_visit_tree(cert1,"");  
      printf("-----------------\n"); */
 
-
+  *der_len = max_len;
   result=asn1_der_coding(cert1,"",der,der_len,errorDescription);
   if(result!=ASN1_SUCCESS){
     printf("\n'certificate' encoding creation: ERROR\n");
@@ -501,7 +513,7 @@ main(int argc,char *argv[])
      asn1_visit_tree(PKIX1Implicit88,"PKIX1Implicit88");   
      printf("-----------------\n"); */
 
-
+  der_len=1024;
   create_certificate(PKIX1Implicit88,der,&der_len);
 
   get_certificate(PKIX1Implicit88,der,der_len);
index 1aafbd7..2eba8c9 100644 (file)
@@ -194,6 +194,9 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len)
   ASN1_TYPE crl=ASN1_TYPE_EMPTY;
   ASN1_TYPE value=ASN1_TYPE_EMPTY;
   char errorDescription[MAX_ERROR_DESCRIPTION_SIZE];
+  int max_len;
+
+  max_len=*der_len;
 
   result=asn1_create_element(cert_def,"PKIX1Implicit88.CertificateList",&crl);
  
@@ -226,6 +229,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len)
   result=asn1_create_element(cert_def,"PKIX1Implicit88.X520countryName",
                          &value);
   result=asn1_write_value(value,"","US",2);
+  *der_len=max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
 
   asn1_delete_structure(&value);
@@ -242,6 +246,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len)
                          &value);
   result=asn1_write_value(value,"","printableString",1);
   result=asn1_write_value(value,"printableString","gov",3);
+  *der_len=max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(crl,"tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -257,6 +262,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len)
   result=asn1_create_element(cert_def,"PKIX1Implicit88.X520OrganizationalUnitName",&value);
   result=asn1_write_value(value,"","printableString",1);
   result=asn1_write_value(value,"printableString","nist",4);
+  *der_len=max_len;
   result=asn1_der_coding(value,"",der,der_len,errorDescription);
   asn1_delete_structure(&value);
   result=asn1_write_value(crl,"tbsCertList.issuer.rdnSequence.?LAST.?LAST.value",der,*der_len);
@@ -298,6 +304,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len)
   result=asn1_write_value(crl,"signatureAlgorithm.parameters",NULL,0); /* NO OPTION */  
 
   /* signature */
+  *der_len=max_len;
   result=asn1_der_coding(crl,"tbsCertList",der,der_len,errorDescription);
   if(result!=ASN1_SUCCESS){
     printf("\n'tbsCertList' encoding creation: ERROR\n");
@@ -313,7 +320,7 @@ create_CRL(node_asn *cert_def, unsigned char *der,int *der_len)
      asn1_visit_tree(crl,"");  
      printf("-----------------\n"); */
 
-
+  *der_len=max_len;
   result=asn1_der_coding(crl,"",der,der_len,errorDescription);
   if(result!=ASN1_SUCCESS){
     printf("\n'crl1' encoding creation: ERROR\n");
@@ -424,7 +431,7 @@ main(int argc,char *argv[])
      asn1_visit_tree(cert_def,"PKIX1Implicit88");   
      printf("-----------------\n"); */
 
-    
+  der_len=1024;
   create_CRL(PKIX1Implicit88,der,&der_len);
 
 
index 2688332..0480c77 100644 (file)
@@ -286,6 +286,7 @@ main(int argc,char *argv[])
  printf("\n");
  asn1_print_structure(stdout,structure,"",ASN1_PRINT_NAME_TYPE_VALUE);
 
+ der_len=1024;
  asn1_result=asn1_der_coding(structure,"",der,&der_len,
                              errorDescription);
  printf("\nCoding: %s\n\n",libtasn1_strerror(asn1_result));
index 7c36822..bd25fc7 100644 (file)
@@ -19,7 +19,7 @@ SequenceTestTag ::= SEQUENCE{
 
 
 Sequence1 ::= SEQUENCE{
-    int1 [0] INTEGER DEFAULT -5,
+    int1 [0] INTEGER {v1(0),v2(1),v3(2)} DEFAULT v2,
     int2     INTEGER,
     seq      SET OF INTEGER,
     id       OBJECT IDENTIFIER,
index b810c06..4270caf 100644 (file)
@@ -52,6 +52,8 @@
 #define ACT_READ_DEFINITIONS   14
 #define ACT_READ_TAG_CLASS     15
 #define ACT_OID_2_STRUCTURE    16
+#define ACT_READ_LENGTH        17
+#define ACT_ENCODING_LENGTH    18
 
 
 typedef struct{
@@ -88,17 +90,21 @@ test_type test_array[]={
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
 
-
   /* Test: OBJECT IDENTIFIER  elements */
   {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS},
+  {ACT_WRITE,"int1","v2",0,ASN1_SUCCESS},
+  {ACT_READ,"int1","\x01",1,ASN1_SUCCESS},
   {ACT_WRITE,"int2","0",0,ASN1_SUCCESS},
   {ACT_WRITE,"oct","\x02\x01\x0a",3,ASN1_SUCCESS},
   {ACT_WRITE,"id","1 2 3 4 5",0,ASN1_VALUE_NOT_VALID},
   {ACT_WRITE,"id","2.5.29.2",0,ASN1_SUCCESS},
   {ACT_READ,"id","2.5.29.2",9,ASN1_SUCCESS},
+  {ACT_READ_LENGTH,"id",NULL,9,ASN1_MEM_ERROR},
   {ACT_WRITE,"any1","\x02\x01\x05",3,ASN1_SUCCESS},
   {ACT_READ_DEFINITIONS,"TEST_TREE.id-anyTest","2.5.29.1",9,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING_LENGTH,"",0,20,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,19,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,200,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
   {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS},
@@ -115,61 +121,67 @@ test_type test_array[]={
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_WRITE,"","teletexString",0,ASN1_SUCCESS},
   {ACT_WRITE,"teletexString","PROVA",5,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING_LENGTH,"",0,7,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,6,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,7,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
   {ACT_CREATE,"TEST_TREE.X520LocalityName",0,0,ASN1_SUCCESS},
   {ACT_DECODING,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
-
+  
   /* Test: OPTIONAL elements */
   {ACT_CREATE,"TEST_TREE.DHParameter",0,0,ASN1_SUCCESS},
   {ACT_WRITE,"prime","1",0,ASN1_SUCCESS},
   {ACT_WRITE,"base","2",0,ASN1_SUCCESS},
   {ACT_WRITE,"privateValueLength",NULL,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING_LENGTH,"",0,8,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,7,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,8,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
   {ACT_CREATE,"TEST_TREE.DHParameter",0,0,ASN1_SUCCESS},
   {ACT_DECODING,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
-
+  
   /* Test: Integer */
   {ACT_CREATE,"TEST_TREE.AnyTest2",0,0,ASN1_SUCCESS},
   {ACT_WRITE,"","int",0,ASN1_SUCCESS},
   {ACT_WRITE,"int","0",0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING_LENGTH,"",0,3,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,2,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,3,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_WRITE,"int","-1",0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"",0,1024,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_WRITE,"int","1",0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"",0,1024,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_WRITE,"int","2000000000",0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"",0,1024,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_WRITE,"int","-2000000000",0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"",0,1024,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_WRITE,"int","-20000000000",0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"",0,1024,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_WRITE,"int","20000000000",0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"",0,1024,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
-
+  
   /* Test: elements without names */
   {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS},
   {ACT_WRITE,"int2","10",0,ASN1_SUCCESS},
@@ -181,37 +193,44 @@ test_type test_array[]={
   {ACT_NUMBER_OF_ELEMENTS,"seq","",2,ASN1_SUCCESS},
   {ACT_WRITE,"id","1.2.3.4",0,ASN1_SUCCESS},
   {ACT_WRITE,"oct","\x30\x03\x02\x01\x15",5,ASN1_SUCCESS},
-  {ACT_ENCODING,"int2",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"int2",0,1024,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
-  {ACT_ENCODING,"seq.?2",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING,"seq.?2",0,2,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"seq.?2",0,3,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING_LENGTH,"",0,25,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,24,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,25,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS},
   {ACT_DECODING_ELEMENT,"int2",0,0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_READ,"int2","\x0a",1,ASN1_SUCCESS},
+  {ACT_READ_LENGTH,"int2",NULL,1,ASN1_MEM_ERROR},
   {ACT_CREATE,"TEST_TREE.Sequence1",0,0,ASN1_SUCCESS},
   {ACT_DECODING,0,0,0,ASN1_SUCCESS},
   {ACT_DECODING_START_END,"seq.?2","START",10,ASN1_SUCCESS},
   {ACT_EXPAND_OCTET,"oct","id",0,ASN1_SUCCESS},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
-
+  
   /* Test GeneralString */
   {ACT_CREATE,"TEST_TREE.Test3",0,0,ASN1_SUCCESS},
   {ACT_WRITE,"a","1234",0,ASN1_SUCCESS},
   {ACT_WRITE,"b","prova",5,ASN1_SUCCESS},
-  {ACT_ENCODING,"",0,0,ASN1_SUCCESS},
+  {ACT_ENCODING_LENGTH,"",0,17,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,16,ASN1_MEM_ERROR},
+  {ACT_ENCODING,"",0,17,ASN1_SUCCESS},
   {ACT_PRINT_DER,0,0,0,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
   {ACT_CREATE,"TEST_TREE.Test3",0,0,ASN1_SUCCESS},
   {ACT_DECODING,0,0,0,ASN1_SUCCESS}, 
   {ACT_DECODING_ELEMENT,"b",0,0,ASN1_SUCCESS},
   {ACT_READ,"b","prova",5,ASN1_SUCCESS},
+  {ACT_READ_LENGTH,"b",NULL,5,ASN1_MEM_ERROR},
   {ACT_VISIT,"","",ASN1_PRINT_ALL,ASN1_SUCCESS},
   {ACT_DELETE,"","",0,ASN1_SUCCESS},
-
+  
 
 
   /* end */
@@ -239,6 +258,10 @@ main(int argc,char *argv[])
   printf(    "/*     Test sequence : Test_tree        */\n");
   printf(    "/****************************************/\n\n");
 
+  /* Check version */
+  if(asn1_check_version("0.2.2")==NULL)
+    printf("\nLibrary version check ERROR:\n actual version: %s\n\n",asn1_check_version(NULL));
+
   if(1)
     result=asn1_parser2tree("Test_tree.asn",&definitions,errorDescription);
   else
@@ -284,9 +307,13 @@ main(int argc,char *argv[])
        result=asn1_write_value(asn1_element,test->par1,test->par2,test->par3);
       break;
     case ACT_READ:
-      valueLen=1024;
+      valueLen=test->par3;
       result=asn1_read_value(asn1_element,test->par1,value,&valueLen);
       break;
+    case ACT_READ_LENGTH:
+      valueLen=0;
+      result=asn1_read_value(asn1_element,test->par1,NULL,&valueLen);
+      break;
     case ACT_READ_DEFINITIONS:
       valueLen=1024;
       result=asn1_read_value(definitions,test->par1,value,&valueLen);
@@ -295,9 +322,15 @@ main(int argc,char *argv[])
       result=asn1_read_tag(asn1_element,test->par1,&tag,&class);
       break;
     case ACT_ENCODING:
+      der_len=test->par3;
       result=asn1_der_coding(asn1_element,test->par1,der,&der_len,
                             errorDescription);
       break;
+    case ACT_ENCODING_LENGTH:
+      der_len=0;
+      result=asn1_der_coding(asn1_element,test->par1,NULL,&der_len,
+                            errorDescription);
+      break;
     case ACT_DECODING:
       result=asn1_der_decoding(&asn1_element,der,der_len,
                             errorDescription);
@@ -372,6 +405,7 @@ main(int argc,char *argv[])
       }
       break;
     case ACT_NUMBER_OF_ELEMENTS:
+    case ACT_READ_LENGTH:
       if((result != test->errorNumber) ||
         (valueLen != test->par3)){
        errorCounter++;
@@ -379,10 +413,22 @@ main(int argc,char *argv[])
        printf("  Action %d - %s\n",test->action,test->par1);
        printf("  Error expected: %s - %d\n",libtasn1_strerror(test->errorNumber),
                                              test->par3);
-       printf("\n  Error detected: %s - %d\n\n",libtasn1_strerror(result),
+       printf("  Error detected: %s - %d\n\n",libtasn1_strerror(result),
                                           valueLen);
       }
       break;
+    case ACT_ENCODING_LENGTH:
+      if((result != test->errorNumber) ||
+        (der_len != test->par3)){
+       errorCounter++;
+       printf("ERROR N. %d:\n",errorCounter);
+       printf("  Action %d - %s\n",test->action,test->par1);
+       printf("  Error expected: %s - %d\n",libtasn1_strerror(test->errorNumber),
+                                             test->par3);
+       printf("  Error detected: %s - %d\n\n",libtasn1_strerror(result),
+                                          der_len);
+      }
+      break;
     case ACT_OID_2_STRUCTURE:
       if((result != test->errorNumber) ||
         ((result == ASN1_SUCCESS) && (strcmp(value,test->par2)))){
index 6099e09..9db663d 100644 (file)
@@ -13,9 +13,88 @@ const ASN1_ARRAY_TYPE Test_tree_asn1_tab[]={
   {"pkix",1073741825,"7"},
   {"id-mod",1073741825,"0"},
   {"id-pkix1-implicit-88",1,"2"},
-  {"Sequence1",536870917,0},
-  {"int1",1610645507,0},
-  {0,9,"-5"},
-  {"int2",3,0},
+  {"SequenceTestTag",1610612741,0},
+  {"int1",1610620931,0},
+  {0,2056,"2"},
+  {"int2",1610620931,0},
+  {0,4104,"3"},
+  {"str1",1610620930,"PrintableString"},
+  {0,4104,"1"},
+  {"str2",1073741826,"UniversalString"},
+  {"str3",536879106,"UniversalString"},
+  {0,2056,"2"},
+  {"Sequence1",1610612741,0},
+  {"int1",1610915843,0},
+  {0,1073741833,"v2"},
+  {0,1073745928,"0"},
+  {"v1",1073741825,"0"},
+  {"v2",1073741825,"1"},
+  {"v3",1,"2"},
+  {"int2",1073741827,0},
+  {"seq",1610612751,0},
+  {0,3,0},
+  {"id",1073741836,0},
+  {"oct",1073741831,0},
+  {"any1",541081613,0},
+  {"id",1,0},
+  {"DHParameter",1610612741,0},
+  {"prime",1073741827,0},
+  {"base",1073741827,0},
+  {"privateValueLength",16387,0},
+  {"id-octetTest1",1879048204,0},
+  {0,1073741825,"1"},
+  {0,1073741825,"2"},
+  {0,1073741825,"3"},
+  {0,1,"4"},
+  {"Sequence_octetTest1",1610612741,0},
+  {"int",3,0},
+  {"AnyTest2",1610612754,0},
+  {"str",1073741831,0},
+  {"int",3,0},
+  {"id-ic",1879048204,0},
+  {0,1073741825,"2"},
+  {0,1,"5"},
+  {"id-anyTest",1879048204,0},
+  {0,1073741825,"id-ic"},
+  {0,1073741825,"29"},
+  {0,1,"1"},
+  {"id-anyTest2",1879048204,0},
+  {0,1073741825,"id-ic"},
+  {0,1073741825,"29"},
+  {0,1,"2"},
+  {"anyTest2",1073741827,0},
+  {"VisibleString",1610620935,0},
+  {0,4360,"26"},
+  {"NumericString",1610620935,0},
+  {0,4360,"18"},
+  {"IA5String",1610620935,0},
+  {0,4360,"22"},
+  {"TeletexString",1610620935,0},
+  {0,4360,"20"},
+  {"PrintableString",1610620935,0},
+  {0,4360,"19"},
+  {"UniversalString",1610620935,0},
+  {0,4360,"28"},
+  {"BMPString",1610620935,0},
+  {0,4360,"30"},
+  {"UTF8String",1610620935,0},
+  {0,4360,"12"},
+  {"Test3",1610612741,0},
+  {"a",1073741827,0},
+  {"b",536879106,"GeneralString2"},
+  {0,2056,"1"},
+  {"GeneralString2",1610620955,0},
+  {0,2056,"2"},
+  {"X520LocalityName",1610612754,0},
+  {"teletexString",1073741826,"TeletexString"},
+  {"printableString",1073741826,"PrintableString"},
+  {"universalString",1073741826,"UniversalString"},
+  {"utf8String",1073741826,"UTF8String"},
+  {"bmpString",2,"BMPString"},
+  {"id-Test",805306380,0},
+  {0,1073741825,"1"},
+  {0,1073741825,"2"},
+  {0,1073741825,"29"},
+  {0,1,"2"},
   {0,0,0}
 };