6f549d42d3868abef4adbc92055f057e9b6d8dae
[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 <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, 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 -1;
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 * Defined in header.
128 */
129 size_t asn1_length(chunk_t *blob)
130 {
131 u_char n;
132 size_t len;
133
134 if (blob->len < 2)
135 {
136 DBG2(DBG_LIB, "insufficient number of octets to parse ASN.1 length");
137 return ASN1_INVALID_LENGTH;
138 }
139
140 /* read length field, skip tag and length */
141 n = blob->ptr[1];
142 *blob = chunk_skip(*blob, 2);
143
144 if ((n & 0x80) == 0)
145 { /* single length octet */
146 if (n > blob->len)
147 {
148 DBG2(DBG_LIB, "length is larger than remaining blob size");
149 return ASN1_INVALID_LENGTH;
150 }
151 return n;
152 }
153
154 /* composite length, determine number of length octets */
155 n &= 0x7f;
156
157 if (n == 0 || n > blob->len)
158 {
159 DBG2(DBG_LIB, "number of length octets invalid");
160 return ASN1_INVALID_LENGTH;
161 }
162
163 if (n > sizeof(len))
164 {
165 DBG2(DBG_LIB, "number of length octets is larger than limit of"
166 " %d octets", (int)sizeof(len));
167 return ASN1_INVALID_LENGTH;
168 }
169
170 len = 0;
171
172 while (n-- > 0)
173 {
174 len = 256*len + *blob->ptr++;
175 blob->len--;
176 }
177 if (len > blob->len)
178 {
179 DBG2(DBG_LIB, "length is larger than remaining blob size");
180 return ASN1_INVALID_LENGTH;
181 }
182 return len;
183 }
184
185 /*
186 * See header.
187 */
188 int asn1_unwrap(chunk_t *blob, chunk_t *inner)
189 {
190 chunk_t res;
191 u_char len;
192 int type;
193
194 if (blob->len < 2)
195 {
196 return ASN1_INVALID;
197 }
198 type = blob->ptr[0];
199 len = blob->ptr[1];
200 *blob = chunk_skip(*blob, 2);
201
202 if ((len & 0x80) == 0)
203 { /* single length octet */
204 res.len = len;
205 }
206 else
207 { /* composite length, determine number of length octets */
208 len &= 0x7f;
209 if (len == 0 || len > sizeof(res.len))
210 {
211 return ASN1_INVALID;
212 }
213 res.len = 0;
214 while (len-- > 0)
215 {
216 res.len = 256 * res.len + blob->ptr[0];
217 *blob = chunk_skip(*blob, 1);
218 }
219 }
220 if (res.len > blob->len)
221 {
222 return ASN1_INVALID;
223 }
224 res.ptr = blob->ptr;
225 *blob = chunk_skip(*blob, res.len);
226 /* updating inner not before we are finished allows a caller to pass
227 * blob = inner */
228 *inner = res;
229 return type;
230 }
231
232 static const int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
233 static const int tm_leap_1970 = 477;
234
235 /**
236 * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
237 */
238 time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
239 {
240 int tm_year, tm_mon, tm_day, tm_days, tm_hour, tm_min, tm_sec;
241 int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap;
242 int tz_hour, tz_min, tz_offset;
243 time_t tm_secs;
244 u_char *eot = NULL;
245
246 if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
247 {
248 tz_offset = 0; /* Zulu time with a zero time zone offset */
249 }
250 else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL)
251 {
252 if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
253 {
254 return 0; /* error in positive timezone offset format */
255 }
256 tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
257 }
258 else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL)
259 {
260 if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
261 {
262 return 0; /* error in negative timezone offset format */
263 }
264 tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */
265 }
266 else
267 {
268 return 0; /* error in time format */
269 }
270
271 /* parse ASN.1 time string */
272 {
273 const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
274 "%4d%2d%2d%2d%2d";
275
276 if (sscanf(utctime->ptr, format, &tm_year, &tm_mon, &tm_day,
277 &tm_hour, &tm_min) != 5)
278 {
279 return 0; /* error in [yy]yymmddhhmm time format */
280 }
281 }
282
283 /* is there a seconds field? */
284 if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14))
285 {
286 if (sscanf(eot-2, "%2d", &tm_sec) != 1)
287 {
288 return 0; /* error in ss seconds field format */
289 }
290 }
291 else
292 {
293 tm_sec = 0;
294 }
295
296 /* representation of two-digit years */
297 if (type == ASN1_UTCTIME)
298 {
299 tm_year += (tm_year < 50) ? 2000 : 1900;
300 }
301
302 /* prevent large 32 bit integer overflows */
303 if (sizeof(time_t) == 4 && tm_year > 2038)
304 {
305 return TIME_32_BIT_SIGNED_MAX;
306 }
307
308 /* representation of months as 0..11*/
309 if (tm_mon < 1 || tm_mon > 12)
310 {
311 return 0; /* error in month format */
312 }
313 tm_mon--;
314
315 /* representation of days as 0..30 */
316 tm_day--;
317
318 /* number of leap years between last year and 1970? */
319 tm_leap_4 = (tm_year - 1) / 4;
320 tm_leap_100 = tm_leap_4 / 25;
321 tm_leap_400 = tm_leap_100 / 4;
322 tm_leap = tm_leap_4 - tm_leap_100 + tm_leap_400 - tm_leap_1970;
323
324 /* if date later then February, is the current year a leap year? */
325 if (tm_mon > 1 && (tm_year % 4 == 0) &&
326 (tm_year % 100 != 0 || tm_year % 400 == 0))
327 {
328 tm_leap++;
329 }
330 tm_days = 365 * (tm_year - 1970) + days[tm_mon] + tm_day + tm_leap;
331 tm_secs = 60 * (60 * (24 * tm_days + tm_hour) + tm_min) + tm_sec - tz_offset;
332
333 /* has a 32 bit signed integer overflow occurred? */
334 return (tm_secs < 0) ? TIME_32_BIT_SIGNED_MAX : tm_secs;
335 }
336
337 /**
338 * Convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
339 */
340 chunk_t asn1_from_time(const time_t *time, asn1_t type)
341 {
342 int offset;
343 const char *format;
344 char buf[BUF_LEN];
345 chunk_t formatted_time;
346 struct tm t;
347
348 gmtime_r(time, &t);
349 if (type == ASN1_GENERALIZEDTIME)
350 {
351 format = "%04d%02d%02d%02d%02d%02dZ";
352 offset = 1900;
353 }
354 else /* ASN1_UTCTIME */
355 {
356 format = "%02d%02d%02d%02d%02d%02dZ";
357 offset = (t.tm_year < 100)? 0 : -100;
358 }
359 snprintf(buf, BUF_LEN, format, t.tm_year + offset,
360 t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
361 formatted_time.ptr = buf;
362 formatted_time.len = strlen(buf);
363 return asn1_simple_object(type, formatted_time);
364 }
365
366 /*
367 * Defined in header.
368 */
369 void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private)
370 {
371 int oid;
372
373 switch (type)
374 {
375 case ASN1_OID:
376 oid = asn1_known_oid(object);
377 if (oid != OID_UNKNOWN)
378 {
379 DBG2(DBG_LIB, " '%s'", oid_names[oid].name);
380 return;
381 }
382 break;
383 case ASN1_UTF8STRING:
384 case ASN1_IA5STRING:
385 case ASN1_PRINTABLESTRING:
386 case ASN1_T61STRING:
387 case ASN1_VISIBLESTRING:
388 DBG2(DBG_LIB, " '%.*s'", (int)object.len, object.ptr);
389 return;
390 case ASN1_UTCTIME:
391 case ASN1_GENERALIZEDTIME:
392 {
393 time_t time = asn1_to_time(&object, type);
394
395 DBG2(DBG_LIB, " '%T'", &time, TRUE);
396 }
397 return;
398 default:
399 break;
400 }
401 if (private)
402 {
403 DBG4(DBG_LIB, "%B", &object);
404 }
405 else
406 {
407 DBG3(DBG_LIB, "%B", &object);
408 }
409 }
410
411 /**
412 * parse an ASN.1 simple type
413 */
414 bool asn1_parse_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
415 {
416 size_t len;
417
418 /* an ASN.1 object must possess at least a tag and length field */
419 if (object->len < 2)
420 {
421 DBG2(DBG_LIB, "L%d - %s: ASN.1 object smaller than 2 octets", level,
422 name);
423 return FALSE;
424 }
425
426 if (*object->ptr != type)
427 {
428 DBG2(DBG_LIB, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
429 level, name, type, *object->ptr);
430 return FALSE;
431 }
432
433 len = asn1_length(object);
434
435 if (len == ASN1_INVALID_LENGTH || object->len < len)
436 {
437 DBG2(DBG_LIB, "L%d - %s: length of ASN.1 object invalid or too large",
438 level, name);
439 return FALSE;
440 }
441
442 DBG2(DBG_LIB, "L%d - %s:", level, name);
443 asn1_debug_simple_object(*object, type, FALSE);
444 return TRUE;
445 }
446
447 /**
448 * ASN.1 definition of an algorithmIdentifier
449 */
450 static const asn1Object_t algorithmIdentifierObjects[] = {
451 { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
452 { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
453 { 1, "parameters", ASN1_EOC, ASN1_RAW|ASN1_OPT }, /* 2 */
454 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
455 { 0, "exit", ASN1_EOC, ASN1_EXIT }
456 };
457 #define ALGORITHM_ID_ALG 1
458 #define ALGORITHM_ID_PARAMETERS 2
459
460 /*
461 * Defined in header
462 */
463 int asn1_parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
464 {
465 asn1_parser_t *parser;
466 chunk_t object;
467 int objectID;
468 int alg = OID_UNKNOWN;
469
470 parser = asn1_parser_create(algorithmIdentifierObjects, blob);
471 parser->set_top_level(parser, level0);
472
473 while (parser->iterate(parser, &objectID, &object))
474 {
475 switch (objectID)
476 {
477 case ALGORITHM_ID_ALG:
478 alg = asn1_known_oid(object);
479 break;
480 case ALGORITHM_ID_PARAMETERS:
481 if (parameters != NULL)
482 {
483 *parameters = object;
484 }
485 break;
486 default:
487 break;
488 }
489 }
490 parser->destroy(parser);
491 return alg;
492 }
493
494 /*
495 * tests if a blob contains a valid ASN.1 set or sequence
496 */
497 bool is_asn1(chunk_t blob)
498 {
499 u_int len;
500 u_char tag;
501
502 if (!blob.len || !blob.ptr)
503 {
504 return FALSE;
505 }
506
507 tag = *blob.ptr;
508 if (tag != ASN1_SEQUENCE && tag != ASN1_SET && tag != ASN1_OCTET_STRING)
509 {
510 DBG2(DBG_LIB, " file content is not binary ASN.1");
511 return FALSE;
512 }
513
514 len = asn1_length(&blob);
515
516 /* exact match */
517 if (len == blob.len)
518 {
519 return TRUE;
520 }
521
522 /* some websites append a surplus newline character to the blob */
523 if (len + 1 == blob.len && *(blob.ptr + len) == '\n')
524 {
525 return TRUE;
526 }
527
528 DBG2(DBG_LIB, " file size does not match ASN.1 coded length");
529 return FALSE;
530 }
531
532 /*
533 * Defined in header.
534 */
535 bool asn1_is_printablestring(chunk_t str)
536 {
537 const char printablestring_charset[] =
538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
539 u_int i;
540
541 for (i = 0; i < str.len; i++)
542 {
543 if (strchr(printablestring_charset, str.ptr[i]) == NULL)
544 return FALSE;
545 }
546 return TRUE;
547 }
548
549 /**
550 * codes ASN.1 lengths up to a size of 16'777'215 bytes
551 */
552 static void asn1_code_length(size_t length, chunk_t *code)
553 {
554 if (length < 128)
555 {
556 code->ptr[0] = length;
557 code->len = 1;
558 }
559 else if (length < 256)
560 {
561 code->ptr[0] = 0x81;
562 code->ptr[1] = (u_char) length;
563 code->len = 2;
564 }
565 else if (length < 65536)
566 {
567 code->ptr[0] = 0x82;
568 code->ptr[1] = length >> 8;
569 code->ptr[2] = length & 0x00ff;
570 code->len = 3;
571 }
572 else
573 {
574 code->ptr[0] = 0x83;
575 code->ptr[1] = length >> 16;
576 code->ptr[2] = (length >> 8) & 0x00ff;
577 code->ptr[3] = length & 0x0000ff;
578 code->len = 4;
579 }
580 }
581
582 /**
583 * build an empty asn.1 object with tag and length fields already filled in
584 */
585 u_char* asn1_build_object(chunk_t *object, asn1_t type, size_t datalen)
586 {
587 u_char length_buf[4];
588 chunk_t length = { length_buf, 0 };
589 u_char *pos;
590
591 /* code the asn.1 length field */
592 asn1_code_length(datalen, &length);
593
594 /* allocate memory for the asn.1 TLV object */
595 object->len = 1 + length.len + datalen;
596 object->ptr = malloc(object->len);
597
598 /* set position pointer at the start of the object */
599 pos = object->ptr;
600
601 /* copy the asn.1 tag field and advance the pointer */
602 *pos++ = type;
603
604 /* copy the asn.1 length field and advance the pointer */
605 memcpy(pos, length.ptr, length.len);
606 pos += length.len;
607
608 return pos;
609 }
610
611 /**
612 * Build a simple ASN.1 object
613 */
614 chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
615 {
616 chunk_t object;
617
618 u_char *pos = asn1_build_object(&object, tag, content.len);
619 memcpy(pos, content.ptr, content.len);
620 pos += content.len;
621
622 return object;
623 }
624
625 /**
626 * Build an ASN.1 BIT_STRING object
627 */
628 chunk_t asn1_bitstring(const char *mode, chunk_t content)
629 {
630 chunk_t object;
631 u_char *pos = asn1_build_object(&object, ASN1_BIT_STRING, 1 + content.len);
632
633 *pos++ = 0x00;
634 memcpy(pos, content.ptr, content.len);
635 if (*mode == 'm')
636 {
637 free(content.ptr);
638 }
639 return object;
640 }
641
642 /**
643 * Build an ASN.1 INTEGER object
644 */
645 chunk_t asn1_integer(const char *mode, chunk_t content)
646 {
647 chunk_t object;
648 size_t len;
649 u_char *pos;
650
651 if (content.len == 0 || (content.len == 1 && *content.ptr == 0x00))
652 {
653 /* a zero ASN.1 integer does not have a value field */
654 len = 0;
655 }
656 else
657 {
658 /* ASN.1 integers must be positive numbers in two's complement */
659 len = content.len + ((*content.ptr & 0x80) ? 1 : 0);
660 }
661 pos = asn1_build_object(&object, ASN1_INTEGER, len);
662 if (len > content.len)
663 {
664 *pos++ = 0x00;
665 }
666 if (len)
667 {
668 memcpy(pos, content.ptr, content.len);
669 }
670 if (*mode == 'm')
671 {
672 free(content.ptr);
673 }
674 return object;
675 }
676
677 /**
678 * Build an ASN.1 object from a variable number of individual chunks.
679 * Depending on the mode, chunks either are moved ('m') or copied ('c').
680 */
681 chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
682 {
683 chunk_t construct;
684 va_list chunks;
685 u_char *pos;
686 int i;
687 int count = strlen(mode);
688
689 /* sum up lengths of individual chunks */
690 va_start(chunks, mode);
691 construct.len = 0;
692 for (i = 0; i < count; i++)
693 {
694 chunk_t ch = va_arg(chunks, chunk_t);
695 construct.len += ch.len;
696 }
697 va_end(chunks);
698
699 /* allocate needed memory for construct */
700 pos = asn1_build_object(&construct, type, construct.len);
701
702 /* copy or move the chunks */
703 va_start(chunks, mode);
704 for (i = 0; i < count; i++)
705 {
706 chunk_t ch = va_arg(chunks, chunk_t);
707
708 memcpy(pos, ch.ptr, ch.len);
709 pos += ch.len;
710
711 switch (*mode++)
712 {
713 case 's':
714 chunk_clear(&ch);
715 break;
716 case 'm':
717 free(ch.ptr);
718 break;
719 default:
720 break;
721 }
722 }
723 va_end(chunks);
724
725 return construct;
726 }
727
728 /**
729 * ASN.1 definition of time
730 */
731 static const asn1Object_t timeObjects[] = {
732 { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */
733 { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
734 { 0, "generalizeTime", ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */
735 { 0, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
736 { 0, "exit", ASN1_EOC, ASN1_EXIT }
737 };
738 #define TIME_UTC 0
739 #define TIME_GENERALIZED 2
740
741 /**
742 * extracts and converts a UTCTIME or GENERALIZEDTIME object
743 */
744 time_t asn1_parse_time(chunk_t blob, int level0)
745 {
746 asn1_parser_t *parser;
747 chunk_t object;
748 int objectID;
749 time_t utc_time = 0;
750
751 parser= asn1_parser_create(timeObjects, blob);
752 parser->set_top_level(parser, level0);
753
754 while (parser->iterate(parser, &objectID, &object))
755 {
756 if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
757 {
758 utc_time = asn1_to_time(&object, (objectID == TIME_UTC)
759 ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
760 }
761 }
762 parser->destroy(parser);
763 return utc_time;
764 }