2 * Copyright (C) 2002 Fabio Fiorina
4 * This file is part of LIBASN1.
6 * The LIBTASN1 library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /*****************************************************/
24 /* Description: Functions to create a DER coding of */
26 /*****************************************************/
31 #include "parser_aux.h"
35 #define MAX_TAG_LEN 16
37 /******************************************************/
38 /* Function : _asn1_error_description_value_not_found */
39 /* Description: creates the ErrorDescription string */
40 /* for the ASN1_VALUE_NOT_FOUND error. */
42 /* node: node of the tree where the value is NULL. */
43 /* ErrorDescription: string returned. */
45 /******************************************************/
47 _asn1_error_description_value_not_found(node_asn
*node
,char *ErrorDescription
)
50 if (ErrorDescription
== NULL
) return;
52 Estrcpy(ErrorDescription
,":: value of element '");
53 _asn1_hierarchical_name(node
,ErrorDescription
+strlen(ErrorDescription
),
54 MAX_ERROR_DESCRIPTION_SIZE
-40);
55 Estrcat(ErrorDescription
,"' not found");
59 /******************************************************/
60 /* Function : _asn1_length_der */
61 /* Description: creates the DER coding for the LEN */
62 /* parameter (only the length). */
64 /* len: value to convert. */
65 /* ans: string returned. */
66 /* ans_len: number of meaningful bytes of ANS */
67 /* (ans[0]..ans[ans_len-1]). */
69 /******************************************************/
71 _asn1_length_der(unsigned long len
,unsigned char *ans
,int *ans_len
)
74 unsigned char temp
[SIZEOF_UNSIGNED_LONG_INT
];
78 if(ans
!=NULL
) ans
[0]=(unsigned char)len
;
90 ans
[0]=((unsigned char)k
&0x7F)+128;
91 while(k
--) ans
[*ans_len
-1-k
]=temp
[k
];
96 /******************************************************/
97 /* Function : _asn1_tag_der */
98 /* Description: creates the DER coding for the CLASS */
99 /* and TAG parameters. */
101 /* class: value to convert. */
102 /* tag_value: value to convert. */
103 /* ans: string returned. */
104 /* ans_len: number of meaningful bytes of ANS */
105 /* (ans[0]..ans[ans_len-1]). */
107 /******************************************************/
109 _asn1_tag_der(unsigned char class,unsigned int tag_value
,unsigned char *ans
,int *ans_len
)
112 unsigned char temp
[SIZEOF_UNSIGNED_INT
];
116 ans
[0]=(class&0xE0) + ((unsigned char)(tag_value
&0x1F));
121 ans
[0]=(class&0xE0) + 31;
124 temp
[k
++]=tag_value
&0x7F;
125 tag_value
=tag_value
>>7;
128 while(k
--) ans
[*ans_len
-1-k
]=temp
[k
]+128;
129 ans
[*ans_len
-1]-=128;
133 /******************************************************/
134 /* Function : _asn1_octect_der */
135 /* Description: creates the DER coding for an */
136 /* OCTET type (length included). */
138 /* str: OCTET string. */
139 /* str_len: STR length (str[0]..str[str_len-1]). */
140 /* der: string returned. */
141 /* der_len: number of meaningful bytes of DER */
142 /* (der[0]..der[ans_len-1]). */
144 /******************************************************/
146 _asn1_octet_der(const unsigned char *str
,int str_len
,unsigned char *der
,int *der_len
)
150 if(der
==NULL
) return;
151 _asn1_length_der(str_len
,der
,&len_len
);
152 memcpy(der
+len_len
,str
,str_len
);
153 *der_len
=str_len
+len_len
;
156 /******************************************************/
157 /* Function : _asn1_time_der */
158 /* Description: creates the DER coding for a TIME */
159 /* type (length included). */
161 /* str: TIME null-terminated string. */
162 /* der: string returned. */
163 /* der_len: number of meaningful bytes of DER */
164 /* (der[0]..der[ans_len-1]). Initially it */
165 /* if must store the lenght of DER. */
167 /* ASN1_MEM_ERROR when DER isn't big enough */
168 /* ASN1_SUCCESS otherwise */
169 /******************************************************/
171 _asn1_time_der(unsigned char *str
,unsigned char *der
,int *der_len
)
178 _asn1_length_der(strlen(str
),(max_len
>0)?der
:NULL
,&len_len
);
180 if((len_len
+(int)strlen(str
))<=max_len
)
181 memcpy(der
+len_len
,str
,strlen(str
));
182 *der_len
=len_len
+strlen(str
);
184 if((*der_len
)>max_len
) return ASN1_MEM_ERROR
;
192 _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
197 if(str==NULL) return;
198 str_len=_asn1_get_length_der(der,&len_len);
199 memcpy(temp,der+len_len,str_len);
200 *der_len=str_len+len_len;
204 strcat(temp,"00+0000");
208 strcat(temp,"+0000");
212 memmove(temp+12,temp+10,6);
213 temp[10]=temp[11]='0';
225 /******************************************************/
226 /* Function : _asn1_objectid_der */
227 /* Description: creates the DER coding for an */
228 /* OBJECT IDENTIFIER type (length included). */
230 /* str: OBJECT IDENTIFIER null-terminated string. */
231 /* der: string returned. */
232 /* der_len: number of meaningful bytes of DER */
233 /* (der[0]..der[ans_len-1]). Initially it */
234 /* must store the length of DER. */
236 /* ASN1_MEM_ERROR when DER isn't big enough */
237 /* ASN1_SUCCESS otherwise */
238 /******************************************************/
240 _asn1_objectid_der(unsigned char *str
,unsigned char *der
,int *der_len
)
242 int len_len
,counter
,k
,first
,max_len
;
243 char *temp
,*n_end
,*n_start
;
245 unsigned long val
,val1
=0;
249 temp
= (char *) _asn1_alloca(strlen(str
)+2);
250 if(temp
==NULL
) return ASN1_MEM_ALLOC_ERROR
;
257 while((n_end
=strchr(n_start
,'.'))){
259 val
=strtoul(n_start
,NULL
,10);
262 if(counter
==1) val1
=val
;
271 bit7
=(val
>>(k
*7))&0x7F;
272 if(bit7
|| first
|| !k
){
274 if(max_len
>(*der_len
))
285 _asn1_length_der(*der_len
,NULL
,&len_len
);
286 if(max_len
>=(*der_len
+len_len
)){
287 memmove(der
+len_len
,der
,*der_len
);
288 _asn1_length_der(*der_len
,der
,&len_len
);
294 if(max_len
<(*der_len
)) return ASN1_MEM_ERROR
;
300 char bit_mask
[]={0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
302 /******************************************************/
303 /* Function : _asn1_bit_der */
304 /* Description: creates the DER coding for a BIT */
305 /* STRING type (length and pad included). */
307 /* str: BIT string. */
308 /* bit_len: number of meaningful bits in STR. */
309 /* der: string returned. */
310 /* der_len: number of meaningful bytes of DER */
311 /* (der[0]..der[ans_len-1]). */
313 /******************************************************/
315 _asn1_bit_der(const unsigned char *str
,int bit_len
,unsigned char *der
,int *der_len
)
317 int len_len
,len_byte
,len_pad
;
319 if(der
==NULL
) return;
321 len_pad
=8-(bit_len
&7);
322 if(len_pad
==8) len_pad
=0;
324 _asn1_length_der(len_byte
+1,der
,&len_len
);
325 der
[len_len
]=len_pad
;
326 memcpy(der
+len_len
+1,str
,len_byte
);
327 der
[len_len
+len_byte
]&=bit_mask
[len_pad
];
328 *der_len
=len_byte
+len_len
+1;
332 /******************************************************/
333 /* Function : _asn1_complete_explicit_tag */
334 /* Description: add the length coding to the EXPLICIT */
337 /* node: pointer to the tree element. */
338 /* der: string with the DER coding of the whole tree*/
339 /* counter: number of meaningful bytes of DER */
340 /* (der[0]..der[*counter-1]). */
341 /* max_len: size of der vector */
343 /* ASN1_MEM_ERROR if der vector isn't big enough, */
344 /* otherwise ASN1_SUCCESS. */
345 /******************************************************/
347 _asn1_complete_explicit_tag(node_asn
*node
,unsigned char *der
,int *counter
,int *max_len
)
350 int is_tag_implicit
,len2
,len3
;
351 unsigned char temp
[SIZEOF_UNSIGNED_INT
];
355 if(node
->type
&CONST_TAG
){
357 /* When there are nested tags we must complete them reverse to
358 the order they were created. This is because completing a tag
359 modifies all data within it, including the incomplete tags
360 which store buffer positions -- simon@josefsson.org 2002-09-06
364 while(p
&& p
!=node
->down
->left
){
365 if(type_field(p
->type
)==TYPE_TAG
){
366 if(p
->type
&CONST_EXPLICIT
){
367 len2
=strtol(p
->name
,NULL
,10);
368 _asn1_set_name(p
,NULL
);
369 _asn1_length_der(*counter
-len2
,temp
,&len3
);
370 if(len3
<=(*max_len
)){
371 memmove(der
+len2
+len3
,der
+len2
,*counter
-len2
);
372 memcpy(der
+len2
,temp
,len3
);
378 else{ /* CONST_IMPLICIT */
379 if(!is_tag_implicit
){
388 if(*max_len
<0) return ASN1_MEM_ERROR
;
394 /******************************************************/
395 /* Function : _asn1_insert_tag_der */
396 /* Description: creates the DER coding of tags of one */
399 /* node: pointer to the tree element. */
400 /* der: string returned */
401 /* counter: number of meaningful bytes of DER */
402 /* (counter[0]..der[*counter-1]). */
403 /* max_len: size of der vector */
405 /* ASN1_GENERIC_ERROR if the type is unknown, */
406 /* ASN1_MEM_ERROR if der vector isn't big enough, */
407 /* otherwise ASN1_SUCCESS. */
408 /******************************************************/
410 _asn1_insert_tag_der(node_asn
*node
,unsigned char *der
,int *counter
,int *max_len
)
413 int tag_len
,is_tag_implicit
;
414 unsigned char class,class_implicit
=0,temp
[SIZEOF_UNSIGNED_INT
*3+1];
415 unsigned long tag_implicit
=0;
416 char tag_der
[MAX_TAG_LEN
];
420 if(node
->type
&CONST_TAG
){
423 if(type_field(p
->type
)==TYPE_TAG
){
424 if(p
->type
&CONST_APPLICATION
) class=APPLICATION
;
425 else if(p
->type
&CONST_UNIVERSAL
) class=UNIVERSAL
;
426 else if(p
->type
&CONST_PRIVATE
) class=PRIVATE
;
427 else class=CONTEXT_SPECIFIC
;
429 if(p
->type
&CONST_EXPLICIT
){
431 _asn1_tag_der(class_implicit
,tag_implicit
,tag_der
,&tag_len
);
433 _asn1_tag_der(class|STRUCTURED
,strtoul(p
->value
,NULL
,10),tag_der
,&tag_len
);
437 memcpy(der
+*counter
,tag_der
,tag_len
);
440 _asn1_ltostr(*counter
,temp
);
441 _asn1_set_name(p
,temp
);
445 else{ /* CONST_IMPLICIT */
446 if(!is_tag_implicit
){
447 if((type_field(node
->type
)==TYPE_SEQUENCE
) ||
448 (type_field(node
->type
)==TYPE_SEQUENCE_OF
) ||
449 (type_field(node
->type
)==TYPE_SET
) ||
450 (type_field(node
->type
)==TYPE_SET_OF
)) class|=STRUCTURED
;
451 class_implicit
=class;
452 tag_implicit
=strtoul(p
->value
,NULL
,10);
462 _asn1_tag_der(class_implicit
,tag_implicit
,tag_der
,&tag_len
);
465 switch(type_field(node
->type
)){
467 _asn1_tag_der(UNIVERSAL
,TAG_NULL
,tag_der
,&tag_len
);
470 _asn1_tag_der(UNIVERSAL
,TAG_BOOLEAN
,tag_der
,&tag_len
);
473 _asn1_tag_der(UNIVERSAL
,TAG_INTEGER
,tag_der
,&tag_len
);
475 case TYPE_ENUMERATED
:
476 _asn1_tag_der(UNIVERSAL
,TAG_ENUMERATED
,tag_der
,&tag_len
);
479 _asn1_tag_der(UNIVERSAL
,TAG_OBJECT_ID
,tag_der
,&tag_len
);
482 if(node
->type
&CONST_UTC
){
483 _asn1_tag_der(UNIVERSAL
,TAG_UTCTime
,tag_der
,&tag_len
);
485 else _asn1_tag_der(UNIVERSAL
,TAG_GENERALIZEDTime
,tag_der
,&tag_len
);
487 case TYPE_OCTET_STRING
:
488 _asn1_tag_der(UNIVERSAL
,TAG_OCTET_STRING
,tag_der
,&tag_len
);
490 case TYPE_GENERALSTRING
:
491 _asn1_tag_der(UNIVERSAL
,TAG_GENERALSTRING
,tag_der
,&tag_len
);
493 case TYPE_BIT_STRING
:
494 _asn1_tag_der(UNIVERSAL
,TAG_BIT_STRING
,tag_der
,&tag_len
);
496 case TYPE_SEQUENCE
: case TYPE_SEQUENCE_OF
:
497 _asn1_tag_der(UNIVERSAL
|STRUCTURED
,TAG_SEQUENCE
,tag_der
,&tag_len
);
499 case TYPE_SET
: case TYPE_SET_OF
:
500 _asn1_tag_der(UNIVERSAL
|STRUCTURED
,TAG_SET
,tag_der
,&tag_len
);
512 return ASN1_GENERIC_ERROR
;
518 memcpy(der
+*counter
,tag_der
,tag_len
);
521 if(*max_len
<0) return ASN1_MEM_ERROR
;
526 /******************************************************/
527 /* Function : _asn1_ordering_set */
528 /* Description: puts the elements of a SET type in */
529 /* the correct order according to DER rules. */
531 /* der: string with the DER coding. */
532 /* node: pointer to the SET element. */
534 /******************************************************/
536 _asn1_ordering_set(unsigned char *der
,node_asn
*node
)
541 struct vet
*next
,*prev
;
544 int counter
,len
,len2
;
545 struct vet
*first
,*last
,*p_vet
,*p2_vet
;
547 unsigned char class,*temp
;
552 if(type_field(node
->type
)!=TYPE_SET
) return;
555 while((type_field(p
->type
)==TYPE_TAG
) || (type_field(p
->type
)==TYPE_SIZE
)) p
=p
->right
;
557 if((p
==NULL
) || (p
->right
==NULL
)) return;
561 p_vet
=(struct vet
*)_asn1_alloca( sizeof(struct vet
));
562 if (p_vet
==NULL
) return;
566 if(first
==NULL
) first
=p_vet
;
567 else last
->next
=p_vet
;
570 /* tag value calculation */
571 tag
=_asn1_get_tag_der(der
+counter
,&class,&len2
);
572 p_vet
->value
=(class<<24)|tag
;
575 /* extraction and length */
576 len2
=_asn1_get_length_der(der
+counter
,&len
);
589 if(p_vet
->value
>p2_vet
->value
){
590 /* change position */
591 temp
=(unsigned char *)_asn1_alloca( p_vet
->end
-counter
);
592 if (temp
==NULL
) return;
594 memcpy(temp
,der
+counter
,p_vet
->end
-counter
);
595 memcpy(der
+counter
,der
+p_vet
->end
,p2_vet
->end
-p_vet
->end
);
596 memcpy(der
+counter
+p2_vet
->end
-p_vet
->end
,temp
,p_vet
->end
-counter
);
600 p_vet
->value
=p2_vet
->value
;
603 p_vet
->end
=counter
+(p2_vet
->end
-p_vet
->end
);
611 if(p_vet
!=first
) p_vet
->prev
->next
=NULL
;
618 /******************************************************/
619 /* Function : _asn1_ordering_set_of */
620 /* Description: puts the elements of a SET OF type in */
621 /* the correct order according to DER rules. */
623 /* der: string with the DER coding. */
624 /* node: pointer to the SET OF element. */
626 /******************************************************/
628 _asn1_ordering_set_of(unsigned char *der
,node_asn
*node
)
632 struct vet
*next
,*prev
;
635 int counter
,len
,len2
,change
;
636 struct vet
*first
,*last
,*p_vet
,*p2_vet
;
638 unsigned char *temp
,class;
643 if(type_field(node
->type
)!=TYPE_SET_OF
) return;
646 while((type_field(p
->type
)==TYPE_TAG
) || (type_field(p
->type
)==TYPE_SIZE
)) p
=p
->right
;
649 if((p
==NULL
) || (p
->right
==NULL
)) return;
653 p_vet
=(struct vet
*)_asn1_alloca(sizeof(struct vet
));
654 if (p_vet
==NULL
) return;
658 if(first
==NULL
) first
=p_vet
;
659 else last
->next
=p_vet
;
662 /* extraction of tag and length */
663 _asn1_get_tag_der(der
+counter
,&class,&len
);
665 len2
=_asn1_get_length_der(der
+counter
,&len
);
678 if((p_vet
->end
-counter
)>(p2_vet
->end
-p_vet
->end
))
679 max
=p_vet
->end
-counter
;
681 max
=p2_vet
->end
-p_vet
->end
;
685 if(der
[counter
+k
]>der
[p_vet
->end
+k
]){change
=1;break;}
686 else if(der
[counter
+k
]<der
[p_vet
->end
+k
]){change
=0;break;}
688 if((change
==-1) && ((p_vet
->end
-counter
)>(p2_vet
->end
-p_vet
->end
)))
692 /* change position */
693 temp
=(unsigned char *)_asn1_alloca(p_vet
->end
-counter
);
694 if (temp
==NULL
) return;
696 memcpy(temp
,der
+counter
,(p_vet
->end
)-counter
);
697 memcpy(der
+counter
,der
+(p_vet
->end
),(p2_vet
->end
)-(p_vet
->end
));
698 memcpy(der
+counter
+(p2_vet
->end
)-(p_vet
->end
),temp
,(p_vet
->end
)-counter
);
701 p_vet
->end
=counter
+(p2_vet
->end
-p_vet
->end
);
709 if(p_vet
!=first
) p_vet
->prev
->next
=NULL
;
717 * asn1_der_coding - Creates the DER encoding for the NAME structure
718 * @element: pointer to an ASN1 element
719 * @name: the name of the structure you want to encode (it must be inside *POINTER).
720 * @ider: vector that will contain the DER encoding. DER must be a pointer to memory cells already allocated.
721 * @len: number of bytes of *der: der[0]..der[len-1], Initialy holds the sizeof of der vector.
722 * @errorDescription : return the error description or an empty string if success.
725 * Creates the DER encoding for the NAME structure (inside *POINTER structure).
729 * ASN1_SUCCESS\: DER encoding OK
731 * ASN1_ELEMENT_NOT_FOUND\: NAME is not a valid element.
733 * ASN1_VALUE_NOT_FOUND\: there is an element without a value.
735 * ASN1_MEM_ERROR\: der vector isn't big enough. Also in this case LEN
736 * will contain the length needed.
740 asn1_der_coding(ASN1_TYPE element
,const char *name
,void *ider
,int *len
,
741 char *ErrorDescription
)
743 node_asn
*node
,*p
,*p2
;
744 char temp
[SIZEOF_UNSIGNED_LONG_INT
*3+1];
745 int counter
,counter_old
,len2
,len3
,tlen
,move
,max_len
,max_len_old
;
747 unsigned char* der
= ider
;
749 node
=_asn1_find_node(element
,name
);
750 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
762 ris
=_asn1_insert_tag_der(p
,der
,&counter
,&max_len
);
764 switch(type_field(p
->type
)){
772 if((p
->type
&CONST_DEFAULT
) && (p
->value
==NULL
)){
778 _asn1_error_description_value_not_found(p
,ErrorDescription
);
779 return ASN1_VALUE_NOT_FOUND
;
784 if(p
->value
[0]=='F') der
[counter
++]=0;
785 else der
[counter
++]=0xFF;
792 case TYPE_INTEGER
: case TYPE_ENUMERATED
:
793 if((p
->type
&CONST_DEFAULT
) && (p
->value
==NULL
)){
799 _asn1_error_description_value_not_found(p
,ErrorDescription
);
800 return ASN1_VALUE_NOT_FOUND
;
802 len2
=_asn1_get_length_der(p
->value
,&len3
);
803 max_len
-= len2
+len3
;
805 memcpy(der
+counter
,p
->value
,len3
+len2
);
811 if((p
->type
&CONST_DEFAULT
) && (p
->value
==NULL
)){
817 _asn1_error_description_value_not_found(p
,ErrorDescription
);
818 return ASN1_VALUE_NOT_FOUND
;
821 ris
=_asn1_objectid_der(p
->value
,der
+counter
,&len2
);
822 if(ris
==ASN1_MEM_ALLOC_ERROR
) return ris
;
830 _asn1_error_description_value_not_found(p
,ErrorDescription
);
831 return ASN1_VALUE_NOT_FOUND
;
834 ris
=_asn1_time_der(p
->value
,der
+counter
,&len2
);
839 case TYPE_OCTET_STRING
:
841 _asn1_error_description_value_not_found(p
,ErrorDescription
);
842 return ASN1_VALUE_NOT_FOUND
;
844 len2
=_asn1_get_length_der(p
->value
,&len3
);
847 memcpy(der
+counter
,p
->value
,len3
+len2
);
851 case TYPE_GENERALSTRING
:
853 _asn1_error_description_value_not_found(p
,ErrorDescription
);
854 return ASN1_VALUE_NOT_FOUND
;
856 len2
=_asn1_get_length_der(p
->value
,&len3
);
859 memcpy(der
+counter
,p
->value
,len3
+len2
);
863 case TYPE_BIT_STRING
:
865 _asn1_error_description_value_not_found(p
,ErrorDescription
);
866 return ASN1_VALUE_NOT_FOUND
;
868 len2
=_asn1_get_length_der(p
->value
,&len3
);
871 memcpy(der
+counter
,p
->value
,len3
+len2
);
875 case TYPE_SEQUENCE
: case TYPE_SET
:
877 _asn1_ltostr(counter
,temp
);
880 _asn1_set_value(p
,temp
,tlen
+1);
887 while(p2
&& (type_field(p2
->type
)==TYPE_TAG
)) p2
=p2
->right
;
898 len2
=strtol(p
->value
,NULL
,10);
899 _asn1_set_value(p
,NULL
,0);
900 if((type_field(p
->type
)==TYPE_SET
) && (max_len
>=0))
901 _asn1_ordering_set(der
+len2
,p
);
902 _asn1_length_der(counter
-len2
,temp
,&len3
);
905 memmove(der
+len2
+len3
,der
+len2
,counter
-len2
);
906 memcpy(der
+len2
,temp
,len3
);
912 case TYPE_SEQUENCE_OF
: case TYPE_SET_OF
:
914 _asn1_ltostr(counter
,temp
);
918 _asn1_set_value(p
,temp
,tlen
+1);
920 while((type_field(p
->type
)==TYPE_TAG
) || (type_field(p
->type
)==TYPE_SIZE
)) p
=p
->right
;
926 else p
=_asn1_find_up(p
);
930 len2
=strtol(p
->value
,NULL
,10);
931 _asn1_set_value(p
,NULL
,0);
932 if((type_field(p
->type
)==TYPE_SET_OF
) && (max_len
>=0))
933 _asn1_ordering_set_of(der
+len2
,p
);
934 _asn1_length_der(counter
-len2
,temp
,&len3
);
937 memmove(der
+len2
+len3
,der
+len2
,counter
-len2
);
938 memcpy(der
+len2
,temp
,len3
);
946 _asn1_error_description_value_not_found(p
,ErrorDescription
);
947 return ASN1_VALUE_NOT_FOUND
;
949 len2
=_asn1_get_length_der(p
->value
,&len3
);
952 memcpy(der
+counter
,p
->value
+len3
,len2
);
957 move
=(move
==UP
)?RIGHT
:DOWN
;
961 if((move
!=DOWN
) && (counter
!=counter_old
)){
962 ris
=_asn1_complete_explicit_tag(p
,der
,&counter
,&max_len
);
965 if(p
==node
&& move
!=DOWN
) break;
968 if(p
->down
) p
=p
->down
;
972 if(p
->right
) p
=p
->right
;
975 if(move
==UP
) p
=_asn1_find_up(p
);
980 if(max_len
<0) return ASN1_MEM_ERROR
;