]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/asn1/asn1.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libstrongswan / asn1 / asn1.c
1 /*
2 * Copyright (C) 2006 Martin Will
3 * Copyright (C) 2000-2016 Andreas Steffen
4 *
5 *
6 * Copyright (C) secunet Security Networks AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <time.h>
22
23 #include <utils/debug.h>
24
25 #include "oid.h"
26 #include "asn1.h"
27 #include "asn1_parser.h"
28
29 /**
30 * Commonly used ASN1 values.
31 */
32 const chunk_t ASN1_INTEGER_0 = chunk_from_chars(0x02, 0x01, 0x00);
33 const chunk_t ASN1_INTEGER_1 = chunk_from_chars(0x02, 0x01, 0x01);
34 const chunk_t ASN1_INTEGER_2 = chunk_from_chars(0x02, 0x01, 0x02);
35
36 /*
37 * Described in header
38 */
39 chunk_t asn1_algorithmIdentifier_params(int oid, chunk_t params)
40 {
41 return asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(oid), params);
42 }
43
44 /*
45 * Described in header
46 */
47 chunk_t asn1_algorithmIdentifier(int oid)
48 {
49 chunk_t parameters;
50
51 /* some algorithmIdentifiers have a NULL parameters field and some do not */
52 switch (oid)
53 {
54 case OID_ECDSA_WITH_SHA1:
55 case OID_ECDSA_WITH_SHA224:
56 case OID_ECDSA_WITH_SHA256:
57 case OID_ECDSA_WITH_SHA384:
58 case OID_ECDSA_WITH_SHA512:
59 case OID_ED25519:
60 case OID_ED448:
61 parameters = chunk_empty;
62 break;
63 default:
64 parameters = asn1_simple_object(ASN1_NULL, chunk_empty);
65 break;
66 }
67 return asn1_algorithmIdentifier_params(oid, parameters);
68 }
69
70 /*
71 * Defined in header.
72 */
73 int asn1_known_oid(chunk_t object)
74 {
75 int oid = 0;
76
77 while (object.len)
78 {
79 if (oid_names[oid].octet == *object.ptr)
80 {
81 if (--object.len == 0 || oid_names[oid].down == 0)
82 {
83 return oid; /* found terminal symbol */
84 }
85 else
86 {
87 object.ptr++; oid++; /* advance to next hex octet */
88 }
89 }
90 else
91 {
92 if (oid_names[oid].next)
93 {
94 oid = oid_names[oid].next;
95 }
96 else
97 {
98 return OID_UNKNOWN;
99 }
100 }
101 }
102 return OID_UNKNOWN;
103 }
104
105 /*
106 * Defined in header.
107 */
108 chunk_t asn1_build_known_oid(int n)
109 {
110 chunk_t oid;
111 int i;
112
113 if (n < 0 || n >= OID_MAX)
114 {
115 return chunk_empty;
116 }
117
118 i = oid_names[n].level + 1;
119 oid = chunk_alloc(2 + i);
120 oid.ptr[0] = ASN1_OID;
121 oid.ptr[1] = i;
122
123 do
124 {
125 if (oid_names[n].level >= i)
126 {
127 n--;
128 continue;
129 }
130 oid.ptr[--i + 2] = oid_names[n--].octet;
131 }
132 while (i > 0);
133
134 return oid;
135 }
136
137 /**
138 * Returns the number of bytes required to encode the given OID node
139 */
140 static int bytes_required(u_int val)
141 {
142 int shift, required = 1;
143
144 /* sufficient to handle 32 bit node numbers */
145 for (shift = 28; shift; shift -= 7)
146 {
147 if (val >> shift)
148 { /* do not encode leading zeroes */
149 required++;
150 }
151 }
152 return required;
153 }
154
155 /*
156 * Defined in header.
157 */
158 chunk_t asn1_oid_from_string(char *str)
159 {
160 enumerator_t *enumerator;
161 size_t buf_len = 64;
162 u_char buf[buf_len];
163 char *end;
164 int i = 0, pos = 0, req, shift;
165 u_int val, first = 0;
166
167 enumerator = enumerator_create_token(str, ".", "");
168 while (enumerator->enumerate(enumerator, &str))
169 {
170 val = strtoul(str, &end, 10);
171 req = bytes_required(val);
172 if (end == str || pos + req > buf_len)
173 {
174 pos = 0;
175 break;
176 }
177 switch (i++)
178 {
179 case 0:
180 first = val;
181 break;
182 case 1:
183 buf[pos++] = first * 40 + val;
184 break;
185 default:
186 for (shift = (req - 1) * 7; shift; shift -= 7)
187 {
188 buf[pos++] = 0x80 | ((val >> shift) & 0x7F);
189 }
190 buf[pos++] = val & 0x7F;
191 }
192 }
193 enumerator->destroy(enumerator);
194
195 return chunk_clone(chunk_create(buf, pos));
196 }
197
198 /*
199 * Defined in header.
200 */
201 char *asn1_oid_to_string(chunk_t oid)
202 {
203 size_t len = 64;
204 char buf[len], *pos = buf;
205 int written;
206 u_int val;
207
208 if (!oid.len)
209 {
210 return NULL;
211 }
212 val = oid.ptr[0] / 40;
213 written = snprintf(buf, len, "%u.%u", val, oid.ptr[0] - val * 40);
214 oid = chunk_skip(oid, 1);
215 if (written < 0 || written >= len)
216 {
217 return NULL;
218 }
219 pos += written;
220 len -= written;
221 val = 0;
222
223 while (oid.len)
224 {
225 val = (val << 7) + (u_int)(oid.ptr[0] & 0x7f);
226
227 if (oid.ptr[0] < 128)
228 {
229 written = snprintf(pos, len, ".%u", val);
230 if (written < 0 || written >= len)
231 {
232 return NULL;
233 }
234 pos += written;
235 len -= written;
236 val = 0;
237 }
238 oid = chunk_skip(oid, 1);
239 }
240 return (val == 0) ? strdup(buf) : NULL;
241 }
242
243 /*
244 * Defined in header.
245 */
246 size_t asn1_length(chunk_t *blob)
247 {
248 u_char n;
249 size_t len;
250
251 if (blob->len < 2)
252 {
253 DBG2(DBG_ASN, "insufficient number of octets to parse ASN.1 length");
254 return ASN1_INVALID_LENGTH;
255 }
256
257 /* read length field, skip tag and length */
258 n = blob->ptr[1];
259 blob->ptr += 2;
260 blob->len -= 2;
261
262 if ((n & 0x80) == 0)
263 { /* single length octet */
264 if (n > blob->len)
265 {
266 DBG2(DBG_ASN, "length is larger than remaining blob size");
267 return ASN1_INVALID_LENGTH;
268 }
269 return n;
270 }
271
272 /* composite length, determine number of length octets */
273 n &= 0x7f;
274
275 if (n == 0 || n > blob->len)
276 {
277 DBG2(DBG_ASN, "number of length octets invalid");
278 return ASN1_INVALID_LENGTH;
279 }
280
281 if (n > sizeof(len))
282 {
283 DBG2(DBG_ASN, "number of length octets is larger than limit of"
284 " %d octets", (int)sizeof(len));
285 return ASN1_INVALID_LENGTH;
286 }
287
288 len = 0;
289
290 while (n-- > 0)
291 {
292 len = 256*len + *blob->ptr++;
293 blob->len--;
294 }
295 if (len > blob->len)
296 {
297 DBG2(DBG_ASN, "length is larger than remaining blob size");
298 return ASN1_INVALID_LENGTH;
299 }
300 return len;
301 }
302
303 /*
304 * See header.
305 */
306 int asn1_unwrap(chunk_t *blob, chunk_t *inner)
307 {
308 chunk_t res;
309 u_char len;
310 int type;
311
312 if (blob->len < 2)
313 {
314 return ASN1_INVALID;
315 }
316 type = blob->ptr[0];
317 len = blob->ptr[1];
318 *blob = chunk_skip(*blob, 2);
319
320 if ((len & 0x80) == 0)
321 { /* single length octet */
322 res.len = len;
323 }
324 else
325 { /* composite length, determine number of length octets */
326 len &= 0x7f;
327 if (len == 0 || len > blob->len || len > sizeof(res.len))
328 {
329 return ASN1_INVALID;
330 }
331 res.len = 0;
332 while (len-- > 0)
333 {
334 res.len = 256 * res.len + blob->ptr[0];
335 *blob = chunk_skip(*blob, 1);
336 }
337 }
338 if (res.len > blob->len)
339 {
340 return ASN1_INVALID;
341 }
342 res.ptr = blob->ptr;
343 *blob = chunk_skip(*blob, res.len);
344 /* updating inner not before we are finished allows a caller to pass
345 * blob = inner */
346 *inner = res;
347 return type;
348 }
349
350 static const int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
351 static const int tm_leap_1970 = 477;
352
353 /**
354 * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calendar time
355 */
356 time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
357 {
358 int tm_year, tm_mon, tm_day, tm_hour, tm_min, tm_sec;
359 int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap;
360 int tz_hour, tz_min, tz_offset;
361 time_t tm_days, tm_secs;
362 char buf[BUF_LEN], *eot = NULL;
363
364 snprintf(buf, sizeof(buf), "%.*s", (int)utctime->len, utctime->ptr);
365
366 if ((eot = strchr(buf, 'Z')) != NULL)
367 {
368 tz_offset = 0; /* Zulu time with a zero time zone offset */
369 }
370 else if ((eot = strchr(buf, '+')) != NULL)
371 {
372 if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
373 {
374 return 0; /* error in positive timezone offset format */
375 }
376 tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
377 }
378 else if ((eot = strchr(buf, '-')) != NULL)
379 {
380 if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
381 {
382 return 0; /* error in negative timezone offset format */
383 }
384 tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */
385 }
386 else
387 {
388 return 0; /* error in time format */
389 }
390
391 /* parse ASN.1 time string */
392 {
393 const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
394 "%4d%2d%2d%2d%2d";
395
396 if (sscanf(buf, format, &tm_year, &tm_mon, &tm_day,
397 &tm_hour, &tm_min) != 5)
398 {
399 return 0; /* error in [yy]yymmddhhmm time format */
400 }
401 }
402
403 /* is there a seconds field? */
404 if ((eot - buf) == ((type == ASN1_UTCTIME)?12:14))
405 {
406 if (sscanf(eot-2, "%2d", &tm_sec) != 1)
407 {
408 return 0; /* error in ss seconds field format */
409 }
410 }
411 else
412 {
413 tm_sec = 0;
414 }
415
416 /* representation of two-digit years */
417 if (type == ASN1_UTCTIME)
418 {
419 tm_year += (tm_year < 50) ? 2000 : 1900;
420 }
421
422 /* prevent obvious 32 bit integer overflows */
423 if (sizeof(time_t) == 4 && (tm_year > 2038 || tm_year < 1901))
424 {
425 return TIME_32_BIT_SIGNED_MAX;
426 }
427
428 /* representation of months as 0..11*/
429 if (tm_mon < 1 || tm_mon > 12)
430 {
431 return 0;
432 }
433 tm_mon--;
434
435 /* representation of days as 0..30 */
436 if (tm_day < 1 || tm_day > 31)
437 { /* we don't actually validate the day in relation to tm_year/tm_mon */
438 return 0;
439 }
440 tm_day--;
441
442 if (tm_hour < 0 || tm_hour > 23 ||
443 tm_min < 0 || tm_min > 59 ||
444 tm_sec < 0 || tm_sec > 60 /* allow leap seconds */)
445 {
446 return 0;
447 }
448
449 /* number of leap years between last year and 1970? */
450 tm_leap_4 = (tm_year - 1) / 4;
451 tm_leap_100 = tm_leap_4 / 25;
452 tm_leap_400 = tm_leap_100 / 4;
453 tm_leap = tm_leap_4 - tm_leap_100 + tm_leap_400 - tm_leap_1970;
454
455 /* if date later then February, is the current year a leap year? */
456 if (tm_mon > 1 && (tm_year % 4 == 0) &&
457 (tm_year % 100 != 0 || tm_year % 400 == 0))
458 {
459 tm_leap++;
460 }
461 tm_days = 365 * (tm_year - 1970) + days[tm_mon] + tm_day + tm_leap;
462 tm_secs = 60 * (60 * (24 * tm_days + tm_hour) + tm_min) + tm_sec - tz_offset;
463
464 if (sizeof(time_t) == 4)
465 { /* has a 32 bit signed integer overflow occurred? */
466 if (tm_year > 1970 && tm_secs < 0)
467 { /* depending on the time zone, the first days in 1970 may result in
468 * a negative value, but dates after 1970 never will */
469 return TIME_32_BIT_SIGNED_MAX;
470 }
471 if (tm_year < 1969 && tm_secs > 0)
472 { /* similarly, tm_secs is not positive for dates before 1970, except
473 * for the last days in 1969, depending on the time zone */
474 return TIME_32_BIT_SIGNED_MAX;
475 }
476 }
477 return tm_secs;
478 }
479
480 /**
481 * Convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
482 */
483 chunk_t asn1_from_time(const time_t *time, asn1_t type)
484 {
485 int offset;
486 const char *format;
487 char buf[BUF_LEN];
488 chunk_t formatted_time;
489 struct tm t = {};
490
491 gmtime_r(time, &t);
492 /* RFC 5280 says that dates through the year 2049 MUST be encoded as UTCTIME
493 * and dates in 2050 or later MUST be encoded as GENERALIZEDTIME. We only
494 * enforce the latter to avoid overflows but allow callers to force the
495 * encoding to GENERALIZEDTIME */
496 type = (t.tm_year >= 150) ? ASN1_GENERALIZEDTIME : type;
497 if (type == ASN1_GENERALIZEDTIME)
498 {
499 format = "%04d%02d%02d%02d%02d%02dZ";
500 offset = 1900;
501 }
502 else /* ASN1_UTCTIME */
503 {
504 format = "%02d%02d%02d%02d%02d%02dZ";
505 offset = (t.tm_year < 100) ? 0 : -100;
506 }
507 snprintf(buf, BUF_LEN, format, t.tm_year + offset,
508 t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
509 formatted_time.ptr = buf;
510 formatted_time.len = strlen(buf);
511 return asn1_simple_object(type, formatted_time);
512 }
513
514 /*
515 * Defined in header.
516 */
517 void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private)
518 {
519 int oid;
520
521 switch (type)
522 {
523 case ASN1_OID:
524 oid = asn1_known_oid(object);
525 if (oid == OID_UNKNOWN)
526 {
527 char *oid_str = asn1_oid_to_string(object);
528
529 if (!oid_str)
530 {
531 break;
532 }
533 DBG2(DBG_ASN, " %s", oid_str);
534 free(oid_str);
535 }
536 else
537 {
538 DBG2(DBG_ASN, " '%s'", oid_names[oid].name);
539 }
540 return;
541 case ASN1_UTF8STRING:
542 case ASN1_IA5STRING:
543 case ASN1_PRINTABLESTRING:
544 case ASN1_T61STRING:
545 case ASN1_VISIBLESTRING:
546 DBG2(DBG_ASN, " '%.*s'", (int)object.len, object.ptr);
547 return;
548 case ASN1_UTCTIME:
549 case ASN1_GENERALIZEDTIME:
550 {
551 time_t time = asn1_to_time(&object, type);
552
553 DBG2(DBG_ASN, " '%T'", &time, TRUE);
554 }
555 return;
556 default:
557 break;
558 }
559 if (private)
560 {
561 DBG4(DBG_ASN, "%B", &object);
562 }
563 else
564 {
565 DBG3(DBG_ASN, "%B", &object);
566 }
567 }
568
569 /**
570 * parse an ASN.1 simple type
571 */
572 bool asn1_parse_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
573 {
574 size_t len;
575
576 /* an ASN.1 object must possess at least a tag and length field */
577 if (object->len < 2)
578 {
579 DBG2(DBG_ASN, "L%d - %s: ASN.1 object smaller than 2 octets", level,
580 name);
581 return FALSE;
582 }
583
584 if (*object->ptr != type)
585 {
586 DBG2(DBG_ASN, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
587 level, name, type, *object->ptr);
588 return FALSE;
589 }
590
591 len = asn1_length(object);
592
593 if (len == ASN1_INVALID_LENGTH)
594 {
595 DBG2(DBG_ASN, "L%d - %s: length of ASN.1 object invalid or too large",
596 level, name);
597 return FALSE;
598 }
599
600 DBG2(DBG_ASN, "L%d - %s:", level, name);
601 asn1_debug_simple_object(*object, type, FALSE);
602 return TRUE;
603 }
604
605 /*
606 * Described in header
607 */
608 uint64_t asn1_parse_integer_uint64(chunk_t blob)
609 {
610 uint64_t val = 0;
611 int i;
612
613 for (i = 0; i < blob.len; i++)
614 { /* if it is longer than 8 bytes, we just use the 8 LSBs */
615 val <<= 8;
616 val |= (uint64_t)blob.ptr[i];
617 }
618 return val;
619 }
620
621 /*
622 * Described in header
623 */
624 chunk_t asn1_integer_from_uint64(uint64_t val)
625 {
626 u_char buf[sizeof(val)];
627 chunk_t enc = chunk_empty;
628
629 if (val < 0x100)
630 {
631 buf[0] = (u_char)val;
632 return chunk_clone(chunk_create(buf, 1));
633 }
634 for (enc.ptr = buf + sizeof(val); val; enc.len++, val >>= 8)
635 { /* fill the buffer from the end */
636 *(--enc.ptr) = val & 0xff;
637 }
638 return chunk_clone(enc);
639 }
640
641 /*
642 * Described in header
643 */
644 int asn1_parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
645 {
646 chunk_t object;
647 int alg = OID_UNKNOWN;
648
649 if (asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE)
650 {
651 DBG2(DBG_ASN, "L%d - algorithmIdentifier:", level0);
652
653 if (asn1_unwrap(&blob, &object) == ASN1_OID)
654 {
655 DBG2(DBG_ASN, "L%d - algorithm:", level0+1);
656 asn1_debug_simple_object(object, ASN1_OID, FALSE);
657 alg = asn1_known_oid(object);
658
659 if (blob.len)
660 {
661 DBG2(DBG_ASN, "L%d - parameters:", level0+1);
662 DBG3(DBG_ASN, "%B", &blob);
663 if (parameters)
664 {
665 *parameters = blob;
666 }
667 }
668 }
669 }
670 return alg;
671 }
672
673 /*
674 * tests if a blob contains a valid ASN.1 set or sequence
675 */
676 bool is_asn1(chunk_t blob)
677 {
678 u_int len;
679 u_char tag;
680
681 if (!blob.len || !blob.ptr)
682 {
683 return FALSE;
684 }
685
686 tag = *blob.ptr;
687 if (tag != ASN1_SEQUENCE && tag != ASN1_SET && tag != ASN1_OCTET_STRING)
688 {
689 DBG2(DBG_ASN, " file content is not binary ASN.1");
690 return FALSE;
691 }
692
693 len = asn1_length(&blob);
694
695 if (len == ASN1_INVALID_LENGTH)
696 {
697 return FALSE;
698 }
699
700 /* exact match */
701 if (len == blob.len)
702 {
703 return TRUE;
704 }
705
706 /* some websites append a surplus newline character to the blob */
707 if (len + 1 == blob.len && *(blob.ptr + len) == '\n')
708 {
709 return TRUE;
710 }
711
712 DBG2(DBG_ASN, " file size does not match ASN.1 coded length");
713 return FALSE;
714 }
715
716 /*
717 * Defined in header.
718 */
719 bool asn1_is_printablestring(chunk_t str)
720 {
721 const char printablestring_charset[] =
722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
723 u_int i;
724
725 for (i = 0; i < str.len; i++)
726 {
727 if (strchr(printablestring_charset, str.ptr[i]) == NULL)
728 {
729 return FALSE;
730 }
731 }
732 return TRUE;
733 }
734
735 /**
736 * codes ASN.1 lengths up to a size of 16'777'215 bytes
737 */
738 static void asn1_code_length(size_t length, chunk_t *code)
739 {
740 if (length < 128)
741 {
742 code->ptr[0] = length;
743 code->len = 1;
744 }
745 else if (length < 256)
746 {
747 code->ptr[0] = 0x81;
748 code->ptr[1] = (u_char) length;
749 code->len = 2;
750 }
751 else if (length < 65536)
752 {
753 code->ptr[0] = 0x82;
754 code->ptr[1] = length >> 8;
755 code->ptr[2] = length & 0x00ff;
756 code->len = 3;
757 }
758 else
759 {
760 code->ptr[0] = 0x83;
761 code->ptr[1] = length >> 16;
762 code->ptr[2] = (length >> 8) & 0x00ff;
763 code->ptr[3] = length & 0x0000ff;
764 code->len = 4;
765 }
766 }
767
768 /**
769 * build an empty asn.1 object with tag and length fields already filled in
770 */
771 u_char* asn1_build_object(chunk_t *object, asn1_t type, size_t datalen)
772 {
773 u_char length_buf[4];
774 chunk_t length = { length_buf, 0 };
775 u_char *pos;
776
777 /* code the asn.1 length field */
778 asn1_code_length(datalen, &length);
779
780 /* allocate memory for the asn.1 TLV object */
781 object->len = 1 + length.len + datalen;
782 object->ptr = malloc(object->len);
783
784 /* set position pointer at the start of the object */
785 pos = object->ptr;
786
787 /* copy the asn.1 tag field and advance the pointer */
788 *pos++ = type;
789
790 /* copy the asn.1 length field and advance the pointer */
791 memcpy(pos, length.ptr, length.len);
792 pos += length.len;
793
794 return pos;
795 }
796
797 /**
798 * Build a simple ASN.1 object
799 */
800 chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
801 {
802 chunk_t object;
803
804 u_char *pos = asn1_build_object(&object, tag, content.len);
805 memcpy(pos, content.ptr, content.len);
806
807 return object;
808 }
809
810 /**
811 * Build an ASN.1 BIT_STRING object
812 */
813 chunk_t asn1_bitstring(const char *mode, chunk_t content)
814 {
815 chunk_t object;
816 u_char *pos = asn1_build_object(&object, ASN1_BIT_STRING, 1 + content.len);
817
818 *pos++ = 0x00;
819 memcpy(pos, content.ptr, content.len);
820 if (*mode == 'm')
821 {
822 free(content.ptr);
823 }
824 return object;
825 }
826
827 /**
828 * Build an ASN.1 INTEGER object
829 */
830 chunk_t asn1_integer(const char *mode, chunk_t content)
831 {
832 chunk_t zero = chunk_from_chars(0x00), object;
833 size_t len;
834 u_char *pos;
835 bool move;
836
837 if (content.len == 0)
838 { /* make sure 0 is encoded properly */
839 content = zero;
840 move = FALSE;
841 }
842 else
843 {
844 move = (*mode == 'm');
845 }
846
847 /* ASN.1 integers must be positive numbers in two's complement */
848 len = content.len + ((*content.ptr & 0x80) ? 1 : 0);
849 pos = asn1_build_object(&object, ASN1_INTEGER, len);
850 if (len > content.len)
851 {
852 *pos++ = 0x00;
853 }
854 memcpy(pos, content.ptr, content.len);
855
856 if (move)
857 {
858 free(content.ptr);
859 }
860 return object;
861 }
862
863 /**
864 * Build an ASN.1 object from a variable number of individual chunks.
865 * Depending on the mode, chunks either are moved ('m') or copied ('c').
866 */
867 chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
868 {
869 chunk_t construct;
870 va_list chunks;
871 u_char *pos;
872 int i;
873 int count = strlen(mode);
874
875 /* sum up lengths of individual chunks */
876 va_start(chunks, mode);
877 construct.len = 0;
878 for (i = 0; i < count; i++)
879 {
880 chunk_t ch = va_arg(chunks, chunk_t);
881 construct.len += ch.len;
882 }
883 va_end(chunks);
884
885 /* allocate needed memory for construct */
886 pos = asn1_build_object(&construct, type, construct.len);
887
888 /* copy or move the chunks */
889 va_start(chunks, mode);
890 for (i = 0; i < count; i++)
891 {
892 chunk_t ch = va_arg(chunks, chunk_t);
893
894 memcpy(pos, ch.ptr, ch.len);
895 pos += ch.len;
896
897 switch (*mode++)
898 {
899 case 's':
900 chunk_clear(&ch);
901 break;
902 case 'm':
903 free(ch.ptr);
904 break;
905 default:
906 break;
907 }
908 }
909 va_end(chunks);
910
911 return construct;
912 }
913
914 /**
915 * ASN.1 definition of time
916 */
917 static const asn1Object_t timeObjects[] = {
918 { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */
919 { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
920 { 0, "generalizeTime", ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */
921 { 0, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
922 { 0, "exit", ASN1_EOC, ASN1_EXIT }
923 };
924 #ifdef TIME_UTC
925 /* used by C11 timespec_get(), <time.h> */
926 # undef TIME_UTC
927 #endif
928 #define TIME_UTC 0
929 #define TIME_GENERALIZED 2
930
931 /**
932 * extracts and converts a UTCTIME or GENERALIZEDTIME object
933 */
934 time_t asn1_parse_time(chunk_t blob, int level0)
935 {
936 asn1_parser_t *parser;
937 chunk_t object;
938 int objectID;
939 time_t utc_time = 0;
940
941 parser= asn1_parser_create(timeObjects, blob);
942 parser->set_top_level(parser, level0);
943
944 while (parser->iterate(parser, &objectID, &object))
945 {
946 if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
947 {
948 utc_time = asn1_to_time(&object, (objectID == TIME_UTC)
949 ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
950 }
951 }
952 parser->destroy(parser);
953 return utc_time;
954 }