[gnutls-dev] Re: Libtasn1 0.2.18 - Tiny ASN.1 Library - Security release

Simon Josefsson jas at extundo.com
Sat Feb 11 11:19:56 CET 2006


On popular demand, we have prepared a minimal set of patches against
0.2.17 that will fix the security problem.

There is a branch in CVS called "libtasn1_0_2_17_security" that also
contain the minimal fixes for 0.2.17 you'll have to apply to get a
security libtasn1.

I'm including the patch below.  Please review it.

Astute readers may recognize that some _asn1* APIs have changed their
signature.  Those APIs are not exported, and are not intended to be
used by external applications.  Unfortunately, GnuTLS did use them.
We are considering to bump the so version in libtasn1_0_2_17_security
and in a new libtasn1 0.3.0.  We would then also have to deprecate
0.2.18 because it didn't bump the so version.  Comments on this
approach are appreciated.

Regards,
Simon

Index: lib/coding.c
===================================================================
RCS file: /cvs/gnutls/libtasn1/lib/coding.c,v
retrieving revision 1.16
retrieving revision 1.16.2.1
diff -u -p -r1.16 -r1.16.2.1
--- lib/coding.c	16 Jul 2005 11:25:32 -0000	1.16
+++ lib/coding.c	11 Feb 2006 10:00:11 -0000	1.16.2.1
@@ -1,22 +1,23 @@
 /*
+ *      Copyright (C) 2004, 2006 Free Software Foundation
  *      Copyright (C) 2002  Fabio Fiorina
- *      Copyright (C) 2004  Simon Josefsson
  *
- * This file is part of LIBASN1.
+ * This file is part of LIBTASN1.
  *
- * The LIBTASN1 library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public   
- * License as published by the Free Software Foundation; either 
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * This library 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
  */
 
 
