From 2f481e1ba7edd27f6a8761891949dc7a0d4800bb Mon Sep 17 00:00:00 2001 From: Simon Josefsson Date: Wed, 8 Feb 2006 11:16:16 +0000 Subject: Add libtasn1 fixes from Nikos, prompted by report from "Evgeny Legerov" . --- lib/minitasn1/coding.c | 41 ++++---- lib/minitasn1/decoding.c | 237 +++++++++++++++++++++++++++------------------ lib/minitasn1/der.h | 14 +-- lib/minitasn1/element.c | 10 +- lib/minitasn1/libtasn1.h | 1 + lib/minitasn1/parser_aux.c | 2 + lib/minitasn1/structure.c | 14 +-- 7 files changed, 190 insertions(+), 129 deletions(-) diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c index 59ee0b248b..331a4af4d7 100644 --- a/lib/minitasn1/coding.c +++ b/lib/minitasn1/coding.c @@ -148,7 +148,7 @@ _asn1_octet_der(const unsigned char *str,int str_len,unsigned char *der,int *der { 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; @@ -534,7 +534,7 @@ _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter,int *max_len /* 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 +569,13 @@ _asn1_ordering_set(unsigned char *der,node_asn *node) 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); counter+=len+len2; p_vet->end=counter; @@ -626,7 +627,7 @@ _asn1_ordering_set(unsigned char *der,node_asn *node) /* 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 +662,15 @@ _asn1_ordering_set_of(unsigned char *der,node_asn *node) 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); + counter+=len+len2; + } p_vet->end=counter; p=p->right; @@ -804,7 +810,7 @@ asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len, _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); max_len -= len2+len3; if(max_len>=0) memcpy(der+counter,p->value,len3+len2); @@ -846,7 +852,7 @@ asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len, _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); max_len-=len2+len3; if(max_len>=0) memcpy(der+counter,p->value,len3+len2); @@ -858,7 +864,7 @@ asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len, _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); max_len-=len2+len3; if(max_len>=0) memcpy(der+counter,p->value,len3+len2); @@ -870,7 +876,7 @@ asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len, _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); max_len-=len2+len3; if(max_len>=0) memcpy(der+counter,p->value,len3+len2); @@ -903,7 +909,7 @@ asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len, 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 +940,9 @@ asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len, if(move==UP){ len2=strtol(p->value,NULL,10); _asn1_set_value(p,NULL,0); - if((type_field(p->type)==TYPE_SET_OF) && (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 +958,7 @@ asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len, _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); max_len-=len2; if(max_len>=0) memcpy(der+counter,p->value+len3,len2); diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c index 8eafb1d81e..9fe36ea519 100644 --- a/lib/minitasn1/decoding.c +++ b/lib/minitasn1/decoding.c @@ -47,11 +47,14 @@ _asn1_error_description_tag_error(node_asn *node,char *ErrorDescription) 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 +66,9 @@ _asn1_get_length_der(const unsigned char *der,int *len) punt=1; if(k){ /* definite length method */ ans=0; - while(punt<=k) ans=ans*256+der[punt++]; + while(punt<=k && punt < der_len) { + ans=ans*256+der[punt++]; + } } else{ /* indefinite length method */ ans=-1; @@ -77,12 +82,14 @@ _asn1_get_length_der(const unsigned char *der,int *len) -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 +100,33 @@ _asn1_get_tag_der(const unsigned char *der,unsigned char *class,int *len) /* Long form */ punt=1; ris=0; - while(der[punt]&128) ris=ris*128+(der[punt++]&0x7F); + while(punt <= der_len && der[punt]&128) ris=ris*128+(der[punt++]&0x7F); + if (punt >= der_len) + return ASN1_DER_ERROR; ris=ris*128+(der[punt++]&0x7F); *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 +141,17 @@ _asn1_get_octet_der(const unsigned char *der,int *der_len,unsigned char *str,int /* 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 +159,19 @@ _asn1_get_time_der(const unsigned char *der,int *der_len,unsigned char *str,int 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_len > der_len) return; val1=der[len_len]/40; val=der[len_len]-val1*40; @@ -170,20 +190,22 @@ _asn1_get_objectid_der(const unsigned char *der,int *der_len,unsigned char *str, 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; - *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 +221,15 @@ _asn1_get_bit_der(const unsigned char *der,int *der_len,unsigned char *str, int 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 +242,10 @@ _asn1_extract_tag_der(node_asn *node,const unsigned char *der,int *der_len) 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; counter+=len2; - len3=_asn1_get_length_der(der+counter,&len2); + len3=_asn1_get_length_der(der+counter,der_len-counter, &len2); counter+=len2; if(!is_tag_implicit){ if((class!=(class2|STRUCTURED)) || (tag!=strtoul(p->value,NULL,10))) @@ -251,7 +275,9 @@ _asn1_extract_tag_der(node_asn *node,const unsigned char *der,int *der_len) } 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((class!=class_implicit) || (tag!=tag_implicit)){ if(type_field(node->type)==TYPE_OCTET_STRING){ class_implicit |= STRUCTURED; @@ -265,11 +291,13 @@ _asn1_extract_tag_der(node_asn *node,const unsigned char *der,int *der_len) 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; + switch(type_field(node->type)){ case TYPE_NULL: if((class!=UNIVERSAL) || (tag!=TAG_NULL)) return ASN1_DER_ERROR; @@ -323,7 +351,7 @@ _asn1_extract_tag_der(node_asn *node,const unsigned char *der,int *der_len) } counter+=len2; - *der_len=counter; + *ret_len=counter; return ASN1_SUCCESS; } @@ -375,7 +403,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 +412,7 @@ _asn1_get_octet_string(const unsigned char* der,node_asn *node,int* len) if(*(der-1) & STRUCTURED){ tot_len=0; - indefinite=_asn1_get_length_der(der,&len3); + indefinite=_asn1_get_length_der(der, *len, &len3); counter+=len3; if(indefinite>=0) indefinite+=len3; @@ -404,7 +432,7 @@ _asn1_get_octet_string(const unsigned char* der,node_asn *node,int* len) 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 +450,30 @@ _asn1_get_octet_string(const unsigned char* der,node_asn *node,int* len) _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); counter2=len3+1; if(indefinite==-1) counter_end=counter-2; else counter_end=counter; while(counter2 *len) return ASN1_DER_ERROR; if(node) _asn1_set_value(node,der,len3+len2); counter=len3+len2; @@ -452,10 +486,10 @@ _asn1_get_octet_string(const unsigned char* der,node_asn *node,int* len) 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 +504,11 @@ _asn1_get_indefinite_length_string(const unsigned char* der,int* len) 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; + counter+=len2; - len2=_asn1_get_length_der(der+counter,&len3); + len2=_asn1_get_length_der(der+counter, *len-counter,&len3); if(len2 == -1){ indefinite++; counter+=1; @@ -520,7 +556,7 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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 +599,11 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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 +642,7 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, if(type_field(p->type)==TYPE_CHOICE){ while(p->down){ if(counterdown,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 +678,7 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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 +719,15 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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+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 +735,7 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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 +754,16 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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 (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 (len3+len2 > len-counter) return ASN1_DER_ERROR; + _asn1_set_value(p,der+counter,len3+len2); counter+=len3+len2; move=RIGHT; break; @@ -732,10 +772,12 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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 +789,7 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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); counter+=len2; if(len3>0){ _asn1_ltostr(counter+len3,temp); @@ -806,7 +848,7 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, } } else{ /* move==DOWN || move==RIGHT */ - len3=_asn1_get_length_der(der+counter,&len2); + len3=_asn1_get_length_der(der+counter,len-counter,&len2); counter+=len2; if(len3){ if(len3>0){ /* definite length method */ @@ -828,8 +870,10 @@ asn1_der_decoding(ASN1_TYPE *element,const void *ider,int len, 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; + + len4=_asn1_get_length_der(der+counter+len2,len-counter-len2,&len3); if(len4 != -1){ len2+=len4; @@ -955,7 +999,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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 +1068,11 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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 +1111,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, if(type_field(p->type)==TYPE_CHOICE){ while(p->down){ if(counterdown,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 +1147,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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 +1200,9 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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(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 +1212,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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 +1221,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, if(p==nodeFound) state=EXIT; } else{ - len2=_asn1_get_length_der(der+counter,&len3); + len2=_asn1_get_length_der(der+counter,len-counter,&len3); len2+=len3; } @@ -1185,7 +1230,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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 +1243,7 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, if(p==nodeFound) state=EXIT; } else{ - len2=_asn1_get_length_der(der+counter,&len3); + len2=_asn1_get_length_der(der+counter,len-counter,&len3); len2+=len3; } @@ -1219,8 +1264,9 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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(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 +1275,9 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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(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 +1307,12 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, } 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); 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); counter+=len2; if(len3>0){ _asn1_ltostr(counter+len3,temp); @@ -1315,12 +1362,12 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, } 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); 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); counter+=len2; if(len3){ _asn1_ltostr(counter+len3,temp); @@ -1339,8 +1386,10 @@ asn1_der_decoding_element(ASN1_TYPE *structure,const char *elementName, 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; + + len4=_asn1_get_length_der(der+counter+len2,len-counter-len2,&len3); if(len4 != -1){ len2+=len4; @@ -1549,7 +1598,7 @@ asn1_der_decoding_startEnd(ASN1_TYPE element,const void *ider,int len, 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 +1646,10 @@ asn1_der_decoding_startEnd(ASN1_TYPE element,const void *ider,int len, 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 +1666,11 @@ asn1_der_decoding_startEnd(ASN1_TYPE element,const void *ider,int len, 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 +1699,17 @@ asn1_der_decoding_startEnd(ASN1_TYPE element,const void *ider,int len, 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); 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); 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); counter+=len2+len3; move=RIGHT; break; @@ -1672,18 +1721,18 @@ asn1_der_decoding_startEnd(ASN1_TYPE element,const void *ider,int len, move=RIGHT; break; case TYPE_GENERALSTRING: - len2=_asn1_get_length_der(der+counter,&len3); + len2=_asn1_get_length_der(der+counter,len-counter,&len3); 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); 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); counter+=len2; if(len3==0) move=RIGHT; else move=DOWN; @@ -1696,7 +1745,7 @@ asn1_der_decoding_startEnd(ASN1_TYPE element,const void *ider,int len, 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); counter+=len2; if((len3==-1) && !der[counter] && !der[counter+1]) counter+=2; @@ -1714,8 +1763,10 @@ asn1_der_decoding_startEnd(ASN1_TYPE element,const void *ider,int len, 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; + + len4=_asn1_get_length_der(der+counter+len2,len-counter-len2,&len3); if(len4 != -1){ counter+=len2+len4+len3; @@ -1887,7 +1938,7 @@ asn1_expand_any_defined_by(ASN1_TYPE definitions,ASN1_TYPE *element) 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); result=asn1_der_decoding(&aux,p->value+len3,len2, errorDescription); @@ -2051,7 +2102,7 @@ asn1_expand_octet_string(ASN1_TYPE definitions,ASN1_TYPE *element, 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); result=asn1_der_decoding(&aux,octetNode->value+len3,len2, errorDescription); diff --git a/lib/minitasn1/der.h b/lib/minitasn1/der.h index 3af8cc79bb..543e70ce23 100644 --- a/lib/minitasn1/der.h +++ b/lib/minitasn1/der.h @@ -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); diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c index 4357634678..35ae24fd99 100644 --- a/lib/minitasn1/element.c +++ b/lib/minitasn1/element.c @@ -677,7 +677,7 @@ asn1_read_value(ASN1_TYPE root,const char *name,void* ivalue, int *len) } 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 +709,22 @@ asn1_read_value(ASN1_TYPE root,const char *name,void* ivalue, int *len) 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); PUT_VALUE( value, value_size, node->value+len3, len2); break; default: diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h index d56e5882d3..c57535017d 100644 --- a/lib/minitasn1/libtasn1.h +++ b/lib/minitasn1/libtasn1.h @@ -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 */ diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c index b86d9ff65e..d765cf580f 100644 --- a/lib/minitasn1/parser_aux.c +++ b/lib/minitasn1/parser_aux.c @@ -187,10 +187,12 @@ _asn1_set_value(node_asn *node,const unsigned char *value,unsigned int len) 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; diff --git a/lib/minitasn1/structure.c b/lib/minitasn1/structure.c index dd138cba50..4ed0f0bf66 100644 --- a/lib/minitasn1/structure.c +++ b/lib/minitasn1/structure.c @@ -362,7 +362,7 @@ _asn1_copy_structure3(node_asn *source_node) 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); _asn1_set_value(p_d,p_s->value,len+len2); break; default: @@ -726,7 +726,7 @@ asn1_print_structure(FILE *out,ASN1_TYPE structure,const char *name,int mode) 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;kvalue)[k+len2]); } @@ -734,7 +734,7 @@ asn1_print_structure(FILE *out,ASN1_TYPE structure,const char *name,int mode) 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;kvalue)[k+len2]); } @@ -751,7 +751,7 @@ asn1_print_structure(FILE *out,ASN1_TYPE structure,const char *name,int mode) case TYPE_BIT_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(%i):",(len-1)*8-(p->value[len2])); for(k=1;kvalue)[k+len2]); } @@ -759,7 +759,7 @@ asn1_print_structure(FILE *out,ASN1_TYPE structure,const char *name,int mode) 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;kvalue)[k+len2]); } @@ -767,7 +767,7 @@ asn1_print_structure(FILE *out,ASN1_TYPE structure,const char *name,int mode) 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;kvalue)[k+len2]); } @@ -778,7 +778,7 @@ asn1_print_structure(FILE *out,ASN1_TYPE structure,const char *name,int mode) 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;kvalue)[k+len3]); } -- cgit v1.2.1