fixed compiler warnings
[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
307 switch (type)
308 {
309 case ASN1_OID:
310 oid = known_oid(object);
311 if (oid != OID_UNKNOWN)
312 {
313 logger->log(logger, CONTROL|LEVEL2, " '%s'", oid_names[oid].name);
314 return;
315 }
316 break;
317 case ASN1_UTF8STRING:
318 case ASN1_IA5STRING:
319 case ASN1_PRINTABLESTRING:
320 case ASN1_T61STRING:
321 case ASN1_VISIBLESTRING:
322 logger->log(logger, CONTROL|LEVEL2, " '%.*s'", (int)object.len, object.ptr);
323 return;
324 case ASN1_UTCTIME:
325 case ASN1_GENERALIZEDTIME:
326 {
327 char buf[TIMETOA_BUF];
328 time_t time = asn1totime(&object, type);
329
330 timetoa(buf, TIMETOA_BUF, &time, TRUE);
331 logger->log(logger, CONTROL|LEVEL2, " '%s'", buf);
332 }
333 return;
334 default:
335 break;
336 }
337 logger->log_chunk(logger, RAW|LEVEL1, "", object);
338 }
339
340 /**
341 * Parses and extracts the next ASN.1 object
342 */
343 bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx)
344 {
345 asn1Object_t obj = objects[*objectID];
346 chunk_t *blob;
347 chunk_t *blob1;
348 u_char *start_ptr;
349
350 *object = CHUNK_INITIALIZER;
351
352 if (obj.flags & ASN1_END) /* end of loop or option found */
353 {
354 if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0)
355 {
356 *objectID = ctx->loopAddr[obj.level]; /* another iteration */
357 obj = objects[*objectID];
358 }
359 else
360 {
361 ctx->loopAddr[obj.level] = 0; /* exit loop or option*/
362 return TRUE;
363 }
364 }
365
366 *level = ctx->level0 + obj.level;
367 blob = ctx->blobs + obj.level;
368 blob1 = blob + 1;
369 start_ptr = blob->ptr;
370
371 /* handle ASN.1 defaults values */
372 if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
373 {
374 /* field is missing */
375 logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", *level, obj.name);
376 if (obj.type & ASN1_CONSTRUCTED)
377 {
378 (*objectID)++ ; /* skip context-specific tag */
379 }
380 return TRUE;
381 }
382
383 /* handle ASN.1 options */
384
385 if ((obj.flags & ASN1_OPT)
386 && (blob->len == 0 || *start_ptr != obj.type))
387 {
388 /* advance to end of missing option field */
389 do
390 (*objectID)++;
391 while (!((objects[*objectID].flags & ASN1_END)
392 && (objects[*objectID].level == obj.level)));
393 return TRUE;
394 }
395
396 /* an ASN.1 object must possess at least a tag and length field */
397
398 if (blob->len < 2)
399 {
400 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets",
401 *level, obj.name);
402 return FALSE;
403 }
404
405 blob1->len = asn1_length(blob);
406
407 if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
408 {
409 logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large",
410 *level, obj.name);
411 return FALSE;
412 }
413
414 blob1->ptr = blob->ptr;
415 blob->ptr += blob1->len;
416 blob->len -= blob1->len;
417
418 /* return raw ASN.1 object without prior type checking */
419
420 if (obj.flags & ASN1_RAW)
421 {
422 logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", *level, obj.name);
423 object->ptr = start_ptr;
424 object->len = (size_t)(blob->ptr - start_ptr);
425 return TRUE;
426 }
427
428 if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0))
429 {
430 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
431 *level, obj.name, obj.type, *start_ptr);
432 logger->log_bytes(logger, RAW|LEVEL1, "", start_ptr, (u_int)(blob->ptr - start_ptr));
433 return FALSE;
434 }
435
436 logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", ctx->level0+obj.level, obj.name);
437
438 /* In case of "SEQUENCE OF" or "SET OF" start a loop */
439 if (obj.flags & ASN1_LOOP)
440 {
441 if (blob1->len > 0)
442 {
443 /* at least one item, start the loop */
444 ctx->loopAddr[obj.level] = *objectID + 1;
445 }
446 else
447 {
448 /* no items, advance directly to end of loop */
449 do
450 (*objectID)++;
451 while (!((objects[*objectID].flags & ASN1_END)
452 && (objects[*objectID].level == obj.level)));
453 return TRUE;
454 }
455 }
456
457 if (obj.flags & ASN1_OBJ)
458 {
459 object->ptr = start_ptr;
460 object->len = (size_t)(blob->ptr - start_ptr);
461 logger->log_chunk(logger, RAW|LEVEL2, "", *object);
462 }
463 else if (obj.flags & ASN1_BODY)
464 {
465 *object = *blob1;
466 debug_asn1_simple_object(*object, obj.type);
467 }
468 return TRUE;
469 }
470
471 /**
472 * parse an ASN.1 simple type
473 */
474 bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
475 {
476 size_t len;
477
478 /* an ASN.1 object must possess at least a tag and length field */
479 if (object->len < 2)
480 {
481 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets",
482 level, name);
483 return FALSE;
484 }
485
486 if (*object->ptr != type)
487 {
488 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
489 level, name, type, *object->ptr);
490 return FALSE;
491 }
492
493 len = asn1_length(object);
494
495 if (len == ASN1_INVALID_LENGTH || object->len < len)
496 {
497 logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large",
498 level, name);
499 return FALSE;
500 }
501
502 logger->log(logger, CONTROL|LEVEL2, "L%d - %s:", level, name);
503 debug_asn1_simple_object(*object, type);
504 return TRUE;
505 }
506
507 /**
508 * extracts an algorithmIdentifier
509 */
510 int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
511 {
512 asn1_ctx_t ctx;
513 chunk_t object;
514 u_int level;
515 int alg = OID_UNKNOWN;
516 int objectID = 0;
517
518 asn1_init(&ctx, blob, level0, FALSE);
519
520 while (objectID < ALGORITHM_ID_ROOF)
521 {
522 if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx))
523 return OID_UNKNOWN;
524
525 switch (objectID)
526 {
527 case ALGORITHM_ID_ALG:
528 alg = known_oid(object);
529 break;
530 case ALGORITHM_ID_PARAMETERS:
531 if (parameters != NULL)
532 *parameters = object;
533 break;
534 default:
535 break;
536 }
537 objectID++;
538 }
539 return alg;
540 }
541
542 /*
543 * tests if a blob contains a valid ASN.1 set or sequence
544 */
545 bool is_asn1(chunk_t blob)
546 {
547 u_int len;
548 u_char tag = *blob.ptr;
549
550 asn1_init_logger();
551
552 if (tag != ASN1_SEQUENCE && tag != ASN1_SET)
553 {
554 logger->log(logger, ERROR|LEVEL2, " file content is not binary ASN.1");
555 return FALSE;
556 }
557 len = asn1_length(&blob);
558 if (len != blob.len)
559 {
560 logger->log(logger, ERROR|LEVEL2, " file size does not match ASN.1 coded length");
561 return FALSE;
562 }
563 return TRUE;
564 }
565
566 /**
567 * codes ASN.1 lengths up to a size of 16'777'215 bytes
568 */
569 void code_asn1_length(size_t length, chunk_t *code)
570 {
571 if (length < 128)
572 {
573 code->ptr[0] = length;
574 code->len = 1;
575 }
576 else if (length < 256)
577 {
578 code->ptr[0] = 0x81;
579 code->ptr[1] = (u_char) length;
580 code->len = 2;
581 }
582 else if (length < 65536)
583 {
584 code->ptr[0] = 0x82;
585 code->ptr[1] = length >> 8;
586 code->ptr[2] = length & 0x00ff;
587 code->len = 3;
588 }
589 else
590 {
591 code->ptr[0] = 0x83;
592 code->ptr[1] = length >> 16;
593 code->ptr[2] = (length >> 8) & 0x00ff;
594 code->ptr[3] = length & 0x0000ff;
595 code->len = 4;
596 }
597 }
598
599 /**
600 * build an empty asn.1 object with tag and length fields already filled in
601 */
602 u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen)
603 {
604 u_char length_buf[4];
605 chunk_t length = { length_buf, 0 };
606 u_char *pos;
607
608 /* code the asn.1 length field */
609 code_asn1_length(datalen, &length);
610
611 /* allocate memory for the asn.1 TLV object */
612 object->len = 1 + length.len + datalen;
613 object->ptr = malloc(object->len);
614
615 /* set position pointer at the start of the object */
616 pos = object->ptr;
617
618 /* copy the asn.1 tag field and advance the pointer */
619 *pos++ = type;
620
621 /* copy the asn.1 length field and advance the pointer */
622 memcpy(pos, length.ptr, length.len);
623 pos += length.len;
624
625 return pos;
626 }
627
628 /**
629 * build a simple ASN.1 object
630 */
631 chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
632 {
633 chunk_t object;
634
635 u_char *pos = build_asn1_object(&object, tag, content.len);
636 memcpy(pos, content.ptr, content.len);
637 pos += content.len;
638
639 return object;
640 }
641
642 /**
643 * Build an ASN.1 object from a variable number of individual chunks.
644 * Depending on the mode, chunks either are moved ('m') or copied ('c').
645 */
646 chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
647 {
648 chunk_t construct;
649 va_list chunks;
650 u_char *pos;
651 int i;
652 int count = strlen(mode);
653
654 /* sum up lengths of individual chunks */
655 va_start(chunks, mode);
656 construct.len = 0;
657 for (i = 0; i < count; i++)
658 {
659 chunk_t ch = va_arg(chunks, chunk_t);
660 construct.len += ch.len;
661 }
662 va_end(chunks);
663
664 /* allocate needed memory for construct */
665 pos = build_asn1_object(&construct, type, construct.len);
666
667 /* copy or move the chunks */
668 va_start(chunks, mode);
669 for (i = 0; i < count; i++)
670 {
671 chunk_t ch = va_arg(chunks, chunk_t);
672
673 switch (*mode++)
674 {
675 case 'm':
676 memcpy(pos, ch.ptr, ch.len);
677 pos += ch.len;
678 free(ch.ptr);
679 break;
680 case 'c':
681 default:
682 memcpy(pos, ch.ptr, ch.len);
683 pos += ch.len;
684 }
685 }
686 va_end(chunks);
687
688 return construct;
689 }
690
691 /**
692 * convert a MP integer into a DER coded ASN.1 object
693 */
694 chunk_t asn1_integer_from_mpz(const mpz_t value)
695 {
696 size_t bits = mpz_sizeinbase(value, 2); /* size in bits */
697 chunk_t n;
698 n.len = 1 + bits / 8; /* size in bytes */
699 n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, value);
700
701 return asn1_wrap(ASN1_INTEGER, "m", n);
702 }
703
704 /**
705 * convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
706 */
707 chunk_t timetoasn1(const time_t *time, asn1_t type)
708 {
709 int offset;
710 const char *format;
711 char buf[TIMETOA_BUF];
712 chunk_t formatted_time;
713 struct tm *t = gmtime(time);
714
715 if (type == ASN1_GENERALIZEDTIME)
716 {
717 format = "%04d%02d%02d%02d%02d%02dZ";
718 offset = 1900;
719 }
720 else /* ASN1_UTCTIME */
721 {
722 format = "%02d%02d%02d%02d%02d%02dZ";
723 offset = (t->tm_year < 100)? 0 : -100;
724 }
725 sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday
726 , t->tm_hour, t->tm_min, t->tm_sec);
727 formatted_time.ptr = buf;
728 formatted_time.len = strlen(buf);
729 return asn1_simple_object(type, formatted_time);
730 }