1 /*
2  * src/lib/krb5/asn.1/asn1_make.c
3  *
4  * Copyright 1994 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 #include "asn1_make.h"
28 
asn1_make_etag(asn1buf * buf,asn1_class asn1class,asn1_tagnum tagnum,unsigned int in_len,unsigned int * retlen)29 asn1_error_code asn1_make_etag(asn1buf *buf, asn1_class asn1class,
30 			       asn1_tagnum tagnum, unsigned int in_len,
31 			       unsigned int *retlen)
32 {
33   return asn1_make_tag(buf,asn1class,CONSTRUCTED,tagnum,in_len,retlen);
34 }
35 
36 
asn1_make_tag(asn1buf * buf,asn1_class asn1class,asn1_construction construction,asn1_tagnum tagnum,unsigned int in_len,unsigned int * retlen)37 asn1_error_code asn1_make_tag(asn1buf *buf, asn1_class asn1class,
38 			      asn1_construction construction,
39 			      asn1_tagnum tagnum, unsigned int in_len,
40 			      unsigned int *retlen)
41 {
42   asn1_error_code retval;
43   unsigned int sumlen=0, length;
44 
45   if(tagnum > ASN1_TAGNUM_MAX) return ASN1_OVERFLOW;
46 
47   retval = asn1_make_length(buf,in_len, &length);
48   if(retval) return retval;
49   sumlen += length;
50   retval = asn1_make_id(buf,asn1class,construction,tagnum,&length);
51   if(retval) return retval;
52   sumlen += length;
53 
54   *retlen = sumlen;
55   return 0;
56 }
57 
asn1_make_length(asn1buf * buf,const unsigned int in_len,unsigned int * retlen)58 asn1_error_code asn1_make_length(asn1buf *buf, const unsigned int in_len, unsigned int *retlen)
59 {
60   asn1_error_code retval;
61 
62   if(in_len < 128){
63     retval = asn1buf_insert_octet(buf, (asn1_octet)(in_len&0x7F));
64     if(retval) return retval;
65     *retlen = 1;
66   }else{
67     int in_copy=in_len, length=0;
68 
69     while(in_copy != 0){
70       retval = asn1buf_insert_octet(buf, (asn1_octet)(in_copy&0xFF));
71       if(retval) return retval;
72       in_copy = in_copy >> 8;
73       length++;
74     }
75     retval = asn1buf_insert_octet(buf, (asn1_octet) (0x80 | (asn1_octet)(length&0x7F)));
76     if(retval) return retval;
77     length++;
78     *retlen = length;
79   }
80 
81   return 0;
82 }
83 
asn1_make_id(asn1buf * buf,asn1_class asn1class,asn1_construction construction,asn1_tagnum tagnum,unsigned int * retlen)84 asn1_error_code asn1_make_id(asn1buf *buf, asn1_class asn1class,
85 			     asn1_construction construction,
86 			     asn1_tagnum tagnum, unsigned int *retlen)
87 {
88   asn1_error_code retval;
89 
90   if(tagnum < 31) {
91     retval = asn1buf_insert_octet(buf, (asn1_octet) (asn1class | construction |
92 						     (asn1_octet)tagnum));
93     if(retval) return retval;
94     *retlen = 1;
95   }else{
96     asn1_tagnum tagcopy = tagnum;
97     int length = 0;
98 
99     retval = asn1buf_insert_octet(buf, (asn1_octet)(tagcopy&0x7F));
100     if(retval) return retval;
101     tagcopy >>= 7;
102     length++;
103 
104     for(; tagcopy != 0; tagcopy >>= 7){
105       retval = asn1buf_insert_octet(buf, (asn1_octet) (0x80 | (asn1_octet)(tagcopy&0x7F)));
106       if(retval) return retval;
107       length++;
108     }
109 
110     retval = asn1buf_insert_octet(buf, (asn1_octet) (asn1class | construction | 0x1F));
111     if(retval) return retval;
112     length++;
113     *retlen = length;
114   }
115 
116   return 0;
117 }
118 
asn1_make_sequence(asn1buf * buf,const unsigned int seq_len,unsigned int * retlen)119 asn1_error_code asn1_make_sequence(asn1buf *buf, const unsigned int seq_len, unsigned int *retlen)
120 {
121   asn1_error_code retval;
122   unsigned int len, sum=0;
123 
124   retval = asn1_make_length(buf,seq_len,&len);
125   if(retval) return retval;
126   sum += len;
127   retval = asn1_make_id(buf,UNIVERSAL,CONSTRUCTED,ASN1_SEQUENCE,&len);
128   if(retval) return retval;
129   sum += len;
130 
131   *retlen = sum;
132   return 0;
133 }
134 
asn1_make_set(asn1buf * buf,const unsigned int set_len,unsigned int * retlen)135 asn1_error_code asn1_make_set(asn1buf *buf, const unsigned int set_len, unsigned int *retlen)
136 {
137   asn1_error_code retval;
138   unsigned int len, sum=0;
139 
140   retval = asn1_make_length(buf,set_len,&len);
141   if(retval) return retval;
142   sum += len;
143   retval = asn1_make_id(buf,UNIVERSAL,CONSTRUCTED,ASN1_SET,&len);
144   if(retval) return retval;
145   sum += len;
146 
147   *retlen = sum;
148   return 0;
149 }
150 
asn1_make_string(asn1buf * buf,const unsigned int length,const char * string,int * retlen)151 asn1_error_code asn1_make_string(asn1buf *buf, const unsigned int length, const char *string, int *retlen)
152 {
153   asn1_error_code retval;
154 
155   retval = asn1buf_insert_charstring(buf,length,string);
156   if(retval) return retval;
157 
158   *retlen = length;
159   return 0;
160 }
161