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