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