Add getdate stuff.
[shishi.git] / asn1 / coding.c
blobd46dc7b3f0c408b907a3bc9eea70f4782a91b134
1 /*
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 /*****************************************************/
23 /* File: coding.c */
24 /* Description: Functions to create a DER coding of */
25 /* an ASN1 type. */
26 /*****************************************************/
28 #include <int.h>
29 #include <errors.h>
30 #include "der.h"
31 #include "parser_aux.h"
32 #include <gstr.h>
33 #include "element.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. */
41 /* Parameters: */
42 /* node: node of the tree where the value is NULL. */
43 /* ErrorDescription: string returned. */
44 /* Return: */
45 /******************************************************/
46 void
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). */
63 /* Parameters: */
64 /* len: value to convert. */
65 /* ans: string returned. */
66 /* ans_len: number of meanful bytes of ANS */
67 /* (ans[0]..ans[ans_len-1]). */
68 /* Return: */
69 /******************************************************/
70 void
71 _asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len)
73 int k;
74 unsigned char temp[SIZEOF_UNSIGNED_LONG_INT];
76 if(len<128){
77 /* short form */
78 if(ans!=NULL) ans[0]=(unsigned char)len;
79 *ans_len=1;
81 else{
82 /* Long form */
83 k=0;
84 while(len){
85 temp[k++]=len&0xFF;
86 len=len>>8;
88 *ans_len=k+1;
89 if(ans!=NULL){
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. */
100 /* Parameters: */
101 /* class: value to convert. */
102 /* tag_value: value to convert. */
103 /* ans: string returned. */
104 /* ans_len: number of meanful bytes of ANS */
105 /* (ans[0]..ans[ans_len-1]). */
106 /* Return: */
107 /******************************************************/
108 void
109 _asn1_tag_der(unsigned char class,unsigned int tag_value,unsigned char *ans,int *ans_len)
111 int k;
112 unsigned char temp[SIZEOF_UNSIGNED_INT];
114 if(tag_value<31){
115 /* short form */
116 ans[0]=(class&0xE0) + ((unsigned char)(tag_value&0x1F));
117 *ans_len=1;
119 else{
120 /* Long form */
121 ans[0]=(class&0xE0) + 31;
122 k=0;
123 while(tag_value){
124 temp[k++]=tag_value&0x7F;
125 tag_value=tag_value>>7;
127 *ans_len=k+1;
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). */
137 /* Parameters: */
138 /* str: OCTET string. */
139 /* str_len: STR length (str[0]..str[str_len-1]). */
140 /* der: string returned. */
141 /* der_len: number of meanful bytes of DER */
142 /* (der[0]..der[ans_len-1]). */
143 /* Return: */
144 /******************************************************/
145 void
146 _asn1_octet_der(const unsigned char *str,int str_len,unsigned char *der,int *der_len)
148 int len_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). */
160 /* Parameters: */
161 /* str: TIME null-terminated string. */
162 /* der: string returned. */
163 /* der_len: number of meanful bytes of DER */
164 /* (der[0]..der[ans_len-1]). Initially it */
165 /* if must store the lenght of DER. */
166 /* Return: */
167 /* ASN1_MEM_ERROR when DER isn't big enough */
168 /* ASN1_SUCCESS otherwise */
169 /******************************************************/
170 asn1_retCode
171 _asn1_time_der(unsigned char *str,unsigned char *der,int *der_len)
173 int len_len;
174 int max_len;
176 max_len=*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;
186 return ASN1_SUCCESS;
191 void
192 _asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str)
194 int len_len,str_len;
195 char temp[20];
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;
201 switch(str_len){
202 case 11:
203 temp[10]=0;
204 strcat(temp,"00+0000");
205 break;
206 case 13:
207 temp[12]=0;
208 strcat(temp,"+0000");
209 break;
210 case 15:
211 temp[15]=0;
212 memmove(temp+12,temp+10,6);
213 temp[10]=temp[11]='0';
214 break;
215 case 17:
216 temp[17]=0;
217 break;
218 default:
219 return;
221 strcpy(str,temp);
225 /******************************************************/
226 /* Function : _asn1_objectid_der */
227 /* Description: creates the DER coding for an */
228 /* OBJECT IDENTIFIER type (length included). */
229 /* Parameters: */
230 /* str: OBJECT IDENTIFIER null-terminated string. */
231 /* der: string returned. */
232 /* der_len: number of meanful bytes of DER */
233 /* (der[0]..der[ans_len-1]). Initially it */
234 /* if must store the lenght of DER. */
235 /* Return: */
236 /* ASN1_MEM_ERROR when DER isn't big enough */
237 /* ASN1_SUCCESS otherwise */
238 /******************************************************/
239 asn1_retCode
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;
244 unsigned char bit7;
245 unsigned long val,val1=0;
247 max_len=*der_len;
249 temp=(char *) _asn1_alloca(strlen(str)+2);
250 if(temp==NULL) return ASN1_MEM_ALLOC_ERROR;
252 strcpy(temp, str);
253 strcat(temp, ".");
255 counter=0;
256 n_start=temp;
257 while((n_end=strchr(n_start,'.'))){
258 *n_end=0;
259 val=strtoul(n_start,NULL,10);
260 counter++;
262 if(counter==1) val1=val;
263 else if(counter==2){
264 if(max_len>0)
265 der[0]=40*val1+val;
266 *der_len=1;
268 else{
269 first=0;
270 for(k=4;k>=0;k--){
271 bit7=(val>>(k*7))&0x7F;
272 if(bit7 || first || !k){
273 if(k) bit7|=0x80;
274 if(max_len>(*der_len))
275 der[*der_len]=bit7;
276 (*der_len)++;
277 first=1;
282 n_start=n_end+1;
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);
290 *der_len+=len_len;
292 _asn1_afree(temp);
294 if(max_len<(*der_len)) return ASN1_MEM_ERROR;
296 return ASN1_SUCCESS;
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). */
306 /* Parameters: */
307 /* str: BIT string. */
308 /* bit_len: number of meanful bits in STR. */
309 /* der: string returned. */
310 /* der_len: number of meanful bytes of DER */
311 /* (der[0]..der[ans_len-1]). */
312 /* Return: */
313 /******************************************************/
314 void
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;
320 len_byte=bit_len>>3;
321 len_pad=8-(bit_len&7);
322 if(len_pad==8) len_pad=0;
323 else len_byte++;
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 */
335 /* tags. */
336 /* Parameters: */
337 /* node: pointer to the tree element. */
338 /* der: string with the DER coding of the whole tree*/
339 /* counter: number of meanful bytes of DER */
340 /* (der[0]..der[*counter-1]). */
341 /* max_len: size of der vector */
342 /* Return: */
343 /* ASN1_MEM_ERROR if der vector isn't big enough, */
344 /* otherwise ASN1_SUCCESS. */
345 /******************************************************/
346 asn1_retCode
347 _asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter,int *max_len)
349 node_asn *p;
350 int is_tag_implicit,len2,len3;
351 unsigned char temp[SIZEOF_UNSIGNED_INT];
353 is_tag_implicit=0;
355 if(node->type&CONST_TAG){
356 p=node->down;
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 alla date within it, including the incomplete tags
360 which store buffer positions -- simon@josefsson.org 2002-09-06
362 while(p->right)
363 p=p->right;
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);
374 *max_len -= len3;
375 *counter+=len3;
376 is_tag_implicit=0;
378 else{ /* CONST_IMPLICIT */
379 if(!is_tag_implicit){
380 is_tag_implicit=1;
384 p=p->left;
388 if(*max_len<0) return ASN1_MEM_ERROR;
390 return ASN1_SUCCESS;
394 /******************************************************/
395 /* Function : _asn1_insert_tag_der */
396 /* Description: creates the DER coding of tags of one */
397 /* NODE. */
398 /* Parameters: */
399 /* node: pointer to the tree element. */
400 /* der: string returned */
401 /* counter: number of meanful bytes of DER */
402 /* (counter[0]..der[*counter-1]). */
403 /* max_len: size of der vector */
404 /* Return: */
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 /******************************************************/
409 asn1_retCode
410 _asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter,int *max_len)
412 node_asn *p;
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];
418 is_tag_implicit=0;
420 if(node->type&CONST_TAG){
421 p=node->down;
422 while(p){
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){
430 if(is_tag_implicit)
431 _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len);
432 else
433 _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),tag_der,&tag_len);
435 *max_len -= tag_len;
436 if(*max_len>=0)
437 memcpy(der+*counter,tag_der,tag_len);
438 *counter+=tag_len;
440 _asn1_ltostr(*counter,temp);
441 _asn1_set_name(p,temp);
443 is_tag_implicit=0;
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);
453 is_tag_implicit=1;
457 p=p->right;
461 if(is_tag_implicit){
462 _asn1_tag_der(class_implicit,tag_implicit,tag_der,&tag_len);
464 else{
465 switch(type_field(node->type)){
466 case TYPE_NULL:
467 _asn1_tag_der(UNIVERSAL,TAG_NULL,tag_der,&tag_len);
468 break;
469 case TYPE_BOOLEAN:
470 _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,tag_der,&tag_len);
471 break;
472 case TYPE_INTEGER:
473 _asn1_tag_der(UNIVERSAL,TAG_INTEGER,tag_der,&tag_len);
474 break;
475 case TYPE_ENUMERATED:
476 _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,tag_der,&tag_len);
477 break;
478 case TYPE_OBJECT_ID:
479 _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,tag_der,&tag_len);
480 break;
481 case TYPE_TIME:
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);
486 break;
487 case TYPE_OCTET_STRING:
488 _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,tag_der,&tag_len);
489 break;
490 case TYPE_GENERALSTRING:
491 _asn1_tag_der(UNIVERSAL,TAG_GENERALSTRING,tag_der,&tag_len);
492 break;
493 case TYPE_BIT_STRING:
494 _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,tag_der,&tag_len);
495 break;
496 case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF:
497 _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,tag_der,&tag_len);
498 break;
499 case TYPE_SET: case TYPE_SET_OF:
500 _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,tag_der,&tag_len);
501 break;
502 case TYPE_TAG:
503 tag_len=0;
504 break;
505 case TYPE_CHOICE:
506 tag_len=0;
507 break;
508 case TYPE_ANY:
509 tag_len=0;
510 break;
511 default:
512 return ASN1_GENERIC_ERROR;
516 *max_len -= tag_len;
517 if(*max_len>=0)
518 memcpy(der+*counter,tag_der,tag_len);
519 *counter+=tag_len;
521 if(*max_len<0) return ASN1_MEM_ERROR;
523 return ASN1_SUCCESS;
526 /******************************************************/
527 /* Function : _asn1_ordering_set */
528 /* Description: puts the elements of a SET type in */
529 /* the correct order according to DER rules. */
530 /* Parameters: */
531 /* der: string with the DER coding. */
532 /* node: pointer to the SET element. */
533 /* Return: */
534 /******************************************************/
535 void
536 _asn1_ordering_set(unsigned char *der,node_asn *node)
538 struct vet{
539 int end;
540 unsigned long value;
541 struct vet *next,*prev;
544 int counter,len,len2;
545 struct vet *first,*last,*p_vet,*p2_vet;
546 node_asn *p;
547 unsigned char class,*temp;
548 unsigned long tag;
550 counter=0;
552 if(type_field(node->type)!=TYPE_SET) return;
554 p=node->down;
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;
559 first=last=NULL;
560 while(p){
561 p_vet=(struct vet *)_asn1_alloca( sizeof(struct vet));
562 if (p_vet==NULL) return;
564 p_vet->next=NULL;
565 p_vet->prev=last;
566 if(first==NULL) first=p_vet;
567 else last->next=p_vet;
568 last=p_vet;
570 /* tag value calculation */
571 tag=_asn1_get_tag_der(der+counter,&class,&len2);
572 p_vet->value=(class<<24)|tag;
573 counter+=len2;
575 /* extraction and length */
576 len2=_asn1_get_length_der(der+counter,&len);
577 counter+=len+len2;
579 p_vet->end=counter;
580 p=p->right;
583 p_vet=first;
585 while(p_vet){
586 p2_vet=p_vet->next;
587 counter=0;
588 while(p2_vet){
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);
597 _asn1_afree(temp);
599 tag=p_vet->value;
600 p_vet->value=p2_vet->value;
601 p2_vet->value=tag;
603 p_vet->end=counter+(p2_vet->end-p_vet->end);
605 counter=p_vet->end;
607 p2_vet=p2_vet->next;
608 p_vet=p_vet->next;
611 if(p_vet!=first) p_vet->prev->next=NULL;
612 else first=NULL;
613 _asn1_afree(p_vet);
614 p_vet=first;
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. */
622 /* Parameters: */
623 /* der: string with the DER coding. */
624 /* node: pointer to the SET OF element. */
625 /* Return: */
626 /******************************************************/
627 void
628 _asn1_ordering_set_of(unsigned char *der,node_asn *node)
630 struct vet{
631 int end;
632 struct vet *next,*prev;
635 int counter,len,len2,change;
636 struct vet *first,*last,*p_vet,*p2_vet;
637 node_asn *p;
638 unsigned char *temp,class;
639 unsigned long k,max;
641 counter=0;
643 if(type_field(node->type)!=TYPE_SET_OF) return;
645 p=node->down;
646 while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
647 p=p->right;
649 if((p==NULL) || (p->right==NULL)) return;
651 first=last=NULL;
652 while(p){
653 p_vet=(struct vet *)_asn1_alloca(sizeof(struct vet));
654 if (p_vet==NULL) return;
656 p_vet->next=NULL;
657 p_vet->prev=last;
658 if(first==NULL) first=p_vet;
659 else last->next=p_vet;
660 last=p_vet;
662 /* extraction of tag and length */
663 _asn1_get_tag_der(der+counter,&class,&len);
664 counter+=len;
665 len2=_asn1_get_length_der(der+counter,&len);
666 counter+=len+len2;
668 p_vet->end=counter;
669 p=p->right;
672 p_vet=first;
674 while(p_vet){
675 p2_vet=p_vet->next;
676 counter=0;
677 while(p2_vet){
678 if((p_vet->end-counter)>(p2_vet->end-p_vet->end))
679 max=p_vet->end-counter;
680 else
681 max=p2_vet->end-p_vet->end;
683 change=-1;
684 for(k=0;k<max;k++)
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)))
689 change=1;
691 if(change==1){
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);
699 _asn1_afree(temp);
701 p_vet->end=counter+(p2_vet->end-p_vet->end);
703 counter=p_vet->end;
705 p2_vet=p2_vet->next;
706 p_vet=p_vet->next;
709 if(p_vet!=first) p_vet->prev->next=NULL;
710 else first=NULL;
711 _asn1_afree(p_vet);
712 p_vet=first;
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 * @der: 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.
723 * Description:
725 * Creates the DER encoding for the NAME structure (inside *POINTER structure).
727 * Returns:
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.
739 asn1_retCode
740 asn1_der_coding(ASN1_TYPE element,const char *name,unsigned char *der,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,move,max_len,max_len_old;
746 asn1_retCode ris;
748 node=_asn1_find_node(element,name);
749 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
751 max_len=*len;
753 counter=0;
754 move=DOWN;
755 p=node;
756 while(1){
758 counter_old=counter;
759 max_len_old=max_len;
760 if(move!=UP){
761 ris=_asn1_insert_tag_der(p,der,&counter,&max_len);
763 switch(type_field(p->type)){
764 case TYPE_NULL:
765 max_len--;
766 if(max_len>=0)
767 der[counter++]=0;
768 move=RIGHT;
769 break;
770 case TYPE_BOOLEAN:
771 if((p->type&CONST_DEFAULT) && (p->value==NULL)){
772 counter=counter_old;
773 max_len=max_len_old;
775 else{
776 if(p->value==NULL){
777 _asn1_error_description_value_not_found(p,ErrorDescription);
778 return ASN1_VALUE_NOT_FOUND;
780 max_len -= 2;
781 if(max_len>=0){
782 der[counter++]=1;
783 if(p->value[0]=='F') der[counter++]=0;
784 else der[counter++]=0xFF;
786 else
787 counter+=2;
789 move=RIGHT;
790 break;
791 case TYPE_INTEGER: case TYPE_ENUMERATED:
792 if((p->type&CONST_DEFAULT) && (p->value==NULL)){
793 counter=counter_old;
794 max_len=max_len_old;
796 else{
797 if(p->value==NULL){
798 _asn1_error_description_value_not_found(p,ErrorDescription);
799 return ASN1_VALUE_NOT_FOUND;
801 len2=_asn1_get_length_der(p->value,&len3);
802 max_len -= len2+len3;
803 if(max_len>=0)
804 memcpy(der+counter,p->value,len3+len2);
805 counter+=len3+len2;
807 move=RIGHT;
808 break;
809 case TYPE_OBJECT_ID:
810 if((p->type&CONST_DEFAULT) && (p->value==NULL)){
811 counter=counter_old;
812 max_len=max_len_old;
814 else{
815 if(p->value==NULL){
816 _asn1_error_description_value_not_found(p,ErrorDescription);
817 return ASN1_VALUE_NOT_FOUND;
819 len2=max_len;
820 ris=_asn1_objectid_der(p->value,der+counter,&len2);
821 if(ris==ASN1_MEM_ALLOC_ERROR) return ris;
822 max_len-=len2;
823 counter+=len2;
825 move=RIGHT;
826 break;
827 case TYPE_TIME:
828 if(p->value==NULL){
829 _asn1_error_description_value_not_found(p,ErrorDescription);
830 return ASN1_VALUE_NOT_FOUND;
832 len2=max_len;
833 ris=_asn1_time_der(p->value,der+counter,&len2);
834 max_len-=len2;
835 counter+=len2;
836 move=RIGHT;
837 break;
838 case TYPE_OCTET_STRING:
839 if(p->value==NULL){
840 _asn1_error_description_value_not_found(p,ErrorDescription);
841 return ASN1_VALUE_NOT_FOUND;
843 len2=_asn1_get_length_der(p->value,&len3);
844 max_len-=len2+len3;
845 if(max_len>=0)
846 memcpy(der+counter,p->value,len3+len2);
847 counter+=len3+len2;
848 move=RIGHT;
849 break;
850 case TYPE_GENERALSTRING:
851 if(p->value==NULL){
852 _asn1_error_description_value_not_found(p,ErrorDescription);
853 return ASN1_VALUE_NOT_FOUND;
855 len2=_asn1_get_length_der(p->value,&len3);
856 max_len-=len2+len3;
857 if(max_len>=0)
858 memcpy(der+counter,p->value,len3+len2);
859 counter+=len3+len2;
860 move=RIGHT;
861 break;
862 case TYPE_BIT_STRING:
863 if(p->value==NULL){
864 _asn1_error_description_value_not_found(p,ErrorDescription);
865 return ASN1_VALUE_NOT_FOUND;
867 len2=_asn1_get_length_der(p->value,&len3);
868 max_len-=len2+len3;
869 if(max_len>=0)
870 memcpy(der+counter,p->value,len3+len2);
871 counter+=len3+len2;
872 move=RIGHT;
873 break;
874 case TYPE_SEQUENCE: case TYPE_SET:
875 if(move!=UP){
876 _asn1_ltostr(counter,temp);
877 _asn1_set_value(p,temp,strlen(temp)+1);
878 if(p->down==NULL){
879 move=UP;
880 continue;
882 else{
883 p2=p->down;
884 while(p2 && (type_field(p2->type)==TYPE_TAG)) p2=p2->right;
885 if(p2){
886 p=p2;
887 move=RIGHT;
888 continue;
890 move=UP;
891 continue;
894 else{ /* move==UP */
895 len2=strtol(p->value,NULL,10);
896 _asn1_set_value(p,NULL,0);
897 if((type_field(p->type)==TYPE_SET) && (max_len>=0))
898 _asn1_ordering_set(der+len2,p);
899 _asn1_length_der(counter-len2,temp,&len3);
900 max_len-=len3;
901 if(max_len>=0){
902 memmove(der+len2+len3,der+len2,counter-len2);
903 memcpy(der+len2,temp,len3);
905 counter+=len3;
906 move=RIGHT;
908 break;
909 case TYPE_SEQUENCE_OF: case TYPE_SET_OF:
910 if(move!=UP){
911 _asn1_ltostr(counter,temp);
912 _asn1_set_value(p,temp,strlen(temp)+1);
913 p=p->down;
914 while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
915 if(p->right){
916 p=p->right;
917 move=RIGHT;
918 continue;
920 else p=_asn1_find_up(p);
921 move=UP;
923 if(move==UP){
924 len2=strtol(p->value,NULL,10);
925 _asn1_set_value(p,NULL,0);
926 if((type_field(p->type)==TYPE_SET_OF) && (max_len>=0))
927 _asn1_ordering_set_of(der+len2,p);
928 _asn1_length_der(counter-len2,temp,&len3);
929 max_len-=len3;
930 if(max_len>=0){
931 memmove(der+len2+len3,der+len2,counter-len2);
932 memcpy(der+len2,temp,len3);
934 counter+=len3;
935 move=RIGHT;
937 break;
938 case TYPE_ANY:
939 if(p->value==NULL){
940 _asn1_error_description_value_not_found(p,ErrorDescription);
941 return ASN1_VALUE_NOT_FOUND;
943 len2=_asn1_get_length_der(p->value,&len3);
944 max_len-=len2;
945 if(max_len>=0)
946 memcpy(der+counter,p->value+len3,len2);
947 counter+=len2;
948 move=RIGHT;
949 break;
950 default:
951 move=(move==UP)?RIGHT:DOWN;
952 break;
955 if((move!=DOWN) && (counter!=counter_old)){
956 ris=_asn1_complete_explicit_tag(p,der,&counter,&max_len);
959 if(p==node && move!=DOWN) break;
961 if(move==DOWN){
962 if(p->down) p=p->down;
963 else move=RIGHT;
965 if(move==RIGHT){
966 if(p->right) p=p->right;
967 else move=UP;
969 if(move==UP) p=_asn1_find_up(p);
972 *len=counter;
974 if(max_len<0) return ASN1_MEM_ERROR;
976 return ASN1_SUCCESS;