fix memset
[heimdal.git] / lib / asn1 / der_put.c
blob0ccb181c0b3910bfcf5640442e8ac7645a77947b
1 /*
2 * Copyright (c) 1997-2005 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$");
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 int
47 der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)
49 unsigned char *base = p;
50 unsigned val = *v;
52 if (val) {
53 while (len > 0 && val) {
54 *p-- = val % 256;
55 val /= 256;
56 --len;
58 if (val != 0)
59 return ASN1_OVERFLOW;
60 else {
61 if(p[1] >= 128) {
62 if(len < 1)
63 return ASN1_OVERFLOW;
64 *p-- = 0;
66 *size = base - p;
67 return 0;
69 } else if (len < 1)
70 return ASN1_OVERFLOW;
71 else {
72 *p = 0;
73 *size = 1;
74 return 0;
78 int
79 der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size)
81 unsigned char *base = p;
82 uint64_t val = *v;
84 if (val) {
85 while (len > 0 && val) {
86 *p-- = val % 256;
87 val /= 256;
88 --len;
90 if (val != 0)
91 return ASN1_OVERFLOW;
92 else {
93 if(p[1] >= 128) {
94 if(len < 1)
95 return ASN1_OVERFLOW;
96 *p-- = 0;
98 *size = base - p;
99 return 0;
101 } else if (len < 1)
102 return ASN1_OVERFLOW;
103 else {
104 *p = 0;
105 *size = 1;
106 return 0;
111 der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
113 unsigned char *base = p;
114 int val = *v;
116 if(val >= 0) {
117 do {
118 if(len < 1)
119 return ASN1_OVERFLOW;
120 *p-- = val % 256;
121 len--;
122 val /= 256;
123 } while(val);
124 if(p[1] >= 128) {
125 if(len < 1)
126 return ASN1_OVERFLOW;
127 *p-- = 0;
128 len--;
130 } else {
131 val = ~val;
132 do {
133 if(len < 1)
134 return ASN1_OVERFLOW;
135 *p-- = ~(val % 256);
136 len--;
137 val /= 256;
138 } while(val);
139 if(p[1] < 128) {
140 if(len < 1)
141 return ASN1_OVERFLOW;
142 *p-- = 0xff;
143 len--;
146 *size = base - p;
147 return 0;
151 der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
153 unsigned char *base = p;
154 int64_t val = *v;
156 if(val >= 0) {
157 do {
158 if(len < 1)
159 return ASN1_OVERFLOW;
160 *p-- = val % 256;
161 len--;
162 val /= 256;
163 } while(val);
164 if(p[1] >= 128) {
165 if(len < 1)
166 return ASN1_OVERFLOW;
167 *p-- = 0;
168 len--;
170 } else {
171 val = ~val;
172 do {
173 if(len < 1)
174 return ASN1_OVERFLOW;
175 *p-- = ~(val % 256);
176 len--;
177 val /= 256;
178 } while(val);
179 if(p[1] < 128) {
180 if(len < 1)
181 return ASN1_OVERFLOW;
182 *p-- = 0xff;
183 len--;
186 *size = base - p;
187 return 0;
192 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
194 if (len < 1)
195 return ASN1_OVERFLOW;
197 if (val < 128) {
198 *p = val;
199 *size = 1;
200 } else {
201 size_t l = 0;
203 while(val > 0) {
204 if(len < 2)
205 return ASN1_OVERFLOW;
206 *p-- = val % 256;
207 val /= 256;
208 len--;
209 l++;
211 *p = 0x80 | l;
212 if(size)
213 *size = l + 1;
215 return 0;
219 der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)
221 if(len < 1)
222 return ASN1_OVERFLOW;
223 if(*data != 0)
224 *p = 0xff;
225 else
226 *p = 0;
227 *size = 1;
228 return 0;
232 der_put_general_string (unsigned char *p, size_t len,
233 const heim_general_string *str, size_t *size)
235 size_t slen = strlen(*str);
237 if (len < slen)
238 return ASN1_OVERFLOW;
239 p -= slen;
240 memcpy (p+1, *str, slen);
241 *size = slen;
242 return 0;
246 der_put_utf8string (unsigned char *p, size_t len,
247 const heim_utf8_string *str, size_t *size)
249 return der_put_general_string(p, len, str, size);
253 der_put_printable_string (unsigned char *p, size_t len,
254 const heim_printable_string *str, size_t *size)
256 return der_put_octet_string(p, len, str, size);
260 der_put_ia5_string (unsigned char *p, size_t len,
261 const heim_ia5_string *str, size_t *size)
263 return der_put_octet_string(p, len, str, size);
267 der_put_bmp_string (unsigned char *p, size_t len,
268 const heim_bmp_string *data, size_t *size)
270 size_t i;
271 if (len / 2 < data->length)
272 return ASN1_OVERFLOW;
273 p -= data->length * 2;
274 for (i = 0; i < data->length; i++) {
275 p[1] = (data->data[i] >> 8) & 0xff;
276 p[2] = data->data[i] & 0xff;
277 p += 2;
279 if (size) *size = data->length * 2;
280 return 0;
284 der_put_universal_string (unsigned char *p, size_t len,
285 const heim_universal_string *data, size_t *size)
287 size_t i;
288 if (len / 4 < data->length)
289 return ASN1_OVERFLOW;
290 p -= data->length * 4;
291 for (i = 0; i < data->length; i++) {
292 p[1] = (data->data[i] >> 24) & 0xff;
293 p[2] = (data->data[i] >> 16) & 0xff;
294 p[3] = (data->data[i] >> 8) & 0xff;
295 p[4] = data->data[i] & 0xff;
296 p += 4;
298 if (size) *size = data->length * 4;
299 return 0;
303 der_put_visible_string (unsigned char *p, size_t len,
304 const heim_visible_string *str, size_t *size)
306 return der_put_general_string(p, len, str, size);
310 der_put_octet_string (unsigned char *p, size_t len,
311 const heim_octet_string *data, size_t *size)
313 if (len < data->length)
314 return ASN1_OVERFLOW;
315 p -= data->length;
316 memcpy (p+1, data->data, data->length);
317 *size = data->length;
318 return 0;
322 der_put_heim_integer (unsigned char *p, size_t len,
323 const heim_integer *data, size_t *size)
325 unsigned char *buf = data->data;
326 int hibitset = 0;
328 if (data->length == 0) {
329 if (len < 1)
330 return ASN1_OVERFLOW;
331 *p-- = 0;
332 if (size)
333 *size = 1;
334 return 0;
336 if (len < data->length)
337 return ASN1_OVERFLOW;
339 len -= data->length;
341 if (data->negative) {
342 int i, carry;
343 for (i = data->length - 1, carry = 1; i >= 0; i--) {
344 *p = buf[i] ^ 0xff;
345 if (carry)
346 carry = !++*p;
347 p--;
349 if (p[1] < 128) {
350 if (len < 1)
351 return ASN1_OVERFLOW;
352 *p-- = 0xff;
353 len--;
354 hibitset = 1;
356 } else {
357 p -= data->length;
358 memcpy(p + 1, buf, data->length);
360 if (p[1] >= 128) {
361 if (len < 1)
362 return ASN1_OVERFLOW;
363 p[0] = 0;
364 len--;
365 hibitset = 1;
368 if (size)
369 *size = data->length + hibitset;
370 return 0;
374 der_put_generalized_time (unsigned char *p, size_t len,
375 const time_t *data, size_t *size)
377 heim_octet_string k;
378 size_t l;
379 int e;
381 e = _heim_time2generalizedtime (*data, &k, 1);
382 if (e)
383 return e;
384 e = der_put_octet_string(p, len, &k, &l);
385 free(k.data);
386 if(e)
387 return e;
388 if(size)
389 *size = l;
390 return 0;
394 der_put_utctime (unsigned char *p, size_t len,
395 const time_t *data, size_t *size)
397 heim_octet_string k;
398 size_t l;
399 int e;
401 e = _heim_time2generalizedtime (*data, &k, 0);
402 if (e)
403 return e;
404 e = der_put_octet_string(p, len, &k, &l);
405 free(k.data);
406 if(e)
407 return e;
408 if(size)
409 *size = l;
410 return 0;
414 der_put_oid (unsigned char *p, size_t len,
415 const heim_oid *data, size_t *size)
417 unsigned char *base = p;
418 int n;
420 for (n = data->length - 1; n >= 2; --n) {
421 unsigned u = data->components[n];
423 if (len < 1)
424 return ASN1_OVERFLOW;
425 *p-- = u % 128;
426 u /= 128;
427 --len;
428 while (u > 0) {
429 if (len < 1)
430 return ASN1_OVERFLOW;
431 *p-- = 128 + u % 128;
432 u /= 128;
433 --len;
436 if (len < 1)
437 return ASN1_OVERFLOW;
438 *p-- = 40 * data->components[0] + data->components[1];
439 *size = base - p;
440 return 0;
444 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
445 unsigned int tag, size_t *size)
447 if (tag <= 30) {
448 if (len < 1)
449 return ASN1_OVERFLOW;
450 *p = MAKE_TAG(class, type, tag);
451 *size = 1;
452 } else {
453 size_t ret = 0;
454 unsigned int continuation = 0;
456 do {
457 if (len < 1)
458 return ASN1_OVERFLOW;
459 *p-- = tag % 128 | continuation;
460 len--;
461 ret++;
462 tag /= 128;
463 continuation = 0x80;
464 } while(tag > 0);
465 if (len < 1)
466 return ASN1_OVERFLOW;
467 *p-- = MAKE_TAG(class, type, 0x1f);
468 ret++;
469 *size = ret;
471 return 0;
475 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
476 Der_class class, Der_type type,
477 unsigned int tag, size_t *size)
479 size_t ret = 0;
480 size_t l;
481 int e;
483 e = der_put_length (p, len, len_val, &l);
484 if(e)
485 return e;
486 p -= l;
487 len -= l;
488 ret += l;
489 e = der_put_tag (p, len, class, type, tag, &l);
490 if(e)
491 return e;
493 ret += l;
494 *size = ret;
495 return 0;
499 _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)
501 struct tm tm;
502 const size_t len = gtimep ? 15 : 13;
504 s->data = malloc(len + 1);
505 if (s->data == NULL)
506 return ENOMEM;
507 s->length = len;
508 if (_der_gmtime(t, &tm) == NULL)
509 return ASN1_BAD_TIMEFORMAT;
510 if (gtimep)
511 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
512 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
513 tm.tm_hour, tm.tm_min, tm.tm_sec);
514 else
515 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",
516 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
517 tm.tm_hour, tm.tm_min, tm.tm_sec);
519 return 0;
523 der_put_bit_string (unsigned char *p, size_t len,
524 const heim_bit_string *data, size_t *size)
526 size_t data_size = (data->length + 7) / 8;
527 if (len < data_size + 1)
528 return ASN1_OVERFLOW;
529 p -= data_size + 1;
531 memcpy (p+2, data->data, data_size);
532 if (data->length && (data->length % 8) != 0)
533 p[1] = 8 - (data->length % 8);
534 else
535 p[1] = 0;
536 *size = data_size + 1;
537 return 0;
541 _heim_der_set_sort(const void *a1, const void *a2)
543 const struct heim_octet_string *s1 = a1, *s2 = a2;
544 int ret;
546 ret = memcmp(s1->data, s2->data,
547 s1->length < s2->length ? s1->length : s2->length);
548 if(ret)
549 return ret;
550 return s1->length - s2->length;