----- Forwarded message from Simon Josefsson <[EMAIL PROTECTED]> ----- From: Simon Josefsson <[EMAIL PROTECTED]> To: [EMAIL PROTECTED], help-gnutls@gnu.org Date: Sat, 11 Feb 2006 11:19:56 +0100 Message-ID: <[EMAIL PROTECTED]> Cc: Matthias Urlichs <[EMAIL PROTECTED]>, Martin Schulze <[EMAIL PROTECTED]> X-Spam-Report: (-2.6 / 8.0 requ) AWL=0.000,BAYES_00=-2.599 autolearn=ham
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: _______________________________________________ Gnutls-dev mailing list [EMAIL PROTECTED] http://lists.gnupg.org/mailman/listinfo/gnutls-dev ----- End forwarded message ----- -- The 'Galactic Cleaning' policy undertaken by Emperor Zhark is a personal vision of the emperor's, and its inclusion in this work does not constitute tacit approval by the author or the publisher for any such projects, howsoever undertaken. (c) Jasper Ffforde -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]