Fix.
[libtasn1.git] / lib / coding.c
blob59ee0b248bc6b48690b94f83b10727c241633876
1 /*
2 * Copyright (C) 2002 Fabio Fiorina
3 * Copyright (C) 2004 Simon Josefsson
5 * This file is part of LIBASN1.
7 * The LIBTASN1 library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 /*****************************************************/
24 /* File: coding.c */
25 /* Description: Functions to create a DER coding of */
26 /* an ASN1 type. */
27 /*****************************************************/
29 #include <int.h>
30 #include <errors.h>
31 #include "der.h"
32 #include "parser_aux.h"
33 #include <gstr.h>
34 #include "element.h"
36 #define MAX_TAG_LEN 16
38 /******************************************************/
39 /* Function : _asn1_error_description_value_not_found */
40 /* Description: creates the ErrorDescription string */
41 /* for the ASN1_VALUE_NOT_FOUND error. */
42 /* Parameters: */
43 /* node: node of the tree where the value is NULL. */
44 /* ErrorDescription: string returned. */
45 /* Return: */
46 /******************************************************/
47 void
48 _asn1_error_description_value_not_found(node_asn *node,char *ErrorDescription)
51 if (ErrorDescription == NULL) return;
53 Estrcpy(ErrorDescription,":: value of element '");
54 _asn1_hierarchical_name(node,ErrorDescription+strlen(ErrorDescription),
55 MAX_ERROR_DESCRIPTION_SIZE-40);
56 Estrcat(ErrorDescription,"' not found");
60 /******************************************************/
61 /* Function : _asn1_length_der */
62 /* Description: creates the DER coding for the LEN */
63 /* parameter (only the length). */
64 /* Parameters: */
65 /* len: value to convert. */
66 /* ans: string returned. */
67 /* ans_len: number of meaningful bytes of ANS */
68 /* (ans[0]..ans[ans_len-1]). */
69 /* Return: */
70 /******************************************************/
71 void
72 _asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len)
74 int k;
75 unsigned char temp[SIZEOF_UNSIGNED_LONG_INT];
77 if(len<128){
78 /* short form */
79 if(ans!=NULL) ans[0]=(unsigned char)len;
80 *ans_len=1;
82 else{
83 /* Long form */
84 k=0;
85 while(len){
86 temp[k++]=len&0xFF;
87 len=len>>8;
89 *ans_len=k+1;
90 if(ans!=NULL){
91 ans[0]=((unsigned char)k&0x7F)+128;
92 while(k--) ans[*ans_len-1-k]=temp[k];
97 /******************************************************/
98 /* Function : _asn1_tag_der */
99 /* Description: creates the DER coding for the CLASS */
100 /* and TAG parameters. */
101 /* Parameters: */
102 /* class: value to convert. */
103 /* tag_value: value to convert. */
104 /* ans: string returned. */
105 /* ans_len: number of meaningful bytes of ANS */
106 /* (ans[0]..ans[ans_len-1]). */
107 /* Return: */
108 /******************************************************/
109 void
110 _asn1_tag_der(unsigned char class,unsigned int tag_value,unsigned char *ans,int *ans_len)
112 int k;
113 unsigned char temp[SIZEOF_UNSIGNED_INT];
115 if(tag_value<31){
116 /* short form */
117 ans[0]=(class&0xE0) + ((unsigned char)(tag_value&0x1F));
118 *ans_len=1;
120 else{
121 /* Long form */
122 ans[0]=(class&0xE0) + 31;
123 k=0;
124 while(tag_value){
125 temp[k++]=tag_value&0x7F;
126 tag_value=tag_value>>7;
128 *ans_len=k+1;
129 while(k--) ans[*ans_len-1-k]=temp[k]+128;
130 ans[*ans_len-1]-=128;
134 /******************************************************/
135 /* Function : _asn1_octect_der */
136 /* Description: creates the DER coding for an */
137 /* OCTET type (length included). */
138 /* Parameters: */
139 /* str: OCTET string. */
140 /* str_len: STR length (str[0]..str[str_len-1]). */
141 /* der: string returned. */
142 /* der_len: number of meaningful bytes of DER */
143 /* (der[0]..der[ans_len-1]). */
144 /* Return: */
145 /******************************************************/
146 void
147 _asn1_octet_der(const unsigned char *str,int str_len,unsigned char *der,int *der_len)
149 int len_len;
151 if(der==NULL) return;
152 _asn1_length_der(str_len,der,&len_len);
153 memcpy(der+len_len,str,str_len);
154 *der_len=str_len+len_len;
157 /******************************************************/
158 /* Function : _asn1_time_der */
159 /* Description: creates the DER coding for a TIME */
160 /* type (length included). */
161 /* Parameters: */
162 /* str: TIME null-terminated string. */
163 /* der: string returned. */
164 /* der_len: number of meaningful bytes of DER */
165 /* (der[0]..der[ans_len-1]). Initially it */
166 /* if must store the lenght of DER. */
167 /* Return: */
168 /* ASN1_MEM_ERROR when DER isn't big enough */
169 /* ASN1_SUCCESS otherwise */
170 /******************************************************/
171 asn1_retCode
172 _asn1_time_der(unsigned char *str,unsigned char *der,int *der_len)
174 int len_len;
175 int max_len;
177 max_len=*der_len;
179 _asn1_length_der(strlen(str),(max_len>0)?der:NULL,&len_len);
181 if((len_len+(int)strlen(str))<=max_len)
182 memcpy(der+len_len,str,strlen(str));
183 *der_len=len_len+strlen(str);
185 if((*der_len)>max_len) return ASN1_MEM_ERROR;
187 return ASN1_SUCCESS;
192 void
193 _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
195 int len_len,str_len;
196 char temp[20];
198 if(str==NULL) return;
199 str_len=_asn1_get_length_der(der,&len_len);
200 memcpy(temp,der+len_len,str_len);
201 *der_len=str_len+len_len;
202 switch(str_len){
203 case 11:
204 temp[10]=0;
205 strcat(temp,"00+0000");
206 break;
207 case 13:
208 temp[12]=0;
209 strcat(temp,"+0000");
210 break;
211 case 15:
212 temp[15]=0;
213 memmove(temp+12,temp+10,6);
214 temp[10]=temp[11]='0';
215 break;
216 case 17:
217 temp[17]=0;
218 break;
219 default:
220 return;
222 strcpy(str,temp);
226 /******************************************************/
227 /* Function : _asn1_objectid_der */
228 /* Description: creates the DER coding for an */
229 /* OBJECT IDENTIFIER type (length included). */
230 /* Parameters: */
231 /* str: OBJECT IDENTIFIER null-terminated string. */
232 /* der: string returned. */
233 /* der_len: number of meaningful bytes of DER */
234 /* (der[0]..der[ans_len-1]). Initially it */
235 /* must store the length of DER. */
236 /* Return: */
237 /* ASN1_MEM_ERROR when DER isn't big enough */
238 /* ASN1_SUCCESS otherwise */
239 /******************************************************/
240 asn1_retCode
241 _asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len)
243 int len_len,counter,k,first,max_len;
244 char *temp,*n_end,*n_start;
245 unsigned char bit7;
246 unsigned long val,val1=0;
248 max_len=*der_len;
250 temp= (char *) _asn1_alloca(strlen(str)+2);
251 if(temp==NULL) return ASN1_MEM_ALLOC_ERROR;
253 strcpy(temp, str);
254 strcat(temp, ".");
256 counter=0;
257 n_start=temp;
258 while((n_end=strchr(n_start,'.'))){
259 *n_end=0;
260 val=strtoul(n_start,NULL,10);
261 counter++;
263 if(counter==1) val1=val;
264 else if(counter==2){
265 if(max_len>0)
266 der[0]=40*val1+val;
267 *der_len=1;
269 else{
270 first=0;
271 for(k=4;k>=0;k--){
272 bit7=(val>>(k*7))&0x7F;
273 if(bit7 || first || !k){
274 if(k) bit7|=0x80;
275 if(max_len>(*der_len))
276 der[*der_len]=bit7;
277 (*der_len)++;
278 first=1;
283 n_start=n_end+1;
286 _asn1_length_der(*der_len,NULL,&len_len);
287 if(max_len>=(*der_len+len_len)){
288 memmove(der+len_len,der,*der_len);
289 _asn1_length_der(*der_len,der,&len_len);
291 *der_len+=len_len;
293 _asn1_afree(temp);
295 if(max_len<(*der_len)) return ASN1_MEM_ERROR;
297 return ASN1_SUCCESS;
301 const char bit_mask[]={0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
303 /******************************************************/
304 /* Function : _asn1_bit_der */
305 /* Description: creates the DER coding for a BIT */
306 /* STRING type (length and pad included). */
307 /* Parameters: */
308 /* str: BIT string. */
309 /* bit_len: number of meaningful bits in STR. */
310 /* der: string returned. */
311 /* der_len: number of meaningful bytes of DER */
312 /* (der[0]..der[ans_len-1]). */
313 /* Return: */
314 /******************************************************/
315 void
316 _asn1_bit_der(const unsigned char *str,int bit_len,unsigned char *der,int *der_len)
318 int len_len,len_byte,len_pad;
320 if(der==NULL) return;
321 len_byte=bit_len>>3;
322 len_pad=8-(bit_len&7);
323 if(len_pad==8) len_pad=0;
324 else len_byte++;
325 _asn1_length_der(len_byte+1,der,&len_len);
326 der[len_len]=len_pad;
327 memcpy(der+len_len+1,str,len_byte);
328 der[len_len+len_byte]&=bit_mask[len_pad];
329 *der_len=len_byte+len_len+1;
333 /******************************************************/
334 /* Function : _asn1_complete_explicit_tag */
335 /* Description: add the length coding to the EXPLICIT */
336 /* tags. */
337 /* Parameters: */
338 /* node: pointer to the tree element. */
339 /* der: string with the DER coding of the whole tree*/
340 /* counter: number of meaningful bytes of DER */
341 /* (der[0]..der[*counter-1]). */
342 /* max_len: size of der vector */
343 /* Return: */
344 /* ASN1_MEM_ERROR if der vector isn't big enough, */
345 /* otherwise ASN1_SUCCESS. */
346 /******************************************************/
347 asn1_retCode
348 _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter,int *max_len)
350 node_asn *p;
351 int is_tag_implicit,len2,len3;
352 unsigned char temp[SIZEOF_UNSIGNED_INT];
354 is_tag_implicit=0;
356 if(node->type&CONST_TAG){
357 p=node->down;
358 /* When there are nested tags we must complete them reverse to
359 the order they were created. This is because completing a tag
360 modifies all data within it, including the incomplete tags
361 which store buffer positions -- simon@josefsson.org 2002-09-06
363 while(p->right)
364 p=p->right;
365 while(p && p!=node->down->left){
366 if(type_field(p->type)==TYPE_TAG){
367 if(p->type&CONST_EXPLICIT){
368 len2=strtol(p->name,NULL,10);
369 _asn1_set_name(p,NULL);
370 _asn1_length_der(*counter-len2,temp,&len3);
371 if(len3<=(*max_len)){
372 memmove(der+len2+len3,der+len2,*counter-len2);
373 memcpy(der+len2,temp,len3);
375 *max_len -= len3;
376 *counter+=len3;
377 is_tag_implicit=0;
379 else{ /* CONST_IMPLICIT */
380 if(!is_tag_implicit){
381 is_tag_implicit=1;
385 p=p->left;
389 if(*max_len<0) return ASN1_MEM_ERROR;
391 return ASN1_SUCCESS;
395 /******************************************************/
396 /* Function : _asn1_insert_tag_der */
397 /* Description: creates the DER coding of tags of one */
398 /* NODE. */
399 /* Parameters: */
400 /* node: pointer to the tree element. */
401 /* der: string returned */
402 /* counter: number of meaningful bytes of DER */
403 /* (counter[0]..der[*counter-1]). */
404 /* max_len: size of der vector */
405 /* Return: */
406 /* ASN1_GENERIC_ERROR if the type is unknown, */
407 /* ASN1_MEM_ERROR if der vector isn't big enough, */
408 /* otherwise ASN1_SUCCESS. */
409 /******************************************************/
410 asn1_retCode
411 _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter,int *max_len)
413 node_asn *p;
414 int tag_len,is_tag_implicit;
415 unsigned char class,class_implicit=0,temp[SIZEOF_UNSIGNED_INT*3+1];
416 unsigned long tag_implicit=0;
417 char tag_der[MAX_TAG_LEN];
419 is_tag_implicit=0;
421 if(node->type&CONST_TAG){
422 p=node->down;
423 while(p){
424 if(type_field(p->type)==TYPE_TAG){
425 if(p->type&CONST_APPLICATION) class=APPLICATION;
426 else if(p->type&CONST_UNIVERSAL) class=UNIVERSAL;
427 else if(p->type&CONST_PRIVATE) class=PRIVATE;
428 else class=CONTEXT_SPECIFIC;
430 if(p->type&CONST_EXPLICIT){
431 if(is_tag_implicit)
432 _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len);
433 else
434 _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),tag_der,&tag_len);
436 *max_len -= tag_len;
437 if(*max_len>=0)
438 memcpy(der+*counter,tag_der,tag_len);
439 *counter+=tag_len;
441 _asn1_ltostr(*counter,temp);
442 _asn1_set_name(p,temp);
444 is_tag_implicit=0;
446 else{ /* CONST_IMPLICIT */
447 if(!is_tag_implicit){
448 if((type_field(node->type)==TYPE_SEQUENCE) ||
449 (type_field(node->type)==TYPE_SEQUENCE_OF) ||
450 (type_field(node->type)==TYPE_SET) ||
451 (type_field(node->type)==TYPE_SET_OF)) class|=STRUCTURED;
452 class_implicit=class;
453 tag_implicit=strtoul(p->value,NULL,10);
454 is_tag_implicit=1;
458 p=p->right;
462 if(is_tag_implicit){
463 _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len);
465 else{
466 switch(type_field(node->type)){
467 case TYPE_NULL:
468 _asn1_tag_der(UNIVERSAL,TAG_NULL,tag_der,&tag_len);
469 break;
470 case TYPE_BOOLEAN:
471 _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,tag_der,&tag_len);
472 break;
473 case TYPE_INTEGER:
474 _asn1_tag_der(UNIVERSAL,TAG_INTEGER,tag_der,&tag_len);
475 break;
476 case TYPE_ENUMERATED:
477 _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,tag_der,&tag_len);
478 break;
479 case TYPE_OBJECT_ID:
480 _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,tag_der,&tag_len);
481 break;
482 case TYPE_TIME:
483 if(node->type&CONST_UTC){
484 _asn1_tag_der(UNIVERSAL,TAG_UTCTime,tag_der,&tag_len);
486 else _asn1_tag_der(UNIVERSAL,TAG_GENERALIZEDTime,tag_der,&tag_len);
487 break;
488 case TYPE_OCTET_STRING:
489 _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,tag_der,&tag_len);
490 break;
491 case TYPE_GENERALSTRING:
492 _asn1_tag_der(UNIVERSAL,TAG_GENERALSTRING,tag_der,&tag_len);
493 break;
494 case TYPE_BIT_STRING:
495 _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,tag_der,&tag_len);
496 break;
497 case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF:
498 _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,tag_der,&tag_len);
499 break;
500 case TYPE_SET: case TYPE_SET_OF:
501 _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,tag_der,&tag_len);
502 break;
503 case TYPE_TAG:
504 tag_len=0;
505 break;
506 case TYPE_CHOICE:
507 tag_len=0;
508 break;
509 case TYPE_ANY:
510 tag_len=0;
511 break;
512 default:
513 return ASN1_GENERIC_ERROR;
517 *max_len -= tag_len;
518 if(*max_len>=0)
519 memcpy(der+*counter,tag_der,tag_len);
520 *counter+=tag_len;
522 if(*max_len<0) return ASN1_MEM_ERROR;
524 return ASN1_SUCCESS;
527 /******************************************************/
528 /* Function : _asn1_ordering_set */
529 /* Description: puts the elements of a SET type in */
530 /* the correct order according to DER rules. */
531 /* Parameters: */
532 /* der: string with the DER coding. */
533 /* node: pointer to the SET element. */
534 /* Return: */
535 /******************************************************/
536 void
537 _asn1_ordering_set(unsigned char *der,node_asn *node)
539 struct vet{
540 int end;
541 unsigned long value;
542 struct vet *next,*prev;
545 int counter,len,len2;
546 struct vet *first,*last,*p_vet,*p2_vet;
547 node_asn *p;
548 unsigned char class,*temp;
549 unsigned long tag;
551 counter=0;
553 if(type_field(node->type)!=TYPE_SET) return;
555 p=node->down;
556 while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
558 if((p==NULL) || (p->right==NULL)) return;
560 first=last=NULL;
561 while(p){
562 p_vet=(struct vet *)_asn1_alloca( sizeof(struct vet));
563 if (p_vet==NULL) return;
565 p_vet->next=NULL;
566 p_vet->prev=last;
567 if(first==NULL) first=p_vet;
568 else last->next=p_vet;
569 last=p_vet;
571 /* tag value calculation */
572 tag=_asn1_get_tag_der(der+counter,&class,&len2);
573 p_vet->value=(class<<24)|tag;
574 counter+=len2;
576 /* extraction and length */
577 len2=_asn1_get_length_der(der+counter,&len);
578 counter+=len+len2;
580 p_vet->end=counter;
581 p=p->right;
584 p_vet=first;
586 while(p_vet){
587 p2_vet=p_vet->next;
588 counter=0;
589 while(p2_vet){
590 if(p_vet->value>p2_vet->value){
591 /* change position */
592 temp=(unsigned char *)_asn1_alloca( p_vet->end-counter);
593 if (temp==NULL) return;
595 memcpy(temp,der+counter,p_vet->end-counter);
596 memcpy(der+counter,der+p_vet->end,p2_vet->end-p_vet->end);
597 memcpy(der+counter+p2_vet->end-p_vet->end,temp,p_vet->end-counter);
598 _asn1_afree(temp);
600 tag=p_vet->value;
601 p_vet->value=p2_vet->value;
602 p2_vet->value=tag;
604 p_vet->end=counter+(p2_vet->end-p_vet->end);
606 counter=p_vet->end;
608 p2_vet=p2_vet->next;
609 p_vet=p_vet->next;
612 if(p_vet!=first) p_vet->prev->next=NULL;
613 else first=NULL;
614 _asn1_afree(p_vet);
615 p_vet=first;
619 /******************************************************/
620 /* Function : _asn1_ordering_set_of */
621 /* Description: puts the elements of a SET OF type in */
622 /* the correct order according to DER rules. */
623 /* Parameters: */
624 /* der: string with the DER coding. */
625 /* node: pointer to the SET OF element. */
626 /* Return: */
627 /******************************************************/
628 void
629 _asn1_ordering_set_of(unsigned char *der,node_asn *node)
631 struct vet{
632 int end;
633 struct vet *next,*prev;
636 int counter,len,len2,change;
637 struct vet *first,*last,*p_vet,*p2_vet;
638 node_asn *p;
639 unsigned char *temp,class;
640 unsigned long k,max;
642 counter=0;
644 if(type_field(node->type)!=TYPE_SET_OF) return;
646 p=node->down;
647 while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
648 p=p->right;
650 if((p==NULL) || (p->right==NULL)) return;
652 first=last=NULL;
653 while(p){
654 p_vet=(struct vet *)_asn1_alloca(sizeof(struct vet));
655 if (p_vet==NULL) return;
657 p_vet->next=NULL;
658 p_vet->prev=last;
659 if(first==NULL) first=p_vet;
660 else last->next=p_vet;
661 last=p_vet;
663 /* extraction of tag and length */
664 _asn1_get_tag_der(der+counter,&class,&len);
665 counter+=len;
666 len2=_asn1_get_length_der(der+counter,&len);
667 counter+=len+len2;
669 p_vet->end=counter;
670 p=p->right;
673 p_vet=first;
675 while(p_vet){
676 p2_vet=p_vet->next;
677 counter=0;
678 while(p2_vet){
679 if((p_vet->end-counter)>(p2_vet->end-p_vet->end))
680 max=p_vet->end-counter;
681 else
682 max=p2_vet->end-p_vet->end;
684 change=-1;
685 for(k=0;k<max;k++)
686 if(der[counter+k]>der[p_vet->end+k]){change=1;break;}
687 else if(der[counter+k]<der[p_vet->end+k]){change=0;break;}
689 if((change==-1) && ((p_vet->end-counter)>(p2_vet->end-p_vet->end)))
690 change=1;
692 if(change==1){
693 /* change position */
694 temp=(unsigned char *)_asn1_alloca(p_vet->end-counter);
695 if (temp==NULL) return;
697 memcpy(temp,der+counter,(p_vet->end)-counter);
698 memcpy(der+counter,der+(p_vet->end),(p2_vet->end)-(p_vet->end));
699 memcpy(der+counter+(p2_vet->end)-(p_vet->end),temp,(p_vet->end)-counter);
700 _asn1_afree(temp);
702 p_vet->end=counter+(p2_vet->end-p_vet->end);
704 counter=p_vet->end;
706 p2_vet=p2_vet->next;
707 p_vet=p_vet->next;
710 if(p_vet!=first) p_vet->prev->next=NULL;
711 else first=NULL;
712 _asn1_afree(p_vet);
713 p_vet=first;
718 * asn1_der_coding - Creates the DER encoding for the NAME structure
719 * @element: pointer to an ASN1 element
720 * @name: the name of the structure you want to encode (it must be
721 * inside *POINTER).
722 * @ider: vector that will contain the DER encoding. DER must be a
723 * pointer to memory cells already allocated.
724 * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy
725 * holds the sizeof of der vector.
726 * @errorDescription : return the error description or an empty
727 * string if success.
729 * Creates the DER encoding for the NAME structure (inside *POINTER
730 * structure).
732 * Returns:
734 * ASN1_SUCCESS: DER encoding OK.
736 * ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
738 * ASN1_VALUE_NOT_FOUND: There is an element without a value.
740 * ASN1_MEM_ERROR: @ider vector isn't big enough. Also in this case
741 * LEN will contain the length needed.
744 asn1_retCode
745 asn1_der_coding(ASN1_TYPE element,const char *name,void *ider,int *len,
746 char *ErrorDescription)
748 node_asn *node,*p,*p2;
749 char temp[SIZEOF_UNSIGNED_LONG_INT*3+1];
750 int counter,counter_old,len2,len3,tlen,move,max_len,max_len_old;
751 asn1_retCode ris;
752 unsigned char* der = ider;
754 node=_asn1_find_node(element,name);
755 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
757 max_len=*len;
759 counter=0;
760 move=DOWN;
761 p=node;
762 while(1){
764 counter_old=counter;
765 max_len_old=max_len;
766 if(move!=UP){
767 ris=_asn1_insert_tag_der(p,der,&counter,&max_len);
769 switch(type_field(p->type)){
770 case TYPE_NULL:
771 max_len--;
772 if(max_len>=0)
773 der[counter++]=0;
774 move=RIGHT;
775 break;
776 case TYPE_BOOLEAN:
777 if((p->type&CONST_DEFAULT) && (p->value==NULL)){
778 counter=counter_old;
779 max_len=max_len_old;
781 else{
782 if(p->value==NULL){
783 _asn1_error_description_value_not_found(p,ErrorDescription);
784 return ASN1_VALUE_NOT_FOUND;
786 max_len -= 2;
787 if(max_len>=0){
788 der[counter++]=1;
789 if(p->value[0]=='F') der[counter++]=0;
790 else der[counter++]=0xFF;
792 else
793 counter+=2;
795 move=RIGHT;
796 break;
797 case TYPE_INTEGER: case TYPE_ENUMERATED:
798 if((p->type&CONST_DEFAULT) && (p->value==NULL)){
799 counter=counter_old;
800 max_len=max_len_old;
802 else{
803 if(p->value==NULL){
804 _asn1_error_description_value_not_found(p,ErrorDescription);
805 return ASN1_VALUE_NOT_FOUND;
807 len2=_asn1_get_length_der(p->value,&len3);
808 max_len -= len2+len3;
809 if(max_len>=0)
810 memcpy(der+counter,p->value,len3+len2);
811 counter+=len3+len2;
813 move=RIGHT;
814 break;
815 case TYPE_OBJECT_ID:
816 if((p->type&CONST_DEFAULT) && (p->value==NULL)){
817 counter=counter_old;
818 max_len=max_len_old;
820 else{
821 if(p->value==NULL){
822 _asn1_error_description_value_not_found(p,ErrorDescription);
823 return ASN1_VALUE_NOT_FOUND;
825 len2=max_len;
826 ris=_asn1_objectid_der(p->value,der+counter,&len2);
827 if(ris==ASN1_MEM_ALLOC_ERROR) return ris;
828 max_len-=len2;
829 counter+=len2;
831 move=RIGHT;
832 break;
833 case TYPE_TIME:
834 if(p->value==NULL){
835 _asn1_error_description_value_not_found(p,ErrorDescription);
836 return ASN1_VALUE_NOT_FOUND;
838 len2=max_len;
839 ris=_asn1_time_der(p->value,der+counter,&len2);
840 max_len-=len2;
841 counter+=len2;
842 move=RIGHT;
843 break;
844 case TYPE_OCTET_STRING:
845 if(p->value==NULL){
846 _asn1_error_description_value_not_found(p,ErrorDescription);
847 return ASN1_VALUE_NOT_FOUND;
849 len2=_asn1_get_length_der(p->value,&len3);
850 max_len-=len2+len3;
851 if(max_len>=0)
852 memcpy(der+counter,p->value,len3+len2);
853 counter+=len3+len2;
854 move=RIGHT;
855 break;
856 case TYPE_GENERALSTRING:
857 if(p->value==NULL){
858 _asn1_error_description_value_not_found(p,ErrorDescription);
859 return ASN1_VALUE_NOT_FOUND;
861 len2=_asn1_get_length_der(p->value,&len3);
862 max_len-=len2+len3;
863 if(max_len>=0)
864 memcpy(der+counter,p->value,len3+len2);
865 counter+=len3+len2;
866 move=RIGHT;
867 break;
868 case TYPE_BIT_STRING:
869 if(p->value==NULL){
870 _asn1_error_description_value_not_found(p,ErrorDescription);
871 return ASN1_VALUE_NOT_FOUND;
873 len2=_asn1_get_length_der(p->value,&len3);
874 max_len-=len2+len3;
875 if(max_len>=0)
876 memcpy(der+counter,p->value,len3+len2);
877 counter+=len3+len2;
878 move=RIGHT;
879 break;
880 case TYPE_SEQUENCE: case TYPE_SET:
881 if(move!=UP){
882 _asn1_ltostr(counter,temp);
883 tlen = strlen(temp);
884 if (tlen > 0)
885 _asn1_set_value(p,temp,tlen+1);
886 if(p->down==NULL){
887 move=UP;
888 continue;
890 else{
891 p2=p->down;
892 while(p2 && (type_field(p2->type)==TYPE_TAG)) p2=p2->right;
893 if(p2){
894 p=p2;
895 move=RIGHT;
896 continue;
898 move=UP;
899 continue;
902 else{ /* move==UP */
903 len2=strtol(p->value,NULL,10);
904 _asn1_set_value(p,NULL,0);
905 if((type_field(p->type)==TYPE_SET) && (max_len>=0))
906 _asn1_ordering_set(der+len2,p);
907 _asn1_length_der(counter-len2,temp,&len3);
908 max_len-=len3;
909 if(max_len>=0){
910 memmove(der+len2+len3,der+len2,counter-len2);
911 memcpy(der+len2,temp,len3);
913 counter+=len3;
914 move=RIGHT;
916 break;
917 case TYPE_SEQUENCE_OF: case TYPE_SET_OF:
918 if(move!=UP){
919 _asn1_ltostr(counter,temp);
920 tlen = strlen(temp);
922 if (tlen > 0)
923 _asn1_set_value(p,temp,tlen+1);
924 p=p->down;
925 while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
926 if(p->right){
927 p=p->right;
928 move=RIGHT;
929 continue;
931 else p=_asn1_find_up(p);
932 move=UP;
934 if(move==UP){
935 len2=strtol(p->value,NULL,10);
936 _asn1_set_value(p,NULL,0);
937 if((type_field(p->type)==TYPE_SET_OF) && (max_len>=0))
938 _asn1_ordering_set_of(der+len2,p);
939 _asn1_length_der(counter-len2,temp,&len3);
940 max_len-=len3;
941 if(max_len>=0){
942 memmove(der+len2+len3,der+len2,counter-len2);
943 memcpy(der+len2,temp,len3);
945 counter+=len3;
946 move=RIGHT;
948 break;
949 case TYPE_ANY:
950 if(p->value==NULL){
951 _asn1_error_description_value_not_found(p,ErrorDescription);
952 return ASN1_VALUE_NOT_FOUND;
954 len2=_asn1_get_length_der(p->value,&len3);
955 max_len-=len2;
956 if(max_len>=0)
957 memcpy(der+counter,p->value+len3,len2);
958 counter+=len2;
959 move=RIGHT;
960 break;
961 default:
962 move=(move==UP)?RIGHT:DOWN;
963 break;
966 if((move!=DOWN) && (counter!=counter_old)){
967 ris=_asn1_complete_explicit_tag(p,der,&counter,&max_len);
970 if(p==node && move!=DOWN) break;
972 if(move==DOWN){
973 if(p->down) p=p->down;
974 else move=RIGHT;
976 if(move==RIGHT){
977 if(p->right) p=p->right;
978 else move=UP;
980 if(move==UP) p=_asn1_find_up(p);
983 *len=counter;
985 if(max_len<0) return ASN1_MEM_ERROR;
987 return ASN1_SUCCESS;