[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-dev
mailing list