xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_encode.c (revision 004388ebfdfe2ed7dfd2d153a876dfcc22d2c006)
1 /*
2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * src/lib/krb5/asn.1/asn1_encode.c
10  *
11  * Copyright 1994 by the Massachusetts Institute of Technology.
12  * All Rights Reserved.
13  *
14  * Export of this software from the United States of America may
15  *   require a specific license from the United States Government.
16  *   It is the responsibility of any person or organization contemplating
17  *   export to obtain such a license before exporting.
18  *
19  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20  * distribute this software and its documentation for any purpose and
21  * without fee is hereby granted, provided that the above copyright
22  * notice appear in all copies and that both that copyright notice and
23  * this permission notice appear in supporting documentation, and that
24  * the name of M.I.T. not be used in advertising or publicity pertaining
25  * to distribution of the software without specific, written prior
26  * permission.  Furthermore if you modify this software you must label
27  * your software as modified software and not distribute it in such a
28  * fashion that it might be confused with the original M.I.T. software.
29  * M.I.T. makes no representations about the suitability of
30  * this software for any purpose.  It is provided "as is" without express
31  * or implied warranty.
32  */
33 
34 /* ASN.1 primitive encoders */
35 
36 #include "asn1_encode.h"
37 #include "asn1_make.h"
38 
39 static asn1_error_code asn1_encode_integer_internal(asn1buf *buf,  long val,
40 						    unsigned int *retlen)
41 {
42   asn1_error_code retval;
43   unsigned int length = 0;
44   long valcopy;
45   int digit;
46 
47   valcopy = val;
48   do {
49     digit = (int) (valcopy&0xFF);
50     retval = asn1buf_insert_octet(buf,(asn1_octet) digit);
51     if(retval) return retval;
52     length++;
53     valcopy = valcopy >> 8;
54   } while (valcopy != 0 && valcopy != ~0);
55 
56   if((val > 0) && ((digit&0x80) == 0x80)) { /* make sure the high bit is */
57     retval = asn1buf_insert_octet(buf,0); /* of the proper signed-ness */
58     if(retval) return retval;
59     length++;
60   }else if((val < 0) && ((digit&0x80) != 0x80)){
61     retval = asn1buf_insert_octet(buf,0xFF);
62     if(retval) return retval;
63     length++;
64   }
65 
66 
67   *retlen = length;
68   return 0;
69 }
70 
71 asn1_error_code asn1_encode_integer(asn1buf * buf,  long val,
72  unsigned int *retlen)
73 {
74   asn1_error_code retval;
75   unsigned int length = 0;
76   unsigned  int partlen;
77   retval = asn1_encode_integer_internal(buf, val, &partlen);
78   if (retval) return retval;
79 
80   length = partlen;
81     retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen);
82   if(retval) return retval;
83   length += partlen;
84 
85   *retlen = length;
86   return 0;
87 }
88 
89 asn1_error_code
90 asn1_encode_enumerated(asn1buf * buf, const long val,
91 		       unsigned int *retlen)
92 {
93   asn1_error_code retval;
94   unsigned int length = 0;
95   unsigned  int partlen;
96   retval = asn1_encode_integer_internal(buf, val, &partlen);
97   if (retval) return retval;
98 
99   length = partlen;
100     retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_ENUMERATED,length, &partlen);
101   if(retval) return retval;
102   length += partlen;
103 
104   *retlen = length;
105   return 0;
106 }
107 
108 asn1_error_code asn1_encode_unsigned_integer(asn1buf *buf, unsigned long val,
109 					     unsigned int *retlen)
110 {
111   asn1_error_code retval;
112   unsigned int length = 0;
113   unsigned int partlen;
114   unsigned long valcopy;
115   int digit;
116 
117   valcopy = val;
118   do {
119     digit = (int) (valcopy&0xFF);
120     retval = asn1buf_insert_octet(buf,(asn1_octet) digit);
121     if(retval) return retval;
122     length++;
123     valcopy = valcopy >> 8;
124   } while (valcopy != 0 && valcopy != ~0);
125 
126   if(digit&0x80) {		          /* make sure the high bit is */
127     retval = asn1buf_insert_octet(buf,0); /* of the proper signed-ness */
128     if(retval) return retval;
129     length++;
130   }
131 
132   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_INTEGER,length, &partlen);
133   if(retval) return retval;
134   length += partlen;
135 
136   *retlen = length;
137   return 0;
138 }
139 
140 asn1_error_code asn1_encode_oid(asn1buf *buf, unsigned int len,
141 				const asn1_octet *val,
142 				unsigned int *retlen)
143 {
144   asn1_error_code retval;
145   unsigned int length;
146 
147   retval = asn1buf_insert_octetstring(buf, len, val);
148   if (retval) return retval;
149   retval = asn1_make_tag(buf, UNIVERSAL, PRIMITIVE, ASN1_OBJECTIDENTIFIER,
150 			 len, &length);
151   if (retval) return retval;
152 
153   *retlen = len + length;
154   return 0;
155 }
156 
157 asn1_error_code asn1_encode_octetstring(asn1buf *buf, unsigned int len,
158 					const asn1_octet *val,
159 					unsigned int *retlen)
160 {
161   asn1_error_code retval;
162   unsigned int length;
163 
164   retval = asn1buf_insert_octetstring(buf,len,val);
165   if(retval) return retval;
166   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_OCTETSTRING,len,&length);
167   if(retval) return retval;
168 
169   *retlen = len + length;
170   return 0;
171 }
172 
173 asn1_error_code asn1_encode_charstring(asn1buf *buf, unsigned int len,
174 				       const char *val, unsigned int *retlen)
175 {
176   asn1_error_code retval;
177   unsigned int length;
178 
179   retval = asn1buf_insert_charstring(buf,len,val);
180   if(retval) return retval;
181   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_OCTETSTRING,len,&length);
182   if(retval) return retval;
183 
184   *retlen = len + length;
185   return 0;
186 }
187 
188 asn1_error_code asn1_encode_null(asn1buf *buf, int *retlen)
189 {
190   asn1_error_code retval;
191 
192   retval = asn1buf_insert_octet(buf,0x00);
193   if(retval) return retval;
194   retval = asn1buf_insert_octet(buf,0x05);
195   if(retval) return retval;
196 
197   *retlen = 2;
198   return 0;
199 }
200 
201 asn1_error_code asn1_encode_printablestring(asn1buf *buf, unsigned int len,
202 					    const char *val, int *retlen)
203 {
204   asn1_error_code retval;
205   unsigned int length;
206 
207   retval = asn1buf_insert_charstring(buf,len,val);
208   if(retval) return retval;
209   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_PRINTABLESTRING,len,			 &length);
210   if(retval) return retval;
211 
212   *retlen = len + length;
213   return 0;
214 }
215 
216 asn1_error_code asn1_encode_ia5string(asn1buf *buf, unsigned int len,
217 				      const char *val, int *retlen)
218 {
219   asn1_error_code retval;
220   unsigned int length;
221 
222   retval = asn1buf_insert_charstring(buf,len,val);
223   if(retval) return retval;
224   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_IA5STRING,len,			 &length);
225   if(retval) return retval;
226 
227   *retlen = len + length;
228   return 0;
229 }
230 
231 asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val,
232 					unsigned int *retlen)
233 {
234   asn1_error_code retval;
235   struct tm *gtime, gtimebuf;
236   char s[16], *sp;
237   unsigned int length, sum=0;
238   time_t gmt_time = val;
239 
240   /*
241    * Time encoding: YYYYMMDDhhmmssZ
242    */
243   if (gmt_time == 0) {
244 	sp = "19700101000000Z";
245   } else {
246 
247 	/*
248         * Sanity check this just to be paranoid, as gmtime can return NULL,
249         * and some bogus implementations might overrun on the sprintf.
250         */
251 #ifdef HAVE_GMTIME_R
252 	if (gmtime_r(&gmt_time, &gtimebuf) == NULL)
253 		return ASN1_BAD_GMTIME;
254 #else
255 	gtime = gmtime(&gmt_time);
256 	if (gtime == NULL)
257 		return ASN1_BAD_GMTIME;
258 	memcpy(&gtimebuf, gtime, sizeof(gtimebuf));
259 #endif
260 	gtime = &gtimebuf;
261 
262 	if (gtime->tm_year > 8099 || gtime->tm_mon > 11 ||
263 	    gtime->tm_mday > 31 || gtime->tm_hour > 23 ||
264 	    gtime->tm_min > 59 || gtime->tm_sec > 59)
265 		return ASN1_BAD_GMTIME;
266 	sprintf(s, "%04d%02d%02d%02d%02d%02dZ",
267 		1900+gtime->tm_year, gtime->tm_mon+1, gtime->tm_mday,
268 		gtime->tm_hour, gtime->tm_min, gtime->tm_sec);
269 	sp = s;
270  }
271 
272   retval = asn1buf_insert_charstring(buf,15,sp);
273   if(retval) return retval;
274   sum = 15;
275 
276    retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_GENERALTIME,sum,&length);
277    if(retval) return retval;
278    sum += length;
279 
280    *retlen = sum;
281    return 0;
282 }
283 
284 asn1_error_code asn1_encode_generalstring(asn1buf *buf, unsigned int len,
285 					  const char *val,
286 					  unsigned int *retlen)
287 {
288   asn1_error_code retval;
289   unsigned int length;
290 
291   retval = asn1buf_insert_charstring(buf,len,val);
292   if(retval) return retval;
293   retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_GENERALSTRING,len,
294 			 &length);
295   if(retval) return retval;
296 
297   *retlen = len + length;
298   return 0;
299 }
300