remove gcc34
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / asn1 / der_put.c
blob41733c57b3f865bb6fe6f57dc1652a655eff9c2b
1 /*
2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "der_locl.h"
36 RCSID("$Id: der_put.c,v 1.28 2003/04/17 07:12:24 lha Exp $");
39 * All encoding functions take a pointer `p' to first position in
40 * which to write, from the right, `len' which means the maximum
41 * number of characters we are able to write. The function returns
42 * the number of characters written in `size' (if non-NULL).
43 * The return value is 0 or an error.
46 static int
47 der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size)
49 unsigned char *base = p;
51 if (val) {
52 while (len > 0 && val) {
53 *p-- = val % 256;
54 val /= 256;
55 --len;
57 if (val != 0)
58 return ASN1_OVERFLOW;
59 else {
60 *size = base - p;
61 return 0;
63 } else if (len < 1)
64 return ASN1_OVERFLOW;
65 else {
66 *p = 0;
67 *size = 1;
68 return 0;
72 int
73 der_put_int (unsigned char *p, size_t len, int val, size_t *size)
75 unsigned char *base = p;
77 if(val >= 0) {
78 do {
79 if(len < 1)
80 return ASN1_OVERFLOW;
81 *p-- = val % 256;
82 len--;
83 val /= 256;
84 } while(val);
85 if(p[1] >= 128) {
86 if(len < 1)
87 return ASN1_OVERFLOW;
88 *p-- = 0;
89 len--;
91 } else {
92 val = ~val;
93 do {
94 if(len < 1)
95 return ASN1_OVERFLOW;
96 *p-- = ~(val % 256);
97 len--;
98 val /= 256;
99 } while(val);
100 if(p[1] < 128) {
101 if(len < 1)
102 return ASN1_OVERFLOW;
103 *p-- = 0xff;
104 len--;
107 *size = base - p;
108 return 0;
113 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
115 if (len < 1)
116 return ASN1_OVERFLOW;
117 if (val < 128) {
118 *p = val;
119 *size = 1;
120 return 0;
121 } else {
122 size_t l;
123 int e;
125 e = der_put_unsigned (p, len - 1, val, &l);
126 if (e)
127 return e;
128 p -= l;
129 *p = 0x80 | l;
130 *size = l + 1;
131 return 0;
136 der_put_general_string (unsigned char *p, size_t len,
137 const general_string *str, size_t *size)
139 size_t slen = strlen(*str);
141 if (len < slen)
142 return ASN1_OVERFLOW;
143 p -= slen;
144 len -= slen;
145 memcpy (p+1, *str, slen);
146 *size = slen;
147 return 0;
151 der_put_octet_string (unsigned char *p, size_t len,
152 const octet_string *data, size_t *size)
154 if (len < data->length)
155 return ASN1_OVERFLOW;
156 p -= data->length;
157 len -= data->length;
158 memcpy (p+1, data->data, data->length);
159 *size = data->length;
160 return 0;
164 der_put_oid (unsigned char *p, size_t len,
165 const oid *data, size_t *size)
167 unsigned char *base = p;
168 int n;
170 for (n = data->length - 1; n >= 2; --n) {
171 unsigned u = data->components[n];
173 if (len < 1)
174 return ASN1_OVERFLOW;
175 *p-- = u % 128;
176 u /= 128;
177 --len;
178 while (u > 0) {
179 if (len < 1)
180 return ASN1_OVERFLOW;
181 *p-- = 128 + u % 128;
182 u /= 128;
183 --len;
186 if (len < 1)
187 return ASN1_OVERFLOW;
188 *p-- = 40 * data->components[0] + data->components[1];
189 *size = base - p;
190 return 0;
194 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
195 int tag, size_t *size)
197 if (len < 1)
198 return ASN1_OVERFLOW;
199 *p = (class << 6) | (type << 5) | tag; /* XXX */
200 *size = 1;
201 return 0;
205 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
206 Der_class class, Der_type type, int tag, size_t *size)
208 size_t ret = 0;
209 size_t l;
210 int e;
212 e = der_put_length (p, len, len_val, &l);
213 if(e)
214 return e;
215 p -= l;
216 len -= l;
217 ret += l;
218 e = der_put_tag (p, len, class, type, tag, &l);
219 if(e)
220 return e;
221 p -= l;
222 len -= l;
223 ret += l;
224 *size = ret;
225 return 0;
229 encode_integer (unsigned char *p, size_t len, const int *data, size_t *size)
231 int num = *data;
232 size_t ret = 0;
233 size_t l;
234 int e;
236 e = der_put_int (p, len, num, &l);
237 if(e)
238 return e;
239 p -= l;
240 len -= l;
241 ret += l;
242 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l);
243 if (e)
244 return e;
245 p -= l;
246 len -= l;
247 ret += l;
248 *size = ret;
249 return 0;
253 encode_unsigned (unsigned char *p, size_t len, const unsigned *data,
254 size_t *size)
256 unsigned num = *data;
257 size_t ret = 0;
258 size_t l;
259 int e;
261 e = der_put_unsigned (p, len, num, &l);
262 if(e)
263 return e;
264 p -= l;
265 len -= l;
266 ret += l;
267 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l);
268 if (e)
269 return e;
270 p -= l;
271 len -= l;
272 ret += l;
273 *size = ret;
274 return 0;
278 encode_enumerated (unsigned char *p, size_t len, const unsigned *data,
279 size_t *size)
281 unsigned num = *data;
282 size_t ret = 0;
283 size_t l;
284 int e;
286 e = der_put_int (p, len, num, &l);
287 if(e)
288 return e;
289 p -= l;
290 len -= l;
291 ret += l;
292 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Enumerated, &l);
293 if (e)
294 return e;
295 p -= l;
296 len -= l;
297 ret += l;
298 *size = ret;
299 return 0;
303 encode_general_string (unsigned char *p, size_t len,
304 const general_string *data, size_t *size)
306 size_t ret = 0;
307 size_t l;
308 int e;
310 e = der_put_general_string (p, len, data, &l);
311 if (e)
312 return e;
313 p -= l;
314 len -= l;
315 ret += l;
316 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_GeneralString, &l);
317 if (e)
318 return e;
319 p -= l;
320 len -= l;
321 ret += l;
322 *size = ret;
323 return 0;
327 encode_octet_string (unsigned char *p, size_t len,
328 const octet_string *k, size_t *size)
330 size_t ret = 0;
331 size_t l;
332 int e;
334 e = der_put_octet_string (p, len, k, &l);
335 if (e)
336 return e;
337 p -= l;
338 len -= l;
339 ret += l;
340 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OctetString, &l);
341 if (e)
342 return e;
343 p -= l;
344 len -= l;
345 ret += l;
346 *size = ret;
347 return 0;
351 encode_oid(unsigned char *p, size_t len,
352 const oid *k, size_t *size)
354 size_t ret = 0;
355 size_t l;
356 int e;
358 e = der_put_oid (p, len, k, &l);
359 if (e)
360 return e;
361 p -= l;
362 len -= l;
363 ret += l;
364 e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OID, &l);
365 if (e)
366 return e;
367 p -= l;
368 len -= l;
369 ret += l;
370 *size = ret;
371 return 0;
375 time2generalizedtime (time_t t, octet_string *s)
377 struct tm *tm;
378 size_t len;
380 len = 15;
382 s->data = malloc(len + 1);
383 if (s->data == NULL)
384 return ENOMEM;
385 s->length = len;
386 tm = gmtime (&t);
387 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
388 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
389 tm->tm_hour, tm->tm_min, tm->tm_sec);
390 return 0;
394 encode_generalized_time (unsigned char *p, size_t len,
395 const time_t *t, size_t *size)
397 size_t ret = 0;
398 size_t l;
399 octet_string k;
400 int e;
402 e = time2generalizedtime (*t, &k);
403 if (e)
404 return e;
405 e = der_put_octet_string (p, len, &k, &l);
406 free (k.data);
407 if (e)
408 return e;
409 p -= l;
410 len -= l;
411 ret += l;
412 e = der_put_length_and_tag (p, len, k.length, UNIV, PRIM,
413 UT_GeneralizedTime, &l);
414 if (e)
415 return e;
416 p -= l;
417 len -= l;
418 ret += l;
419 *size = ret;
420 return 0;