xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/asn1/der_put.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: der_put.c,v 1.2 2017/01/28 21:31:45 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "der_locl.h"
37 
38 __RCSID("$NetBSD: der_put.c,v 1.2 2017/01/28 21:31:45 christos Exp $");
39 
40 /*
41  * All encoding functions take a pointer `p' to first position in
42  * which to write, from the right, `len' which means the maximum
43  * number of characters we are able to write.  The function returns
44  * the number of characters written in `size' (if non-NULL).
45  * The return value is 0 or an error.
46  */
47 
48 int
49 der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)
50 {
51     unsigned char *base = p;
52     unsigned val = *v;
53 
54     if (val) {
55 	while (len > 0 && val) {
56 	    *p-- = val % 256;
57 	    val /= 256;
58 	    --len;
59 	}
60 	if (val != 0)
61 	    return ASN1_OVERFLOW;
62 	else {
63 	    if(p[1] >= 128) {
64 		if(len < 1)
65 		    return ASN1_OVERFLOW;
66 		*p-- = 0;
67 	    }
68 	    *size = base - p;
69 	    return 0;
70 	}
71     } else if (len < 1)
72 	return ASN1_OVERFLOW;
73     else {
74 	*p    = 0;
75 	*size = 1;
76 	return 0;
77     }
78 }
79 
80 int
81 der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size)
82 {
83     unsigned char *base = p;
84     uint64_t val = *v;
85 
86     if (val) {
87        while (len > 0 && val) {
88            *p-- = val % 256;
89            val /= 256;
90            --len;
91        }
92        if (val != 0)
93            return ASN1_OVERFLOW;
94        else {
95            if(p[1] >= 128) {
96                if(len < 1)
97                    return ASN1_OVERFLOW;
98                *p-- = 0;
99            }
100            *size = base - p;
101            return 0;
102        }
103     } else if (len < 1)
104        return ASN1_OVERFLOW;
105     else {
106        *p    = 0;
107        *size = 1;
108        return 0;
109     }
110 }
111 
112 int
113 der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
114 {
115     unsigned char *base = p;
116     int val = *v;
117 
118     if(val >= 0) {
119 	do {
120 	    if(len < 1)
121 		return ASN1_OVERFLOW;
122 	    *p-- = val % 256;
123 	    len--;
124 	    val /= 256;
125 	} while(val);
126 	if(p[1] >= 128) {
127 	    if(len < 1)
128 		return ASN1_OVERFLOW;
129 	    *p-- = 0;
130 	    len--;
131 	}
132     } else {
133 	val = ~val;
134 	do {
135 	    if(len < 1)
136 		return ASN1_OVERFLOW;
137 	    *p-- = ~(val % 256);
138 	    len--;
139 	    val /= 256;
140 	} while(val);
141 	if(p[1] < 128) {
142 	    if(len < 1)
143 		return ASN1_OVERFLOW;
144 	    *p-- = 0xff;
145 	    len--;
146 	}
147     }
148     *size = base - p;
149     return 0;
150 }
151 
152 int
153 der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
154 {
155     unsigned char *base = p;
156     int64_t val = *v;
157 
158     if(val >= 0) {
159        do {
160            if(len < 1)
161                return ASN1_OVERFLOW;
162            *p-- = val % 256;
163            len--;
164            val /= 256;
165        } while(val);
166        if(p[1] >= 128) {
167            if(len < 1)
168                return ASN1_OVERFLOW;
169            *p-- = 0;
170            len--;
171        }
172     } else {
173        val = ~val;
174        do {
175            if(len < 1)
176                return ASN1_OVERFLOW;
177            *p-- = ~(val % 256);
178            len--;
179            val /= 256;
180        } while(val);
181        if(p[1] < 128) {
182            if(len < 1)
183                return ASN1_OVERFLOW;
184            *p-- = 0xff;
185            len--;
186        }
187     }
188     *size = base - p;
189     return 0;
190 }
191 
192 
193 int
194 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
195 {
196     if (len < 1)
197 	return ASN1_OVERFLOW;
198 
199     if (val < 128) {
200 	*p = val;
201 	*size = 1;
202     } else {
203 	size_t l = 0;
204 
205 	while(val > 0) {
206 	    if(len < 2)
207 		return ASN1_OVERFLOW;
208 	    *p-- = val % 256;
209 	    val /= 256;
210 	    len--;
211 	    l++;
212 	}
213 	*p = 0x80 | l;
214 	if(size)
215 	    *size = l + 1;
216     }
217     return 0;
218 }
219 
220 int
221 der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)
222 {
223     if(len < 1)
224 	return ASN1_OVERFLOW;
225     if(*data != 0)
226 	*p = 0xff;
227     else
228 	*p = 0;
229     *size = 1;
230     return 0;
231 }
232 
233 int
234 der_put_general_string (unsigned char *p, size_t len,
235 			const heim_general_string *str, size_t *size)
236 {
237     size_t slen = strlen(*str);
238 
239     if (len < slen)
240 	return ASN1_OVERFLOW;
241     p -= slen;
242     memcpy (p+1, *str, slen);
243     *size = slen;
244     return 0;
245 }
246 
247 int
248 der_put_utf8string (unsigned char *p, size_t len,
249 		    const heim_utf8_string *str, size_t *size)
250 {
251     return der_put_general_string(p, len, str, size);
252 }
253 
254 int
255 der_put_printable_string (unsigned char *p, size_t len,
256 			  const heim_printable_string *str, size_t *size)
257 {
258     return der_put_octet_string(p, len, str, size);
259 }
260 
261 int
262 der_put_ia5_string (unsigned char *p, size_t len,
263 		    const heim_ia5_string *str, size_t *size)
264 {
265     return der_put_octet_string(p, len, str, size);
266 }
267 
268 int
269 der_put_bmp_string (unsigned char *p, size_t len,
270 		    const heim_bmp_string *data, size_t *size)
271 {
272     size_t i;
273     if (len / 2 < data->length)
274 	return ASN1_OVERFLOW;
275     p -= data->length * 2;
276     for (i = 0; i < data->length; i++) {
277 	p[1] = (data->data[i] >> 8) & 0xff;
278 	p[2] = data->data[i] & 0xff;
279 	p += 2;
280     }
281     if (size) *size = data->length * 2;
282     return 0;
283 }
284 
285 int
286 der_put_universal_string (unsigned char *p, size_t len,
287 			  const heim_universal_string *data, size_t *size)
288 {
289     size_t i;
290     if (len / 4 < data->length)
291 	return ASN1_OVERFLOW;
292     p -= data->length * 4;
293     for (i = 0; i < data->length; i++) {
294 	p[1] = (data->data[i] >> 24) & 0xff;
295 	p[2] = (data->data[i] >> 16) & 0xff;
296 	p[3] = (data->data[i] >> 8) & 0xff;
297 	p[4] = data->data[i] & 0xff;
298 	p += 4;
299     }
300     if (size) *size = data->length * 4;
301     return 0;
302 }
303 
304 int
305 der_put_visible_string (unsigned char *p, size_t len,
306 			 const heim_visible_string *str, size_t *size)
307 {
308     return der_put_general_string(p, len, str, size);
309 }
310 
311 int
312 der_put_octet_string (unsigned char *p, size_t len,
313 		      const heim_octet_string *data, size_t *size)
314 {
315     if (len < data->length)
316 	return ASN1_OVERFLOW;
317     p -= data->length;
318     memcpy (p+1, data->data, data->length);
319     *size = data->length;
320     return 0;
321 }
322 
323 int
324 der_put_heim_integer (unsigned char *p, size_t len,
325 		     const heim_integer *data, size_t *size)
326 {
327     unsigned char *buf = data->data;
328     int hibitset = 0;
329 
330     if (data->length == 0) {
331 	if (len < 1)
332 	    return ASN1_OVERFLOW;
333 	*p-- = 0;
334 	if (size)
335 	    *size = 1;
336 	return 0;
337     }
338     if (len < data->length)
339 	return ASN1_OVERFLOW;
340 
341     len -= data->length;
342 
343     if (data->negative) {
344 	ssize_t i;
345 	int carry;
346 	for (i = data->length - 1, carry = 1; i >= 0; i--) {
347 	    *p = buf[i] ^ 0xff;
348 	    if (carry)
349 		carry = !++*p;
350 	    p--;
351 	}
352 	if (p[1] < 128) {
353 	    if (len < 1)
354 		return ASN1_OVERFLOW;
355 	    *p-- = 0xff;
356 	    len--;
357 	    hibitset = 1;
358 	}
359     } else {
360 	p -= data->length;
361 	memcpy(p + 1, buf, data->length);
362 
363 	if (p[1] >= 128) {
364 	    if (len < 1)
365 		return ASN1_OVERFLOW;
366 	    p[0] = 0;
367 	    len--;
368 	    hibitset = 1;
369 	}
370     }
371     if (size)
372 	*size = data->length + hibitset;
373     return 0;
374 }
375 
376 int
377 der_put_generalized_time (unsigned char *p, size_t len,
378 			  const time_t *data, size_t *size)
379 {
380     heim_octet_string k;
381     size_t l;
382     int e;
383 
384     e = _heim_time2generalizedtime (*data, &k, 1);
385     if (e)
386 	return e;
387     e = der_put_octet_string(p, len, &k, &l);
388     free(k.data);
389     if(e)
390 	return e;
391     if(size)
392 	*size = l;
393     return 0;
394 }
395 
396 int
397 der_put_utctime (unsigned char *p, size_t len,
398 		 const time_t *data, size_t *size)
399 {
400     heim_octet_string k;
401     size_t l;
402     int e;
403 
404     e = _heim_time2generalizedtime (*data, &k, 0);
405     if (e)
406 	return e;
407     e = der_put_octet_string(p, len, &k, &l);
408     free(k.data);
409     if(e)
410 	return e;
411     if(size)
412 	*size = l;
413     return 0;
414 }
415 
416 int
417 der_put_oid (unsigned char *p, size_t len,
418 	     const heim_oid *data, size_t *size)
419 {
420     unsigned char *base = p;
421     size_t n;
422 
423     for (n = data->length - 1; n >= 2; --n) {
424 	unsigned u = data->components[n];
425 
426 	if (len < 1)
427 	    return ASN1_OVERFLOW;
428 	*p-- = u % 128;
429 	u /= 128;
430 	--len;
431 	while (u > 0) {
432 	    if (len < 1)
433 		return ASN1_OVERFLOW;
434 	    *p-- = 128 + u % 128;
435 	    u /= 128;
436 	    --len;
437 	}
438     }
439     if (len < 1)
440 	return ASN1_OVERFLOW;
441     *p-- = 40 * data->components[0] + data->components[1];
442     *size = base - p;
443     return 0;
444 }
445 
446 int
447 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
448 	     unsigned int tag, size_t *size)
449 {
450     if (tag <= 30) {
451 	if (len < 1)
452 	    return ASN1_OVERFLOW;
453 	*p = MAKE_TAG(class, type, tag);
454 	*size = 1;
455     } else {
456 	size_t ret = 0;
457 	unsigned int continuation = 0;
458 
459 	do {
460 	    if (len < 1)
461 		return ASN1_OVERFLOW;
462 	    *p-- = tag % 128 | continuation;
463 	    len--;
464 	    ret++;
465 	    tag /= 128;
466 	    continuation = 0x80;
467 	} while(tag > 0);
468 	if (len < 1)
469 	    return ASN1_OVERFLOW;
470 	*p-- = MAKE_TAG(class, type, 0x1f);
471 	ret++;
472 	*size = ret;
473     }
474     return 0;
475 }
476 
477 int
478 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
479 			Der_class class, Der_type type,
480 			unsigned int tag, size_t *size)
481 {
482     size_t ret = 0;
483     size_t l;
484     int e;
485 
486     e = der_put_length (p, len, len_val, &l);
487     if(e)
488 	return e;
489     p -= l;
490     len -= l;
491     ret += l;
492     e = der_put_tag (p, len, class, type, tag, &l);
493     if(e)
494 	return e;
495 
496     ret += l;
497     *size = ret;
498     return 0;
499 }
500 
501 int
502 _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)
503 {
504      struct tm tm;
505      const size_t len = gtimep ? 15 : 13;
506 
507      s->data = NULL;
508      s->length = 0;
509      if (_der_gmtime(t, &tm) == NULL)
510 	 return ASN1_BAD_TIMEFORMAT;
511      s->data = malloc(len + 1);
512      if (s->data == NULL)
513 	 return ENOMEM;
514      s->length = len;
515      if (gtimep)
516 	 snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
517 		   tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
518 		   tm.tm_hour, tm.tm_min, tm.tm_sec);
519      else
520 	 snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",
521 		   tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
522 		   tm.tm_hour, tm.tm_min, tm.tm_sec);
523 
524      return 0;
525 }
526 
527 int
528 der_put_bit_string (unsigned char *p, size_t len,
529 		    const heim_bit_string *data, size_t *size)
530 {
531     size_t data_size = (data->length + 7) / 8;
532     if (len < data_size + 1)
533 	return ASN1_OVERFLOW;
534     p -= data_size + 1;
535 
536     memcpy (p+2, data->data, data_size);
537     if (data->length && (data->length % 8) != 0)
538 	p[1] = 8 - (data->length % 8);
539     else
540 	p[1] = 0;
541     *size = data_size + 1;
542     return 0;
543 }
544 
545 int
546 _heim_der_set_sort(const void *a1, const void *a2)
547 {
548     const heim_octet_string *s1 = a1, *s2 = a2;
549     int ret;
550 
551     ret = memcmp(s1->data, s2->data,
552 		 s1->length < s2->length ? s1->length : s2->length);
553     if(ret)
554 	return ret;
555     return (int)(s1->length - s2->length);
556 }
557