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