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