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