moved parse_time() from x509.c to asn1.c
[strongswan.git] / src / libstrongswan / asn1 / asn1.c
1 /* Simple ASN.1 parser
2 * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
3 * Copyright (C) 2006 Martin Will, Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <time.h>
19
20 #include "asn1.h"
21
22 #include <library.h>
23 #include <debug.h>
24
25 /* some common prefabricated ASN.1 constants */
26 static u_char ASN1_INTEGER_0_str[] = { 0x02, 0x00 };
27 static u_char ASN1_INTEGER_1_str[] = { 0x02, 0x01, 0x01 };
28 static u_char ASN1_INTEGER_2_str[] = { 0x02, 0x01, 0x02 };
29
30 const chunk_t ASN1_INTEGER_0 = chunk_from_buf(ASN1_INTEGER_0_str);
31 const chunk_t ASN1_INTEGER_1 = chunk_from_buf(ASN1_INTEGER_1_str);
32 const chunk_t ASN1_INTEGER_2 = chunk_from_buf(ASN1_INTEGER_2_str);
33
34 /* some popular algorithmIdentifiers */
35
36 static u_char ASN1_md5_id_str[] = {
37 0x30, 0x0C,
38 0x06, 0x08,
39 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,
40 0x05, 0x00
41 };
42
43 static u_char ASN1_sha1_id_str[] = {
44 0x30, 0x09,
45 0x06, 0x05,
46 0x2B, 0x0E,0x03, 0x02, 0x1A,
47 0x05, 0x00
48 };
49
50 static u_char ASN1_md5WithRSA_id_str[] = {
51 0x30, 0x0D,
52 0x06, 0x09,
53 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04,
54 0x05, 0x00
55 };
56
57 static u_char ASN1_sha1WithRSA_id_str[] = {
58 0x30, 0x0D,
59 0x06, 0x09,
60 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
61 0x05, 0x00
62 };
63
64 static u_char ASN1_rsaEncryption_id_str[] = {
65 0x30, 0x0D,
66 0x06, 0x09,
67 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
68 0x05, 0x00
69 };
70
71 const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str);
72 const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str);
73 const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str);
74 const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str);
75 const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str);
76
77 /* ASN.1 definiton of an algorithmIdentifier */
78 static const asn1Object_t algorithmIdentifierObjects[] = {
79 { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
80 { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
81 { 1, "parameters", ASN1_EOC, ASN1_RAW } /* 2 */
82 };
83
84 #define ALGORITHM_ID_ALG 1
85 #define ALGORITHM_ID_PARAMETERS 2
86 #define ALGORITHM_ID_ROOF 3
87
88 /**
89 * return the ASN.1 encoded algorithm identifier
90 */
91 chunk_t asn1_algorithmIdentifier(int oid)
92 {
93 switch (oid)
94 {
95 case OID_RSA_ENCRYPTION:
96 return ASN1_rsaEncryption_id;
97 case OID_MD5_WITH_RSA:
98 return ASN1_md5WithRSA_id;
99 case OID_SHA1_WITH_RSA:
100 return ASN1_sha1WithRSA_id;
101 case OID_MD5:
102 return ASN1_md5_id;
103 case OID_SHA1:
104 return ASN1_sha1_id;
105 default:
106 return chunk_empty;
107 }
108 }
109
110 /**
111 * If the oid is listed in the oid_names table then the corresponding
112 * position in the oid_names table is returned otherwise -1 is returned
113 */
114 int known_oid(chunk_t object)
115 {
116 int oid = 0;
117
118 while (object.len)
119 {
120 if (oid_names[oid].octet == *object.ptr)
121 {
122 if (--object.len == 0 || oid_names[oid].down == 0)
123 {
124 return oid; /* found terminal symbol */
125 }
126 else
127 {
128 object.ptr++; oid++; /* advance to next hex octet */
129 }
130 }
131 else
132 {
133 if (oid_names[oid].next)
134 oid = oid_names[oid].next;
135 else
136 return OID_UNKNOWN;
137 }
138 }
139 return -1;
140 }
141
142 /**
143 * Decodes the length in bytes of an ASN.1 object
144 */
145 u_int asn1_length(chunk_t *blob)
146 {
147 u_char n;
148 size_t len;
149
150 /* advance from tag field on to length field */
151 blob->ptr++;
152 blob->len--;
153
154 /* read first octet of length field */
155 n = *blob->ptr++;
156 blob->len--;
157
158 if ((n & 0x80) == 0)
159 {/* single length octet */
160 return n;
161 }
162
163 /* composite length, determine number of length octets */
164 n &= 0x7f;
165
166 if (n > blob->len)
167 {
168 DBG2("number of length octets is larger than ASN.1 object");
169 return ASN1_INVALID_LENGTH;
170 }
171
172 if (n > sizeof(len))
173 {
174 DBG2("number of length octets is larger than limit of %d octets",
175 (int)sizeof(len));
176 return ASN1_INVALID_LENGTH;
177 }
178
179 len = 0;
180
181 while (n-- > 0)
182 {
183 len = 256*len + *blob->ptr++;
184 blob->len--;
185 }
186 return len;
187 }
188
189 /**
190 * determines if a character string is of type ASN.1 printableString
191 */
192 bool is_printablestring(chunk_t str)
193 {
194 const char printablestring_charset[] =
195 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
196 u_int i;
197
198 for (i = 0; i < str.len; i++)
199 {
200 if (strchr(printablestring_charset, str.ptr[i]) == NULL)
201 return FALSE;
202 }
203 return TRUE;
204 }
205
206 /**
207 * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
208 */
209 time_t asn1totime(const chunk_t *utctime, asn1_t type)
210 {
211 struct tm t;
212 time_t tz_offset;
213 u_char *eot = NULL;
214
215 if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
216 {
217 tz_offset = 0; /* Zulu time with a zero time zone offset */
218 }
219 else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL)
220 {
221 int tz_hour, tz_min;
222
223 sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
224 tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
225 }
226 else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL)
227 {
228 int tz_hour, tz_min;
229
230 sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
231 tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */
232 }
233 else
234 {
235 return 0; /* error in time format */
236 }
237
238 {
239 const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
240 "%4d%2d%2d%2d%2d";
241
242 sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday,
243 &t.tm_hour, &t.tm_min);
244 }
245
246 /* is there a seconds field? */
247 if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14))
248 {
249 sscanf(eot-2, "%2d", &t.tm_sec);
250 }
251 else
252 {
253 t.tm_sec = 0;
254 }
255
256 /* representation of year */
257 if (t.tm_year >= 1900)
258 {
259 t.tm_year -= 1900;
260 }
261 else if (t.tm_year >= 100)
262 {
263 return 0;
264 }
265 else if (t.tm_year < 50)
266 {
267 t.tm_year += 100;
268 }
269
270 /* representation of month 0..11*/
271 t.tm_mon--;
272
273 /* set daylight saving time to off */
274 t.tm_isdst = 0;
275
276 /* compensate timezone */
277
278 return mktime(&t) - timezone - tz_offset;
279 }
280
281 /**
282 * Initializes the internal context of the ASN.1 parser
283 */
284 void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0,
285 bool implicit, bool private)
286 {
287 ctx->blobs[0] = blob;
288 ctx->level0 = level0;
289 ctx->implicit = implicit;
290 ctx->private = private;
291 memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr));
292 }
293
294 /**
295 * print the value of an ASN.1 simple object
296 */
297 static void debug_asn1_simple_object(chunk_t object, asn1_t type, bool private)
298 {
299 int oid;
300
301 switch (type)
302 {
303 case ASN1_OID:
304 oid = known_oid(object);
305 if (oid != OID_UNKNOWN)
306 {
307 DBG2(" '%s'", oid_names[oid].name);
308 return;
309 }
310 break;
311 case ASN1_UTF8STRING:
312 case ASN1_IA5STRING:
313 case ASN1_PRINTABLESTRING:
314 case ASN1_T61STRING:
315 case ASN1_VISIBLESTRING:
316 DBG2(" '%.*s'", (int)object.len, object.ptr);
317 return;
318 case ASN1_UTCTIME:
319 case ASN1_GENERALIZEDTIME:
320 {
321 time_t time = asn1totime(&object, type);
322
323 DBG2(" '%T'", &time);
324 }
325 return;
326 default:
327 break;
328 }
329 if (private)
330 {
331 DBG4("%B", &object);
332 }
333 else
334 {
335 DBG3("%B", &object);
336 }
337 }
338
339 /**
340 * Parses and extracts the next ASN.1 object
341 */
342 bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx)
343 {
344 asn1Object_t obj = objects[*objectID];
345 chunk_t *blob;
346 chunk_t *blob1;
347 u_char *start_ptr;
348
349 *object = chunk_empty;
350
351 if (obj.flags & ASN1_END) /* end of loop or option found */
352 {
353 if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0)
354 {
355 *objectID = ctx->loopAddr[obj.level]; /* another iteration */
356 obj = objects[*objectID];
357 }
358 else
359 {
360 ctx->loopAddr[obj.level] = 0; /* exit loop or option*/
361 return TRUE;
362 }
363 }
364
365 *level = ctx->level0 + obj.level;
366 blob = ctx->blobs + obj.level;
367 blob1 = blob + 1;
368 start_ptr = blob->ptr;
369
370 /* handle ASN.1 defaults values */
371 if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
372 {
373 /* field is missing */
374 DBG2("L%d - %s:", *level, obj.name);
375 if (obj.type & ASN1_CONSTRUCTED)
376 {
377 (*objectID)++ ; /* skip context-specific tag */
378 }
379 return TRUE;
380 }
381
382 /* handle ASN.1 options */
383
384 if ((obj.flags & ASN1_OPT)
385 && (blob->len == 0 || *start_ptr != obj.type))
386 {
387 /* advance to end of missing option field */
388 do
389 (*objectID)++;
390 while (!((objects[*objectID].flags & ASN1_END)
391 && (objects[*objectID].level == obj.level)));
392 return TRUE;
393 }
394
395 /* an ASN.1 object must possess at least a tag and length field */
396
397 if (blob->len < 2)
398 {
399 DBG2("L%d - %s: ASN.1 object smaller than 2 octets",
400 *level, obj.name);
401 return FALSE;
402 }
403
404 blob1->len = asn1_length(blob);
405
406 if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
407 {
408 DBG2("L%d - %s: length of ASN.1 object invalid or too large",
409 *level, obj.name);
410 return FALSE;
411 }
412
413 blob1->ptr = blob->ptr;
414 blob->ptr += blob1->len;
415 blob->len -= blob1->len;
416
417 /* return raw ASN.1 object without prior type checking */
418
419 if (obj.flags & ASN1_RAW)
420 {
421 DBG2("L%d - %s:", *level, obj.name);
422 object->ptr = start_ptr;
423 object->len = (size_t)(blob->ptr - start_ptr);
424 return TRUE;
425 }
426
427 if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0))
428 {
429 DBG1("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
430 *level, obj.name, obj.type, *start_ptr);
431 DBG3("%b", start_ptr, (u_int)(blob->ptr - start_ptr));
432 return FALSE;
433 }
434
435 DBG2("L%d - %s:", ctx->level0+obj.level, obj.name);
436
437 /* In case of "SEQUENCE OF" or "SET OF" start a loop */
438 if (obj.flags & ASN1_LOOP)
439 {
440 if (blob1->len > 0)
441 {
442 /* at least one item, start the loop */
443 ctx->loopAddr[obj.level] = *objectID + 1;
444 }
445 else
446 {
447 /* no items, advance directly to end of loop */
448 do
449 (*objectID)++;
450 while (!((objects[*objectID].flags & ASN1_END)
451 && (objects[*objectID].level == obj.level)));
452 return TRUE;
453 }
454 }
455
456 if (obj.flags & ASN1_OBJ)
457 {
458 object->ptr = start_ptr;
459 object->len = (size_t)(blob->ptr - start_ptr);
460 if (ctx->private)
461 {
462 DBG4("%B", object);
463 }
464 else
465 {
466 DBG3("%B", object);
467 }
468 }
469 else if (obj.flags & ASN1_BODY)
470 {
471 *object = *blob1;
472 debug_asn1_simple_object(*object, obj.type, ctx->private);
473 }
474 return TRUE;
475 }
476
477 /**
478 * parse an ASN.1 simple type
479 */
480 bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
481 {
482 size_t len;
483
484 /* an ASN.1 object must possess at least a tag and length field */
485 if (object->len < 2)
486 {
487 DBG2("L%d - %s: ASN.1 object smaller than 2 octets", level, name);
488 return FALSE;
489 }
490
491 if (*object->ptr != type)
492 {
493 DBG2("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
494 level, name, type, *object->ptr);
495 return FALSE;
496 }
497
498 len = asn1_length(object);
499
500 if (len == ASN1_INVALID_LENGTH || object->len < len)
501 {
502 DBG2("L%d - %s: length of ASN.1 object invalid or too large",
503 level, name);
504 return FALSE;
505 }
506
507 DBG2("L%d - %s:", level, name);
508 debug_asn1_simple_object(*object, type, FALSE);
509 return TRUE;
510 }
511
512 /**
513 * extracts an algorithmIdentifier
514 */
515 int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
516 {
517 asn1_ctx_t ctx;
518 chunk_t object;
519 u_int level;
520 int alg = OID_UNKNOWN;
521 int objectID = 0;
522
523 asn1_init(&ctx, blob, level0, FALSE, FALSE);
524
525 while (objectID < ALGORITHM_ID_ROOF)
526 {
527 if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx))
528 return OID_UNKNOWN;
529
530 switch (objectID)
531 {
532 case ALGORITHM_ID_ALG:
533 alg = known_oid(object);
534 break;
535 case ALGORITHM_ID_PARAMETERS:
536 if (parameters != NULL)
537 *parameters = object;
538 break;
539 default:
540 break;
541 }
542 objectID++;
543 }
544 return alg;
545 }
546
547 /*
548 * tests if a blob contains a valid ASN.1 set or sequence
549 */
550 bool is_asn1(chunk_t blob)
551 {
552 u_int len;
553 u_char tag = *blob.ptr;
554
555 if (tag != ASN1_SEQUENCE && tag != ASN1_SET)
556 {
557 DBG2(" file content is not binary ASN.1");
558 return FALSE;
559 }
560 len = asn1_length(&blob);
561 if (len != blob.len)
562 {
563 DBG2(" file size does not match ASN.1 coded length");
564 return FALSE;
565 }
566 return TRUE;
567 }
568
569 /**
570 * codes ASN.1 lengths up to a size of 16'777'215 bytes
571 */
572 void code_asn1_length(size_t length, chunk_t *code)
573 {
574 if (length < 128)
575 {
576 code->ptr[0] = length;
577 code->len = 1;
578 }
579 else if (length < 256)
580 {
581 code->ptr[0] = 0x81;
582 code->ptr[1] = (u_char) length;
583 code->len = 2;
584 }
585 else if (length < 65536)
586 {
587 code->ptr[0] = 0x82;
588 code->ptr[1] = length >> 8;
589 code->ptr[2] = length & 0x00ff;
590 code->len = 3;
591 }
592 else
593 {
594 code->ptr[0] = 0x83;
595 code->ptr[1] = length >> 16;
596 code->ptr[2] = (length >> 8) & 0x00ff;
597 code->ptr[3] = length & 0x0000ff;
598 code->len = 4;
599 }
600 }
601
602 /**
603 * build an empty asn.1 object with tag and length fields already filled in
604 */
605 u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen)
606 {
607 u_char length_buf[4];
608 chunk_t length = { length_buf, 0 };
609 u_char *pos;
610
611 /* code the asn.1 length field */
612 code_asn1_length(datalen, &length);
613
614 /* allocate memory for the asn.1 TLV object */
615 object->len = 1 + length.len + datalen;
616 object->ptr = malloc(object->len);
617
618 /* set position pointer at the start of the object */
619 pos = object->ptr;
620
621 /* copy the asn.1 tag field and advance the pointer */
622 *pos++ = type;
623
624 /* copy the asn.1 length field and advance the pointer */
625 memcpy(pos, length.ptr, length.len);
626 pos += length.len;
627
628 return pos;
629 }
630
631 /**
632 * build a simple ASN.1 object
633 */
634 chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
635 {
636 chunk_t object;
637
638 u_char *pos = build_asn1_object(&object, tag, content.len);
639 memcpy(pos, content.ptr, content.len);
640 pos += content.len;
641
642 return object;
643 }
644
645 /**
646 * Build an ASN.1 object from a variable number of individual chunks.
647 * Depending on the mode, chunks either are moved ('m') or copied ('c').
648 */
649 chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
650 {
651 chunk_t construct;
652 va_list chunks;
653 u_char *pos;
654 int i;
655 int count = strlen(mode);
656
657 /* sum up lengths of individual chunks */
658 va_start(chunks, mode);
659 construct.len = 0;
660 for (i = 0; i < count; i++)
661 {
662 chunk_t ch = va_arg(chunks, chunk_t);
663 construct.len += ch.len;
664 }
665 va_end(chunks);
666
667 /* allocate needed memory for construct */
668 pos = build_asn1_object(&construct, type, construct.len);
669
670 /* copy or move the chunks */
671 va_start(chunks, mode);
672 for (i = 0; i < count; i++)
673 {
674 chunk_t ch = va_arg(chunks, chunk_t);
675
676 switch (*mode++)
677 {
678 case 'm':
679 memcpy(pos, ch.ptr, ch.len);
680 pos += ch.len;
681 free(ch.ptr);
682 break;
683 case 'c':
684 default:
685 memcpy(pos, ch.ptr, ch.len);
686 pos += ch.len;
687 }
688 }
689 va_end(chunks);
690
691 return construct;
692 }
693
694 /**
695 * convert a MP integer into a DER coded ASN.1 object
696 */
697 chunk_t asn1_integer_from_mpz(const mpz_t value)
698 {
699 size_t bits = mpz_sizeinbase(value, 2); /* size in bits */
700 chunk_t n;
701 n.len = 1 + bits / 8; /* size in bytes */
702 n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, value);
703
704 return asn1_wrap(ASN1_INTEGER, "m", n);
705 }
706
707 /**
708 * convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
709 */
710 chunk_t timetoasn1(const time_t *time, asn1_t type)
711 {
712 int offset;
713 const char *format;
714 char buf[32];
715 chunk_t formatted_time;
716 struct tm *t = gmtime(time);
717
718 if (type == ASN1_GENERALIZEDTIME)
719 {
720 format = "%04d%02d%02d%02d%02d%02dZ";
721 offset = 1900;
722 }
723 else /* ASN1_UTCTIME */
724 {
725 format = "%02d%02d%02d%02d%02d%02dZ";
726 offset = (t->tm_year < 100)? 0 : -100;
727 }
728 snprintf(buf, sizeof(buf), format, t->tm_year + offset,
729 t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
730 formatted_time.ptr = buf;
731 formatted_time.len = strlen(buf);
732 return asn1_simple_object(type, formatted_time);
733 }
734
735 /**
736 * ASN.1 definition of time
737 */
738 static const asn1Object_t timeObjects[] = {
739 { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */
740 { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
741 { 0, "generalizeTime",ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */
742 { 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */
743 };
744 #define TIME_UTC 0
745 #define TIME_GENERALIZED 2
746 #define TIME_ROOF 4
747
748 /**
749 * extracts and converts a UTCTIME or GENERALIZEDTIME object
750 */
751 time_t parse_time(chunk_t blob, int level0)
752 {
753 asn1_ctx_t ctx;
754 chunk_t object;
755 u_int level;
756 int objectID = 0;
757
758 asn1_init(&ctx, blob, level0, FALSE, FALSE);
759
760 while (objectID < TIME_ROOF)
761 {
762 if (!extract_object(timeObjects, &objectID, &object, &level, &ctx))
763 return 0;
764
765 if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
766 {
767 return asn1totime(&object, (objectID == TIME_UTC)
768 ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
769 }
770 objectID++;
771 }
772 return 0;
773 }