@@ -148,7 +149,7 @@ _asn1_octet_der(const unsigned char *str
 {
   int len_len;
 
-  if(der==NULL) return;
+  if(der==NULL || str_len <= 0) return;
   _asn1_length_der(str_len,der,&len_len);
   memcpy(der+len_len,str,str_len);
   *der_len=str_len+len_len;
@@ -196,7 +197,8 @@ _asn1_get_utctime_der(unsigned char *der
   char temp[20];
 
   if(str==NULL) return;
-  str_len=_asn1_get_length_der(der,&len_len);
+  str_len=_asn1_get_length_der(der,*der_len,&len_len);
+  if (str_len<0) return;
   memcpy(temp,der+len_len,str_len);
   *der_len=str_len+len_len;
   switch(str_len){
@@ -534,7 +536,7 @@ _asn1_insert_tag_der(node_asn *node,unsi
 /* Return:                                            */
 /******************************************************/
 void
-_asn1_ordering_set(unsigned char *der,node_asn *node)
+_asn1_ordering_set(unsigned char *der, int der_len, node_asn *node)
 {
   struct vet{
     int end;
@@ -569,12 +571,14 @@ _asn1_ordering_set(unsigned char *der,no
     last=p_vet;
 
     /* tag value calculation */
-    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    if (_asn1_get_tag_der(der+counter, der_len-counter,&class,&len2, &tag)!=ASN1_SUCCESS)
+       return;
     p_vet->value=(class<<24)|tag;
     counter+=len2;
 
     /* extraction and length */
-    len2=_asn1_get_length_der(der+counter,&len);
+    len2=_asn1_get_length_der(der+counter,der_len-counter,&len);
+    if (len2<0) return;
     counter+=len+len2;
 
     p_vet->end=counter;
@@ -626,7 +630,7 @@ _asn1_ordering_set(unsigned char *der,no
 /* Return:                                            */
 /******************************************************/
 void
-_asn1_ordering_set_of(unsigned char *der,node_asn *node)
+_asn1_ordering_set_of(unsigned char *der, int der_len, node_asn *node)
 {
   struct vet{
     int end;
@@ -661,10 +665,16 @@ _asn1_ordering_set_of(unsigned char *der
     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;
+    if (der_len-counter > 0) {
+
+       if (_asn1_get_tag_der(der+counter, der_len - counter, &class,&len,NULL)!=ASN1_SUCCESS)
+          return;
+       counter+=len;
+    
+       len2=_asn1_get_length_der(der+counter,der_len-counter,&len);
+       if (len2<0) return;
+       counter+=len+len2;
+    }
 
     p_vet->end=counter;
     p=p->right;
@@ -804,7 +814,8 @@ asn1_der_coding(ASN1_TYPE element,const 
 	  _asn1_error_description_value_not_found(p,ErrorDescription);
 	  return ASN1_VALUE_NOT_FOUND;
 	}
-	len2=_asn1_get_length_der(p->value,&len3);
+	len2=_asn1_get_length_der(p->value,p->value_len, &len3);
+	if (len2<0) return ASN1_DER_ERROR;
 	max_len -= len2+len3;
 	if(max_len>=0)
 	  memcpy(der+counter,p->value,len3+len2);
@@ -846,7 +857,8 @@ asn1_der_coding(ASN1_TYPE element,const 
 	_asn1_error_description_value_not_found(p,ErrorDescription);
 	return ASN1_VALUE_NOT_FOUND;
       }
-      len2=_asn1_get_length_der(p->value,&len3);
+      len2=_asn1_get_length_der(p->value,p->value_len,&len3);
+      if (len2<0) return ASN1_DER_ERROR;
       max_len-=len2+len3;
       if(max_len>=0)
 	memcpy(der+counter,p->value,len3+len2);
@@ -858,7 +870,8 @@ asn1_der_coding(ASN1_TYPE element,const 
 	_asn1_error_description_value_not_found(p,ErrorDescription);
 	return ASN1_VALUE_NOT_FOUND;
       }
-      len2=_asn1_get_length_der(p->value,&len3);
+      len2=_asn1_get_length_der(p->value,p->value_len,&len3);
+      if (len2<0) return ASN1_DER_ERROR;
       max_len-=len2+len3;
       if(max_len>=0)
 	memcpy(der+counter,p->value,len3+len2);
@@ -870,7 +883,8 @@ asn1_der_coding(ASN1_TYPE element,const 
 	_asn1_error_description_value_not_found(p,ErrorDescription);
 	return ASN1_VALUE_NOT_FOUND;
       }
-      len2=_asn1_get_length_der(p->value,&len3);
+      len2=_asn1_get_length_der(p->value,p->value_len,&len3);
+      if (len2<0) return ASN1_DER_ERROR;
       max_len-=len2+len3;
       if(max_len>=0)
 	memcpy(der+counter,p->value,len3+len2);
@@ -903,7 +917,7 @@ asn1_der_coding(ASN1_TYPE element,const 
 	len2=strtol(p->value,NULL,10);
 	_asn1_set_value(p,NULL,0);
 	if((type_field(p->type)==TYPE_SET) && (max_len>=0))
-	  _asn1_ordering_set(der+len2,p);
+	  _asn1_ordering_set(der+len2, max_len-len2,p);
 	_asn1_length_der(counter-len2,temp,&len3);
 	max_len-=len3;
 	if(max_len>=0){
@@ -934,8 +948,9 @@ asn1_der_coding(ASN1_TYPE element,const 
       if(move==UP){
 	len2=strtol(p->value,NULL,10);
 	_asn1_set_value(p,NULL,0);
-	if((type_field(p->type)==TYPE_SET_OF) && (max_len>=0))
-	  _asn1_ordering_set_of(der+len2,p);
+	if((type_field(p->type)==TYPE_SET_OF) && (max_len-len2>0)) {
+	  _asn1_ordering_set_of(der+len2, max_len-len2,p);
+        }
 	_asn1_length_der(counter-len2,temp,&len3);
 	max_len-=len3;
 	if(max_len>=0){
@@ -951,7 +966,8 @@ asn1_der_coding(ASN1_TYPE element,const 
 	_asn1_error_description_value_not_found(p,ErrorDescription);
 	return ASN1_VALUE_NOT_FOUND;
       }
-      len2=_asn1_get_length_der(p->value,&len3);
+      len2=_asn1_get_length_der(p->value,p->value_len,&len3);
+      if (len2<0) return ASN1_DER_ERROR;
       max_len-=len2;
       if(max_len>=0)
 	memcpy(der+counter,p->value+len3,len2);
Index: lib/decoding.c
===================================================================
RCS file: /cvs/gnutls/libtasn1/lib/decoding.c,v
retrieving revision 1.26
retrieving revision 1.26.2.1
diff -u -p -r1.26 -r1.26.2.1
--- lib/decoding.c	16 Jul 2005 11:25:32 -0000	1.26
+++ lib/decoding.c	11 Feb 2006 10:00:11 -0000	1.26.2.1
@@ -1,22 +1,23 @@
 /*
+ *      Copyright (C) 2004, 2006 Free Software Foundation
  *      Copyright (C) 2002 Fabio Fiorina
- *      Copyright (C) 2004 Simon Josefsson
  *
- * This file is part of LIBASN1.
+ * This file is part of LIBTASN1.
  *
- * The LIBTASN1 library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public   
- * License as published by the Free Software Foundation; either 
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * This library 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
  */
  
 
@@ -47,11 +48,14 @@ _asn1_error_description_tag_error(node_a
 
   
 signed long
-_asn1_get_length_der(const unsigned char *der,int  *len)
+_asn1_get_length_der(const unsigned char *der, int der_len, int  *len)
 {
   unsigned long ans;
   int k,punt;
 
+  *len = 0;
+  if (der_len <= 0) return 0;
+
   if(!(der[0]&128)){
     /* short form */
     *len=1;
@@ -63,7 +67,13 @@ _asn1_get_length_der(const unsigned char
     punt=1;
     if(k){  /* definite length method */
       ans=0;
-      while(punt<=k) ans=ans*256+der[punt++];
+      while(punt<=k && punt < der_len) {
+	unsigned long last = ans;
+         ans=ans*256+der[punt++];
+	 if (ans < last)
+	   /* we wrapped around, no bignum support... */
+	   return -2;
+      }
     }
     else{  /* indefinite length method */
       ans=-1;
@@ -77,12 +87,14 @@ _asn1_get_length_der(const unsigned char
 
 
 
-unsigned int
-_asn1_get_tag_der(const unsigned char *der,unsigned char *class,int  *len)
+int
+_asn1_get_tag_der(const unsigned char *der, int der_len,
+                 unsigned char *class,int  *len, unsigned long *tag)
 {
   int punt,ris;
 
-  if (der==NULL || len == NULL) return ASN1_DER_ERROR;
+  if (der==NULL || der_len <= 0 || len == NULL) return ASN1_DER_ERROR;
+
   *class=der[0]&0xE0;
   if((der[0]&0x1F)!=0x1F){
     /* short form */
@@ -93,25 +105,46 @@ _asn1_get_tag_der(const unsigned char *d
     /* Long form */
     punt=1;
     ris=0;
-    while(der[punt]&128) ris=ris*128+(der[punt++]&0x7F);
-    ris=ris*128+(der[punt++]&0x7F);   
+    while(punt <= der_len && der[punt]&128)
+      {
+	int last = ris;
+	ris=ris*128+(der[punt++]&0x7F);
+	if (ris < last)
+	  /* wrapper around, and no bignums... */
+	  return ASN1_DER_ERROR;
+      }
+    if (punt >= der_len)
+      return ASN1_DER_ERROR;
+    {
+      int last = ris;
+      ris=ris*128+(der[punt++]&0x7F);
+      if (ris < last)
+	/* wrapper around, and no bignums... */
+	return ASN1_DER_ERROR;
+    }
     *len=punt;
   }
-  return ris;
+  if (tag) *tag = ris;
+  return ASN1_SUCCESS;
 }
 
 
 
 
 int
-_asn1_get_octet_der(const unsigned char *der,int *der_len,unsigned char *str,int str_size, int *str_len)
+_asn1_get_octet_der(const unsigned char *der, int der_len, int *ret_len,unsigned char *str,int str_size, int *str_len)
 {
   int len_len;
 
+  if (der_len <= 0) return ASN1_GENERIC_ERROR;
+
   /* if(str==NULL) return ASN1_SUCCESS; */
-  *str_len=_asn1_get_length_der(der,&len_len);
+  *str_len=_asn1_get_length_der(der, der_len, &len_len);
+  
+  if (*str_len < 0)
+     return ASN1_DER_ERROR;
 
-  *der_len=*str_len+len_len;
+  *ret_len=*str_len+len_len;
   if ( str_size >= *str_len)
 	  memcpy(str,der+len_len,*str_len);
   else {
@@ -126,17 +159,17 @@ _asn1_get_octet_der(const unsigned char 
 /* Returns ASN1_SUCCESS on success or an error code on error.
  */
 int
-_asn1_get_time_der(const unsigned char *der,int *der_len,unsigned char *str,int str_size)
+_asn1_get_time_der(const unsigned char *der, int der_len, int *ret_len,unsigned char *str,int str_size)
 {
   int len_len,str_len;
 
-  if(str==NULL) return ASN1_DER_ERROR;
-  str_len=_asn1_get_length_der(der,&len_len);
+  if(der_len <=0 || str==NULL) return ASN1_DER_ERROR;
+  str_len=_asn1_get_length_der(der, der_len, &len_len);
   if (str_len < 0 || str_size < str_len) 
      return ASN1_DER_ERROR;
   memcpy(str,der+len_len,str_len);
   str[str_len]=0;
-  *der_len=str_len+len_len;
+  *ret_len=str_len+len_len;
   
   return ASN1_SUCCESS;
 }
@@ -144,14 +177,19 @@ _asn1_get_time_der(const unsigned char *
 
 
 void
-_asn1_get_objectid_der(const unsigned char *der,int *der_len,unsigned char *str, int str_size)
+_asn1_get_objectid_der(const unsigned char *der,int der_len, int *ret_len,unsigned char *str, int str_size)
 {
   int len_len,len,k;
   char temp[20];
   unsigned long val,val1;
 
-  if(str==NULL) return;
-  len=_asn1_get_length_der(der,&len_len);
+  *ret_len = 0;
+  if (str && str_size > 0) str[0] = 0; /* no oid */
+
+  if(str==NULL || der_len <= 0) return;
+  len=_asn1_get_length_der(der,der_len, &len_len);
+  
+  if (len < 0 || len > der_len || len_len > der_len) return;
   
   val1=der[len_len]/40;
   val=der[len_len]-val1*40;
@@ -170,20 +208,24 @@ _asn1_get_objectid_der(const unsigned ch
       val=0;
     }
   }
-  *der_len=len+len_len;
+  *ret_len=len+len_len;
 }
 
 
 
 
 int
-_asn1_get_bit_der(const unsigned char *der,int *der_len,unsigned char *str, int str_size, int *bit_len)
+_asn1_get_bit_der(const unsigned char *der, int der_len,
+  int *ret_len,unsigned char *str, int str_size, int *bit_len)
 {
   int len_len,len_byte;
 
-  len_byte=_asn1_get_length_der(der,&len_len)-1;
+  if (der_len <=0) return ASN1_GENERIC_ERROR;
+  len_byte=_asn1_get_length_der(der,der_len,&len_len)-1;
+  if (len_byte < 0)
+    return ASN1_DER_ERROR;
 
-  *der_len=len_byte+len_len+1;  
+  *ret_len=len_byte+len_len+1;  
   *bit_len=len_byte*8-der[len_len];
 
   if (str_size >= len_byte)
@@ -199,14 +241,15 @@ _asn1_get_bit_der(const unsigned char *d
 
 
 int
-_asn1_extract_tag_der(node_asn *node,const unsigned char *der,int *der_len)
+_asn1_extract_tag_der(node_asn *node,const unsigned char *der, int der_len,int *ret_len)
 {
   node_asn *p;
   int counter,len2,len3,is_tag_implicit;
   unsigned long tag,tag_implicit=0;
   unsigned char class,class2,class_implicit=0;
 
-
+  if (der_len <= 0) return ASN1_GENERIC_ERROR;
+  
   counter=is_tag_implicit=0;
 
   if(node->type&CONST_TAG){
@@ -219,9 +262,14 @@ _asn1_extract_tag_der(node_asn *node,con
 	else class2=CONTEXT_SPECIFIC;
 	
 	if(p->type&CONST_EXPLICIT){
-	  tag=_asn1_get_tag_der(der+counter,&class,&len2);
+	  if (_asn1_get_tag_der(der+counter, der_len-counter,&class,&len2, &tag)!=ASN1_SUCCESS)
+	     return ASN1_DER_ERROR;
+	  if (counter+len2 > der_len)
+	    return ASN1_DER_ERROR;
 	  counter+=len2;
-	  len3=_asn1_get_length_der(der+counter,&len2);
+	  len3=_asn1_get_length_der(der+counter,der_len-counter, &len2);
+	  if (len3 < 0)
+	    return ASN1_DER_ERROR;
 	  counter+=len2;
 	  if(!is_tag_implicit){
 	    if((class!=(class2|STRUCTURED)) || (tag!=strtoul(p->value,NULL,10)))
@@ -251,7 +299,11 @@ _asn1_extract_tag_der(node_asn *node,con
   }
 
   if(is_tag_implicit){
-    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    if (_asn1_get_tag_der(der+counter, der_len-counter,&class,&len2, &tag)!=ASN1_SUCCESS)
+	     return ASN1_DER_ERROR;
+    if (counter+len2 > der_len)
+      return ASN1_DER_ERROR;
+
     if((class!=class_implicit) || (tag!=tag_implicit)){
       if(type_field(node->type)==TYPE_OCTET_STRING){
 	class_implicit |= STRUCTURED;
@@ -265,11 +317,15 @@ _asn1_extract_tag_der(node_asn *node,con
   else{
     if(type_field(node->type)==TYPE_TAG){
       counter=0;
-      *der_len=counter;
+      *ret_len=counter;
       return ASN1_SUCCESS;
     }
 
-    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    if (_asn1_get_tag_der(der+counter, der_len-counter,&class,&len2,&tag)!=ASN1_SUCCESS)
+     return ASN1_DER_ERROR;
+    if (counter+len2 > der_len)
+      return ASN1_DER_ERROR;
+
     switch(type_field(node->type)){
     case TYPE_NULL:
       if((class!=UNIVERSAL) || (tag!=TAG_NULL)) return ASN1_DER_ERROR;
@@ -323,7 +379,7 @@ _asn1_extract_tag_der(node_asn *node,con
   }
 
   counter+=len2;
-  *der_len=counter;
+  *ret_len=counter;
   return ASN1_SUCCESS;
 }
 
@@ -375,7 +431,7 @@ _asn1_delete_not_used(node_asn *node)
 
 
 asn1_retCode
-_asn1_get_octet_string(const unsigned char* der,node_asn *node,int* len)
+_asn1_get_octet_string(const unsigned char* der, node_asn *node,int* len)
 {
   int len2,len3,counter,counter2,counter_end,tot_len,indefinite;
   char *temp,*temp2;
@@ -384,7 +440,9 @@ _asn1_get_octet_string(const unsigned ch
 
   if(*(der-1) & STRUCTURED){
     tot_len=0;
-    indefinite=_asn1_get_length_der(der,&len3);
+    indefinite=_asn1_get_length_der(der, *len, &len3);
+    if (indefinite < -1)
+      return ASN1_DER_ERROR;
 
     counter+=len3;
     if(indefinite>=0) indefinite+=len3;
@@ -404,7 +462,7 @@ _asn1_get_octet_string(const unsigned ch
 	
       counter++;
 
-      len2=_asn1_get_length_der(der+counter,&len3);
+      len2=_asn1_get_length_der(der+counter,*len-counter, &len3);
       if(len2 <= 0) return ASN1_DER_ERROR;
 
       counter+=len3+len2;
@@ -422,24 +480,33 @@ _asn1_get_octet_string(const unsigned ch
       _asn1_length_der(tot_len,temp,&len2);
       tot_len+=len2;
       temp2=temp+len2;
-      len2=_asn1_get_length_der(der,&len3);
+      len2=_asn1_get_length_der(der,*len,&len3);
+      if(len2 < -1) return ASN1_DER_ERROR;
       counter2=len3+1;
 
       if(indefinite==-1) counter_end=counter-2;
       else counter_end=counter;
       
       while(counter2<counter_end){
-	len2=_asn1_get_length_der(der+counter2,&len3);	
+	len2=_asn1_get_length_der(der+counter2, *len-counter, &len3);
+	if(len2 < -1) return ASN1_DER_ERROR;
+
+	/* FIXME: to be checked. Is this ok? Has the
+	 * size been checked before?
+	 */
 	memcpy(temp2,der+counter2+len3,len2);
 	temp2+=len2;
 	counter2+=len2+len3+1;
       }
+      
       _asn1_set_value(node,temp,tot_len);
       _asn1_afree(temp);
     }
   }
   else{  /* NOT STRUCTURED */
-    len2=_asn1_get_length_der(der,&len3);
+    len2=_asn1_get_length_der(der, *len, &len3);
+    if(len2 < 0) return ASN1_DER_ERROR;
+    if (len3+len2 > *len) return ASN1_DER_ERROR;
     if(node)
       _asn1_set_value(node,der,len3+len2);
     counter=len3+len2;
@@ -452,10 +519,10 @@ _asn1_get_octet_string(const unsigned ch
 
 
 asn1_retCode
-_asn1_get_indefinite_length_string(const unsigned char* der,int* len)
+_asn1_get_indefinite_length_string(const unsigned char* der, int* len)
 {
   int len2,len3,counter,indefinite;
-  unsigned int tag;
+  unsigned long tag;
   unsigned char class;
 
   counter=indefinite=0;
@@ -470,9 +537,13 @@ _asn1_get_indefinite_length_string(const
       else continue;
     }
 
-    tag=_asn1_get_tag_der(der+counter,&class,&len2);
+    if(_asn1_get_tag_der(der+counter, *len-counter,&class,&len2,&tag)!=ASN1_SUCCESS)
+     return ASN1_DER_ERROR;
+    if (counter+len2 > *len)
+      return ASN1_DER_ERROR;
     counter+=len2;
-    len2=_asn1_get_length_der(der+counter,&len3);
+    len2=_asn1_get_length_der(der+counter, *len-counter,&len3);
+    if(len2 < -1) return ASN1_DER_ERROR;
     if(len2 == -1){
       indefinite++;
       counter+=1;
@@ -520,7 +591,7 @@ asn1_der_decoding(ASN1_TYPE *element,con
   char temp[128];
   int counter,len2,len3,len4,move,ris,tlen;
   unsigned char class,*temp2;
-  unsigned int tag;
+  unsigned long tag;
   int indefinite, result;
   const unsigned char* der = ider;
 
@@ -563,11 +634,11 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	while(p2){
 	  if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){
 	    if(type_field(p2->type)!=TYPE_CHOICE)
-	      ris=_asn1_extract_tag_der(p2,der+counter,&len2);
+	      ris=_asn1_extract_tag_der(p2,der+counter,len-counter, &len2);
 	    else{
 	      p3=p2->down;
 	      while(p3){
-		ris=_asn1_extract_tag_der(p3,der+counter,&len2);
+		ris=_asn1_extract_tag_der(p3,der+counter,len-counter, &len2);
 		if(ris==ASN1_SUCCESS) break;
 		p3=p3->right;
 	      }
@@ -606,7 +677,7 @@ asn1_der_decoding(ASN1_TYPE *element,con
       if(type_field(p->type)==TYPE_CHOICE){
 	while(p->down){
 	  if(counter<len)
-	    ris=_asn1_extract_tag_der(p->down,der+counter,&len2);
+	    ris=_asn1_extract_tag_der(p->down,der+counter,len-counter,&len2);
 	  else
 	    ris=ASN1_DER_ERROR;
 	  if(ris==ASN1_SUCCESS){
@@ -642,7 +713,7 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	if((len2!=-1) && (counter>len2)) ris=ASN1_TAG_ERROR;
       }
      
-      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,&len2);
+      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,len-counter,&len2);
       if(ris!=ASN1_SUCCESS){
 	if(p->type&CONST_OPTION){
 	  p->type|=CONST_NOT_USED;
@@ -683,13 +754,15 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	move=RIGHT;
 	break;
       case TYPE_INTEGER: case TYPE_ENUMERATED:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter, &len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
+	if (len2+len3 > len-counter) return ASN1_DER_ERROR;
 	_asn1_set_value(p,der+counter,len3+len2);
 	counter+=len3+len2;
 	move=RIGHT;
 	break;
       case TYPE_OBJECT_ID:
-	_asn1_get_objectid_der(der+counter,&len2, temp, sizeof(temp));
+	_asn1_get_objectid_der(der+counter,len-counter,&len2, temp, sizeof(temp));
 	tlen = strlen(temp);
 	if( tlen > 0)
 	   _asn1_set_value(p,temp,tlen+1);
@@ -697,7 +770,7 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	move=RIGHT;
       break;
       case TYPE_TIME:
-	result = _asn1_get_time_der(der+counter,&len2,temp,sizeof(temp)-1);
+	result = _asn1_get_time_der(der+counter,len-counter,&len2,temp,sizeof(temp)-1);
 	if (result != ASN1_SUCCESS) {
 		asn1_delete_structure(element);
 	        return result;
@@ -716,14 +789,18 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	move=RIGHT;
 	break;
       case TYPE_GENERALSTRING:
-	len2=_asn1_get_length_der(der+counter,&len3);
-	_asn1_set_value(p,der+counter,len3+len2);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
+	if (len3+len2 > len-counter) return ASN1_DER_ERROR;
+	   _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);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
+	if (len3+len2 > len-counter) return ASN1_DER_ERROR;
+  	   _asn1_set_value(p,der+counter,len3+len2);
 	counter+=len3+len2;
 	move=RIGHT;
 	break;
@@ -732,10 +809,12 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	  len2=strtol(p->value,NULL,10);
 	  _asn1_set_value(p,NULL,0);
 	  if(len2==-1){ /* indefinite length method */
-	    if((der[counter]) || der[counter+1]){
-	      asn1_delete_structure(element);
-	      return ASN1_DER_ERROR;
-	    }
+	    if (len-counter+1 > 0) {
+ 	      if((der[counter]) || der[counter+1]){
+	        asn1_delete_structure(element);
+	        return ASN1_DER_ERROR;
+	      }
+            } else return ASN1_DER_ERROR;
 	    counter+=2;
 	  }
 	  else{ /* definite length method */
@@ -747,7 +826,8 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	  move=RIGHT;
 	}
 	else{   /* move==DOWN || move==RIGHT */
-	  len3=_asn1_get_length_der(der+counter,&len2);
+	  len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	  if(len3 < -1) return ASN1_DER_ERROR;
 	  counter+=len2;
 	  if(len3>0){
 	    _asn1_ltostr(counter+len3,temp);
@@ -806,7 +886,8 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	  }
 	}
 	else{   /* move==DOWN || move==RIGHT */
-	  len3=_asn1_get_length_der(der+counter,&len2);
+	  len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	  if(len3 < -1) return ASN1_DER_ERROR;
 	  counter+=len2;
 	  if(len3){
 	    if(len3>0){ /* definite length method */
@@ -828,9 +909,13 @@ asn1_der_decoding(ASN1_TYPE *element,con
 	move=RIGHT;
 	break;
       case TYPE_ANY:
-	tag=_asn1_get_tag_der(der+counter,&class,&len2);
-	len4=_asn1_get_length_der(der+counter+len2,&len3);
-	
+	if(_asn1_get_tag_der(der+counter,len-counter,&class,&len2,&tag)!=ASN1_SUCCESS)
+       return ASN1_DER_ERROR;
+	if (counter+len2 > len)
+	  return ASN1_DER_ERROR;
+	len4=_asn1_get_length_der(der+counter+len2,len-counter-len2,&len3);
+	if(len4 < -1) return ASN1_DER_ERROR;
+	if(len4 > len-counter+len2+len3) return ASN1_DER_ERROR;
 	if(len4 != -1){
 	  len2+=len4;
 	  _asn1_length_der(len2+len3,NULL,&len4);
@@ -955,7 +1040,7 @@ asn1_der_decoding_element(ASN1_TYPE *str
   int nameLen=MAX_NAME_SIZE*10-1,state;
   int counter,len2,len3,len4,move,ris, tlen;
   unsigned char class,*temp2;
-  unsigned int tag;
+  unsigned long tag;
   int indefinite, result;
   const unsigned char* der = ider;
 
@@ -1024,11 +1109,11 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	while(p2){
 	  if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){
 	    if(type_field(p2->type)!=TYPE_CHOICE)
-	      ris=_asn1_extract_tag_der(p2,der+counter,&len2);
+	      ris=_asn1_extract_tag_der(p2,der+counter,len-counter,&len2);
 	    else{
 	      p3=p2->down;
 	      while(p3){
-		ris=_asn1_extract_tag_der(p3,der+counter,&len2);
+		ris=_asn1_extract_tag_der(p3,der+counter,len-counter,&len2);
 		if(ris==ASN1_SUCCESS) break;
 		p3=p3->right;
 	      }
@@ -1067,7 +1152,7 @@ asn1_der_decoding_element(ASN1_TYPE *str
       if(type_field(p->type)==TYPE_CHOICE){
 	while(p->down){
 	  if(counter<len)
-	    ris=_asn1_extract_tag_der(p->down,der+counter,&len2);
+	    ris=_asn1_extract_tag_der(p->down,der+counter,len-counter,&len2);
 	  else
 	    ris=ASN1_DER_ERROR;
 	  if(ris==ASN1_SUCCESS){
@@ -1103,7 +1188,7 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	if(counter>len2) ris=ASN1_TAG_ERROR;
       }
 
-      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,&len2);
+      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,len-counter,&len2);
       if(ris!=ASN1_SUCCESS){
 	if(p->type&CONST_OPTION){
 	  p->type|=CONST_NOT_USED;
@@ -1156,8 +1241,10 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	move=RIGHT;
 	break;
       case TYPE_INTEGER: case TYPE_ENUMERATED:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	if(state==FOUND){
+	  if (len3+len2 > len-counter) return ASN1_DER_ERROR;
 	  _asn1_set_value(p,der+counter,len3+len2);
 	  
 	  if(p==nodeFound) state=EXIT;
@@ -1167,7 +1254,7 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	break;
       case TYPE_OBJECT_ID:
 	if(state==FOUND){
-	  _asn1_get_objectid_der(der+counter,&len2, temp, sizeof(temp));
+	  _asn1_get_objectid_der(der+counter,len-counter,&len2, temp, sizeof(temp));
 	  tlen = strlen(temp);
 	  
 	  if (tlen > 0)
@@ -1176,7 +1263,8 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	  if(p==nodeFound) state=EXIT;
 	}
 	else{
-	  len2=_asn1_get_length_der(der+counter,&len3);
+	  len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	  if(len2 < 0) return ASN1_DER_ERROR;
 	  len2+=len3;
 	}
 
@@ -1185,7 +1273,7 @@ asn1_der_decoding_element(ASN1_TYPE *str
       break;
       case TYPE_TIME:
 	if(state==FOUND){
-	  result = _asn1_get_time_der(der+counter,&len2,temp,sizeof(temp)-1);
+	  result = _asn1_get_time_der(der+counter,len-counter,&len2,temp,sizeof(temp)-1);
 	  if (result != ASN1_SUCCESS) {
 		asn1_delete_structure(structure);
 	        return result;
@@ -1198,7 +1286,8 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	  if(p==nodeFound) state=EXIT;
 	}
 	else{
-	  len2=_asn1_get_length_der(der+counter,&len3);
+	  len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	  if(len2 < 0) return ASN1_DER_ERROR;
 	  len2+=len3;
 	}
 
@@ -1219,8 +1308,10 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	move=RIGHT;
 	break;
       case TYPE_GENERALSTRING:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	if(state==FOUND){
+	  if (len3+len2 > len-counter) return ASN1_DER_ERROR;
 	  _asn1_set_value(p,der+counter,len3+len2);
 	 
 	  if(p==nodeFound) state=EXIT;
@@ -1229,8 +1320,10 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	move=RIGHT;
 	break;
       case TYPE_BIT_STRING:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	if(state==FOUND){
+	  if (len3+len2 > len-counter) return ASN1_DER_ERROR;
 	  _asn1_set_value(p,der+counter,len3+len2);
 	  
 	  if(p==nodeFound) state=EXIT;
@@ -1260,12 +1353,14 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	}
 	else{   /* move==DOWN || move==RIGHT */
 	  if(state==OTHER_BRANCH){
-	    len3=_asn1_get_length_der(der+counter,&len2);
+	    len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	    if(len3 < 0) return ASN1_DER_ERROR;
 	    counter+=len2+len3;
 	    move=RIGHT;
 	  }
 	  else { /*  state==SAME_BRANCH or state==FOUND */
-	    len3=_asn1_get_length_der(der+counter,&len2);
+	    len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	    if(len3 < 0) return ASN1_DER_ERROR;
 	    counter+=len2;
 	    if(len3>0){
 	      _asn1_ltostr(counter+len3,temp);
@@ -1315,12 +1410,14 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	}
 	else{   /* move==DOWN || move==RIGHT */
 	  if(state==OTHER_BRANCH){
-	    len3=_asn1_get_length_der(der+counter,&len2);
+	    len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	    if(len3 < 0) return ASN1_DER_ERROR;
 	    counter+=len2+len3;
 	    move=RIGHT;
 	  }
 	  else{ /* state==FOUND or state==SAME_BRANCH */
-	    len3=_asn1_get_length_der(der+counter,&len2);
+	    len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	    if(len3 < 0) return ASN1_DER_ERROR;
 	    counter+=len2;
 	    if(len3){
 	      _asn1_ltostr(counter+len3,temp);
@@ -1339,9 +1436,14 @@ asn1_der_decoding_element(ASN1_TYPE *str
 	
 	break;
       case TYPE_ANY:
-	tag=_asn1_get_tag_der(der+counter,&class,&len2);
-	len4=_asn1_get_length_der(der+counter+len2,&len3);
-	
+	if(_asn1_get_tag_der(der+counter, len-counter,&class,&len2,&tag)!=ASN1_SUCCESS)
+          return ASN1_DER_ERROR;
+	if (counter+len2 > len)
+	  return ASN1_DER_ERROR;
+
+	len4=_asn1_get_length_der(der+counter+len2,len-counter-len2,&len3);
+	if(len4 < -1) return ASN1_DER_ERROR;
+
 	if(len4 != -1){
 	  len2+=len4;
 	  if(state==FOUND){
@@ -1549,7 +1651,7 @@ asn1_der_decoding_startEnd(ASN1_TYPE ele
   node_asn *node,*node_to_find,*p,*p2,*p3;
   int counter,len2,len3,len4,move,ris;
   unsigned char class;
-  unsigned int tag;
+  unsigned long tag;
   int indefinite;
   const unsigned char* der = ider;
 
@@ -1597,10 +1699,10 @@ asn1_der_decoding_startEnd(ASN1_TYPE ele
 	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);
+	      ris=_asn1_extract_tag_der(p2,der+counter,len-counter,&len2);
 	    else{
 	      p3=p2->down;
-	      ris=_asn1_extract_tag_der(p3,der+counter,&len2);
+	      ris=_asn1_extract_tag_der(p3,der+counter,len-counter,&len2);
 	    }
 	    if(ris==ASN1_SUCCESS){
 	      p2->type&=~CONST_NOT_USED;
@@ -1617,11 +1719,11 @@ asn1_der_decoding_startEnd(ASN1_TYPE ele
 
       if(type_field(p->type)==TYPE_CHOICE){
 	p=p->down;
-	ris=_asn1_extract_tag_der(p,der+counter,&len2);
+	ris=_asn1_extract_tag_der(p,der+counter,len-counter,&len2);
 	if(p==node_to_find) *start=counter;
       }
 
-      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,&len2);
+      if(ris==ASN1_SUCCESS) ris=_asn1_extract_tag_der(p,der+counter,len-counter,&len2);
       if(ris!=ASN1_SUCCESS){
 	if(p->type&CONST_OPTION){
 	  p->type|=CONST_NOT_USED;
@@ -1650,17 +1752,20 @@ asn1_der_decoding_startEnd(ASN1_TYPE ele
 	move=RIGHT;
 	break;
       case TYPE_INTEGER: case TYPE_ENUMERATED:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	counter+=len3+len2;
 	move=RIGHT;
 	break;
       case TYPE_OBJECT_ID:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	counter+=len2+len3;
 	move=RIGHT;
       break;
       case TYPE_TIME:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	counter+=len2+len3;
 	move=RIGHT;
 	break;
@@ -1672,18 +1777,21 @@ asn1_der_decoding_startEnd(ASN1_TYPE ele
 	move=RIGHT;
 	break;
       case TYPE_GENERALSTRING:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	counter+=len3+len2;
 	move=RIGHT;
 	break;
       case TYPE_BIT_STRING:
-	len2=_asn1_get_length_der(der+counter,&len3);
+	len2=_asn1_get_length_der(der+counter,len-counter,&len3);
+	if(len2 < 0) return ASN1_DER_ERROR;
 	counter+=len3+len2;
 	move=RIGHT;
 	break;
       case TYPE_SEQUENCE:  case TYPE_SET:
 	if(move!=UP){
-	  len3=_asn1_get_length_der(der+counter,&len2);
+	  len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	  if(len3 < -1) return ASN1_DER_ERROR;
 	  counter+=len2;
 	  if(len3==0) move=RIGHT;
 	  else move=DOWN; 
@@ -1696,7 +1804,8 @@ asn1_der_decoding_startEnd(ASN1_TYPE ele
 	break;
       case TYPE_SEQUENCE_OF: case TYPE_SET_OF:
 	if(move!=UP){
-	  len3=_asn1_get_length_der(der+counter,&len2);
+	  len3=_asn1_get_length_der(der+counter,len-counter,&len2);
+	  if(len3 < -1) return ASN1_DER_ERROR;
 	  counter+=len2;
 	  if((len3==-1) && !der[counter] && !der[counter+1])
 	    counter+=2;
@@ -1714,9 +1823,14 @@ asn1_der_decoding_startEnd(ASN1_TYPE ele
 	move=RIGHT;
 	break;
       case TYPE_ANY:
-	tag=_asn1_get_tag_der(der+counter,&class,&len2);
-	len4=_asn1_get_length_der(der+counter+len2,&len3);
-	
+	if (_asn1_get_tag_der(der+counter, len-counter,&class,&len2,&tag)!=ASN1_SUCCESS)
+        return ASN1_DER_ERROR;
+	if (counter+len2 > len)
+	  return ASN1_DER_ERROR;
+
+	len4=_asn1_get_length_der(der+counter+len2,len-counter-len2,&len3);
+	if(len4 < -1) return ASN1_DER_ERROR;
+
 	if(len4 != -1){
 	  counter+=len2+len4+len3;
 	}
@@ -1887,8 +2001,9 @@ asn1_expand_any_defined_by(ASN1_TYPE def
 		result=asn1_create_element(definitions,name,&aux);
 		if(result == ASN1_SUCCESS){
 		  _asn1_set_name(aux,p->name);
-		  len2=_asn1_get_length_der(p->value,&len3);
-		  
+		  len2=_asn1_get_length_der(p->value,p->value_len,&len3);
+		  if(len2 < 0) return ASN1_DER_ERROR;
+
 		  result=asn1_der_decoding(&aux,p->value+len3,len2,
 					   errorDescription);
 		  if(result == ASN1_SUCCESS){
@@ -2051,8 +2166,9 @@ asn1_expand_octet_string(ASN1_TYPE defin
 	  result=asn1_create_element(definitions,name,&aux);
 	  if(result == ASN1_SUCCESS){
 	    _asn1_set_name(aux,octetNode->name);	  
-	    len2=_asn1_get_length_der(octetNode->value,&len3);
-	    
+	    len2=_asn1_get_length_der(octetNode->value,octetNode->value_len,&len3);
+	    if(len2 < 0) return ASN1_DER_ERROR;
+
 	    result=asn1_der_decoding(&aux,octetNode->value+len3,len2,
 				     errorDescription);
 	    if(result == ASN1_SUCCESS){
Index: lib/der.h
===================================================================
RCS file: /cvs/gnutls/libtasn1/lib/der.h,v
retrieving revision 1.6
retrieving revision 1.6.2.1
diff -u -p -r1.6 -r1.6.2.1
--- lib/der.h	30 Jul 2003 19:52:56 -0000	1.6
+++ lib/der.h	11 Feb 2006 10:00:11 -0000	1.6.2.1
@@ -28,23 +28,23 @@
 #define TAG_NULL             0x05
 #define TAG_GENERALSTRING    0x1B
 
-unsigned int _asn1_get_tag_der(const unsigned char *der,
-                unsigned char *class,int  *len);
+int _asn1_get_tag_der(const unsigned char *der, int der_len,
+                unsigned char *class,int  *len, unsigned long *tag);
 
 void _asn1_octet_der(const unsigned char *str,int str_len,
                      unsigned char *der,int *der_len);
 
-asn1_retCode _asn1_get_octet_der(const unsigned char *der,
-                int *der_len,unsigned char *str,int str_size, int *str_len);
+asn1_retCode _asn1_get_octet_der(const unsigned char *der, int der_len,
+                int *ret_len,unsigned char *str,int str_size, int *str_len);
 
 void _asn1_bit_der(const unsigned char *str,int bit_len,
                    unsigned char *der,int *der_len);
 
-asn1_retCode _asn1_get_bit_der(const unsigned char *der,
-                int *der_len,unsigned char *str, int str_size, 
+asn1_retCode _asn1_get_bit_der(const unsigned char *der, int der_len,
+                int *ret_len,unsigned char *str, int str_size, 
                 int *bit_len);
 
-signed long _asn1_get_length_der(const unsigned char *der,int  *len);
+signed long _asn1_get_length_der(const unsigned char *der,int der_len, int  *len);
 
 void _asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len);
 
Index: lib/element.c
===================================================================
RCS file: /cvs/gnutls/libtasn1/lib/element.c,v
retrieving revision 1.22
retrieving revision 1.22.2.1
diff -u -p -r1.22 -r1.22.2.1
--- lib/element.c	16 Jul 2005 11:25:32 -0000	1.22
+++ lib/element.c	11 Feb 2006 10:00:11 -0000	1.22.2.1
@@ -1,22 +1,23 @@
 /*
+ *      Copyright (C) 2004, 2006 Free Software Foundation
  *      Copyright (C) 2000, 2001, 2002, 2003 Fabio Fiorina
- *      Copyright (C) 2004 Simon Josefsson
  *
- * This file is part of LIBASN1.
+ * This file is part of LIBTASN1.
  *
- * The LIBTASN1 library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
  */
 
 /*****************************************************/
@@ -677,7 +678,7 @@ asn1_read_value(ASN1_TYPE root,const cha
     }
     else{
       len2=-1;
-      if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+      if (_asn1_get_octet_der(node->value,node->value_len,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
     }
     break;
   case TYPE_OBJECT_ID:
@@ -709,22 +710,23 @@ asn1_read_value(ASN1_TYPE root,const cha
     break;
   case TYPE_OCTET_STRING:
     len2=-1;
-    if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+    if (_asn1_get_octet_der(node->value,node->value_len,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
     break;
   case TYPE_GENERALSTRING:
     len2=-1;
-    if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+    if (_asn1_get_octet_der(node->value,node->value_len,&len2,value, value_size, len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
     break;
   case TYPE_BIT_STRING:
     len2=-1;
-    if (_asn1_get_bit_der(node->value,&len2,value,value_size,len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
+    if (_asn1_get_bit_der(node->value,node->value_len,&len2,value,value_size,len)!=ASN1_SUCCESS) return ASN1_MEM_ERROR;
     break;
   case TYPE_CHOICE:
     PUT_STR_VALUE( value, value_size, node->down->name);
     break; 
   case TYPE_ANY:
     len3=-1;
-    len2=_asn1_get_length_der(node->value,&len3);
+    len2=_asn1_get_length_der(node->value,node->value_len,&len3);
+    if (len2 < 0) return ASN1_DER_ERROR;
     PUT_VALUE( value, value_size, node->value+len3, len2);
     break;
   default:
Index: lib/libtasn1.h
===================================================================
RCS file: /cvs/gnutls/libtasn1/lib/libtasn1.h,v
retrieving revision 1.30
retrieving revision 1.30.2.1
diff -u -p -r1.30 -r1.30.2.1
--- lib/libtasn1.h	31 Aug 2005 13:17:47 -0000	1.30
+++ lib/libtasn1.h	11 Feb 2006 10:00:11 -0000	1.30.2.1
@@ -1,6 +1,6 @@
 /*
+ *      Copyright (C) 2004, 2005, 2006 Free Software Foundation
  *      Copyright (C) 2002 Fabio Fiorina
- *      Copyright (C) 2004, 2005 Simon Josefsson
  *
  * This file is part of LIBTASN1.
  *
@@ -108,6 +108,7 @@ typedef struct node_asn_struct{
   char *name;                    /* Node name */
   unsigned int type;             /* Node type */
   unsigned char *value;          /* Node value */
+  int value_len;
   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 */ 
Index: lib/parser_aux.c
===================================================================
RCS file: /cvs/gnutls/libtasn1/lib/parser_aux.c,v
retrieving revision 1.13
retrieving revision 1.13.2.1
diff -u -p -r1.13 -r1.13.2.1
--- lib/parser_aux.c	16 Jul 2005 11:25:32 -0000	1.13
+++ lib/parser_aux.c	11 Feb 2006 10:00:11 -0000	1.13.2.1
@@ -1,22 +1,23 @@
 /*
+ *      Copyright (C) 2004, 2006 Free Software Foundation
  *      Copyright (C) 2000,2001 Fabio Fiorina
- *      Copyright (C) 2004 Simon Josefsson
  *
- * This file is part of LIBASN1.
+ * This file is part of LIBTASN1.
  *
- * The LIBTASN1 library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public   
- * License as published by the Free Software Foundation; either 
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * This library 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
  */
 
 #include <int.h>
@@ -187,10 +188,12 @@ _asn1_set_value(node_asn *node,const uns
   if(node->value){
     _asn1_free(node->value);
     node->value=NULL;  
+    node->value_len = 0;
   }
   if(!len) return node;
   node->value=(unsigned char *) _asn1_malloc(len);
   if (node->value==NULL) return NULL;
+  node->value_len = len;
   
   memcpy(node->value,value,len);
   return node;
Index: lib/structure.c
===================================================================
RCS file: /cvs/gnutls/libtasn1/lib/structure.c,v
retrieving revision 1.21
retrieving revision 1.21.2.1
diff -u -p -r1.21 -r1.21.2.1
--- lib/structure.c	16 Jul 2005 11:25:32 -0000	1.21
+++ lib/structure.c	11 Feb 2006 10:00:11 -0000	1.21.2.1
@@ -1,22 +1,23 @@
 /*
+ *      Copyright (C) 2004, 2006 Free Software Foundation
  *      Copyright (C) 2002  Fabio Fiorina
- *      Copyright (C) 2004  Simon Josefsson
  *
- * This file is part of LIBASN1.
+ * This file is part of LIBTASN1.
  *
- * The LIBTASN1 library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
+ * The LIBTASN1 library is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library 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
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
  */
 
 
@@ -362,7 +363,8 @@ _asn1_copy_structure3(node_asn *source_n
 	case TYPE_OCTET_STRING: case TYPE_BIT_STRING: case TYPE_GENERALSTRING:
 	case TYPE_INTEGER:
 	  len2=-1;
-	  len=_asn1_get_length_der(p_s->value,&len2);
+	  len=_asn1_get_length_der(p_s->value,p_s->value_len,&len2);
+	  if (len < 0) return NULL;
 	  _asn1_set_value(p_d,p_s->value,len+len2);
 	  break;
 	default:
@@ -726,17 +728,19 @@ asn1_print_structure(FILE *out,ASN1_TYPE
       case TYPE_INTEGER:
 	if(p->value){
 	  len2=-1;
-	  len=_asn1_get_length_der(p->value,&len2);
+	  len=_asn1_get_length_der(p->value,p->value_len,&len2);
 	  fprintf(out,"  value:0x");
-	  for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+	  if (len > 0)
+	    for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
 	}
 	break;
       case TYPE_ENUMERATED:
 	if(p->value){
 	  len2=-1;
-	  len=_asn1_get_length_der(p->value,&len2);
+	  len=_asn1_get_length_der(p->value,p->value_len,&len2);
 	  fprintf(out,"  value:0x");
-	  for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+	  if (len > 0)
+	    for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
 	}
 	break;
       case TYPE_TIME:
@@ -751,25 +755,30 @@ asn1_print_structure(FILE *out,ASN1_TYPE
       case TYPE_BIT_STRING:
 	if(p->value){
 	  len2=-1;
-	  len=_asn1_get_length_der(p->value,&len2);
-	  fprintf(out,"  value(%i):",(len-1)*8-(p->value[len2]));
-	  for(k=1;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+	  len=_asn1_get_length_der(p->value,p->value_len,&len2);
+	  if (len>0)
+	    {
+	      fprintf(out,"  value(%i):",(len-1)*8-(p->value[len2]));
+	      for(k=1;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+	    }
 	}
 	break;
       case TYPE_OCTET_STRING:
 	if(p->value){
 	  len2=-1;
-	  len=_asn1_get_length_der(p->value,&len2);
+	  len=_asn1_get_length_der(p->value,p->value_len,&len2);
 	  fprintf(out,"  value:");
-	  for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+	  if (len>0)
+	    for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
 	}
 	break;
       case TYPE_GENERALSTRING:
 	if(p->value){
 	  len2=-1;
-	  len=_asn1_get_length_der(p->value,&len2);
+	  len=_asn1_get_length_der(p->value,p->value_len,&len2);
 	  fprintf(out,"  value:");
-	  for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
+	  if (len>0)
+	    for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
 	}
 	break;
       case TYPE_OBJECT_ID:
@@ -778,9 +787,10 @@ asn1_print_structure(FILE *out,ASN1_TYPE
       case TYPE_ANY:
 	if(p->value){
 	  len3=-1;
-	  len2=_asn1_get_length_der(p->value,&len3);
+	  len2=_asn1_get_length_der(p->value,p->value_len,&len3);
 	  fprintf(out,"  value:");
-	  for(k=0;k<len2;k++) fprintf(out,"%02x",(p->value)[k+len3]);
+	  if (len2>0)
+	    for(k=0;k<len2;k++) fprintf(out,"%02x",(p->value)[k+len3]);
 	}
 	break;
       case TYPE_SET:




More information about the Gnutls-devel mailing list