- startet importing pluto ASN1 stuff
[strongswan.git] / Source / lib / asn1-pluto / asn1-pluto.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-pluto.h"
21 #include "oid.h"
22
23 #include <utils/logger_manager.h>
24
25 static logger_t *logger;
26
27 /* Names of the months */
28 static const char* months[] = {
29 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
30 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
31 };
32
33 /* some common prefabricated ASN.1 constants */
34 static u_char ASN1_INTEGER_0_str[] = { 0x02, 0x00 };
35 static u_char ASN1_INTEGER_1_str[] = { 0x02, 0x01, 0x01 };
36 static u_char ASN1_INTEGER_2_str[] = { 0x02, 0x01, 0x02 };
37
38 const chunk_t ASN1_INTEGER_0 = chunk_from_buf(ASN1_INTEGER_0_str);
39 const chunk_t ASN1_INTEGER_1 = chunk_from_buf(ASN1_INTEGER_1_str);
40 const chunk_t ASN1_INTEGER_2 = chunk_from_buf(ASN1_INTEGER_2_str);
41
42 /* some popular algorithmIdentifiers */
43
44 static u_char ASN1_md5_id_str[] = {
45 0x30, 0x0C,
46 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,
47 0x05, 0x00
48 };
49
50 static u_char ASN1_sha1_id_str[] = {
51 0x30, 0x09,
52 0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A,
53 0x05, 0x00
54 };
55
56 static u_char ASN1_md5WithRSA_id_str[] = {
57 0x30, 0x0D,
58 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04,
59 0x05, 0x00
60 };
61
62 static u_char ASN1_sha1WithRSA_id_str[] = {
63 0x30, 0x0D,
64 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
65 0x05, 0x00
66 };
67
68 static u_char ASN1_rsaEncryption_id_str[] = {
69 0x30, 0x0D,
70 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
71 0x05, 0x00
72 };
73
74 const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str);
75 const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str);
76 const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str);
77 const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str);
78 const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str);
79
80 /* ASN.1 definiton of an algorithmIdentifier */
81 static const asn1Object_t algorithmIdentifierObjects[] = {
82 { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
83 { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
84 { 1, "parameters", ASN1_EOC, ASN1_RAW } /* 2 */
85 };
86
87 #define ALGORITHM_ID_ALG 1
88 #define ALGORITHM_ID_PARAMETERS 2
89 #define ALGORITHM_ID_ROOF 3
90
91 /*
92 * return the ASN.1 encoded algorithm identifier
93 */
94 chunk_t asn1_algorithmIdentifier(int oid)
95 {
96 switch (oid)
97 {
98 case OID_RSA_ENCRYPTION:
99 return ASN1_rsaEncryption_id;
100 case OID_MD5_WITH_RSA:
101 return ASN1_md5WithRSA_id;
102 case OID_SHA1_WITH_RSA:
103 return ASN1_sha1WithRSA_id;
104 case OID_MD5:
105 return ASN1_md5_id;
106 case OID_SHA1:
107 return ASN1_sha1_id;
108 default:
109 return CHUNK_INITIALIZER;
110 }
111 }
112
113 /*
114 * If the oid is listed in the oid_names table then the corresponding
115 * position in the oid_names table is returned otherwise -1 is returned
116 */
117 int known_oid(chunk_t object)
118 {
119 int oid = 0;
120
121 while (object.len)
122 {
123 if (oid_names[oid].octet == *object.ptr)
124 {
125 if (--object.len == 0 || oid_names[oid].down == 0)
126 {
127 return oid; /* found terminal symbol */
128 }
129 else
130 {
131 object.ptr++; oid++; /* advance to next hex octet */
132 }
133 }
134 else
135 {
136 if (oid_names[oid].next)
137 oid = oid_names[oid].next;
138 else
139 return OID_UNKNOWN;
140 }
141 }
142 return -1;
143 }
144
145 /*
146 * Decodes the length in bytes of an ASN.1 object
147 */
148 u_int asn1_length(chunk_t *blob)
149 {
150 u_char n;
151 size_t len;
152
153 /* advance from tag field on to length field */
154 blob->ptr++;
155 blob->len--;
156
157 /* read first octet of length field */
158 n = *blob->ptr++;
159 blob->len--;
160
161 if ((n & 0x80) == 0)
162 {/* single length octet */
163 return n;
164 }
165
166 /* composite length, determine number of length octets */
167 n &= 0x7f;
168
169 if (n > blob->len)
170 {
171 logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than ASN.1 object");
172 return ASN1_INVALID_LENGTH;
173 }
174
175 if (n > sizeof(len))
176 {
177 logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than limit of %d octets",
178 (int)sizeof(len));
179 return ASN1_INVALID_LENGTH;
180 }
181
182 len = 0;
183
184 while (n-- > 0)
185 {
186 len = 256*len + *blob->ptr++;
187 blob->len--;
188 }
189 return len;
190 }
191
192 /*
193 * determines if a character string is of type ASN.1 printableString
194 */
195 bool is_printablestring(chunk_t str)
196 {
197 const char printablestring_charset[] =
198 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
199 u_int i;
200
201 for (i = 0; i < str.len; i++)
202 {
203 if (strchr(printablestring_charset, str.ptr[i]) == NULL)
204 return FALSE;
205 }
206 return TRUE;
207 }
208
209 /*
210 * Display a date either in local or UTC time
211 * TODO: Does not seem to be thread save
212 */
213 char* timetoa(const time_t *time, bool utc)
214 {
215 static char buf[30];
216
217 if (*time == 0)
218 sprintf(buf, "--- -- --:--:--%s----", (utc)?" UTC ":" ");
219 else
220 {
221 struct tm *t = (utc)? gmtime(time) : localtime(time);
222 sprintf(buf, "%s %02d %02d:%02d:%02d%s%04d",
223 months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
224 (utc)?" UTC ":" ", t->tm_year + 1900);
225 }
226 return buf;
227 }
228
229 /*
230 * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
231 */
232 time_t asn1totime(const chunk_t *utctime, asn1_t type)
233 {
234 struct tm t;
235 time_t tz_offset;
236 u_char *eot = NULL;
237
238 if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
239 {
240 tz_offset = 0; /* Zulu time with a zero time zone offset */
241 }
242 else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL)
243 {
244 int tz_hour, tz_min;
245
246 sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
247 tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
248 }
249 else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL)
250 {
251 int tz_hour, tz_min;
252
253 sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
254 tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */
255 }
256 else
257 {
258 return 0; /* error in time format */
259 }
260
261 {
262 const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
263 "%4d%2d%2d%2d%2d";
264
265 sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday,
266 &t.tm_hour, &t.tm_min);
267 }
268
269 /* is there a seconds field? */
270 if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14))
271 {
272 sscanf(eot-2, "%2d", &t.tm_sec);
273 }
274 else
275 {
276 t.tm_sec = 0;
277 }
278
279 /* representation of year */
280 if (t.tm_year >= 1900)
281 {
282 t.tm_year -= 1900;
283 }
284 else if (t.tm_year >= 100)
285 {
286 return 0;
287 }
288 else if (t.tm_year < 50)
289 {
290 t.tm_year += 100;
291 }
292
293 /* representation of month 0..11*/
294 t.tm_mon--;
295
296 /* set daylight saving time to off */
297 t.tm_isdst = 0;
298
299 /* compensate timezone */
300
301 return mktime(&t) - timezone - tz_offset;
302 }
303
304 /*
305 * Initializes the internal context of the ASN.1 parser
306 */
307 void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit)
308 {
309 logger = logger_manager->get_logger(logger_manager, ASN1);
310 ctx->blobs[0] = blob;
311 ctx->level0 = level0;
312 ctx->implicit = implicit;
313 memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr));
314 }
315
316 /*
317 * print the value of an ASN.1 simple object
318 */
319 static void debug_asn1_simple_object(chunk_t object, asn1_t type)
320 {
321 int oid;
322 time_t time;
323
324 switch (type)
325 {
326 case ASN1_OID:
327 oid = known_oid(object);
328 if (oid != OID_UNKNOWN)
329 {
330 logger->log(logger, CONTROL|LEVEL1, " '%s'", oid_names[oid].name);
331 return;
332 }
333 break;
334 case ASN1_UTF8STRING:
335 case ASN1_IA5STRING:
336 case ASN1_PRINTABLESTRING:
337 case ASN1_T61STRING:
338 case ASN1_VISIBLESTRING:
339 logger->log(logger, CONTROL|LEVEL1, " '%.*s'", (int)object.len, object.ptr);
340 return;
341 case ASN1_UTCTIME:
342 case ASN1_GENERALIZEDTIME:
343 time = asn1totime(&object, type);
344 logger->log(logger, CONTROL|LEVEL1, " '%s'", timetoa(&time, TRUE));
345 return;
346 default:
347 break;
348 }
349 logger->log_chunk(logger, RAW|LEVEL1, "", object);
350 }
351
352 /*
353 * Parses and extracts the next ASN.1 object
354 */
355 bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx)
356 {
357 asn1Object_t obj = objects[*objectID];
358 chunk_t *blob;
359 chunk_t *blob1;
360 u_char *start_ptr;
361
362 *object = CHUNK_INITIALIZER;
363
364 if (obj.flags & ASN1_END) /* end of loop or option found */
365 {
366 if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0)
367 {
368 *objectID = ctx->loopAddr[obj.level]; /* another iteration */
369 obj = objects[*objectID];
370 }
371 else
372 {
373 ctx->loopAddr[obj.level] = 0; /* exit loop or option*/
374 return TRUE;
375 }
376 }
377
378 *level = ctx->level0 + obj.level;
379 blob = ctx->blobs + obj.level;
380 blob1 = blob + 1;
381 start_ptr = blob->ptr;
382
383 /* handle ASN.1 defaults values */
384 if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
385 {
386 /* field is missing */
387 logger->log(logger, CONTROL|LEVEL1, "L%d - %s:", *level, obj.name);
388 if (obj.type & ASN1_CONSTRUCTED)
389 {
390 (*objectID)++ ; /* skip context-specific tag */
391 }
392 return TRUE;
393 }
394
395 /* handle ASN.1 options */
396
397 if ((obj.flags & ASN1_OPT)
398 && (blob->len == 0 || *start_ptr != obj.type))
399 {
400 /* advance to end of missing option field */
401 do
402 (*objectID)++;
403 while (!((objects[*objectID].flags & ASN1_END)
404 && (objects[*objectID].level == obj.level)));
405 return TRUE;
406 }
407
408 /* an ASN.1 object must possess at least a tag and length field */
409
410 if (blob->len < 2)
411 {
412 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets",
413 *level, obj.name);
414 return FALSE;
415 }
416
417 blob1->len = asn1_length(blob);
418
419 if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
420 {
421 logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large",
422 *level, obj.name);
423 return FALSE;
424 }
425
426 blob1->ptr = blob->ptr;
427 blob->ptr += blob1->len;
428 blob->len -= blob1->len;
429
430 /* return raw ASN.1 object without prior type checking */
431
432 if (obj.flags & ASN1_RAW)
433 {
434 logger->log(logger, CONTROL|LEVEL1, "L%d - %s:", *level, obj.name);
435 object->ptr = start_ptr;
436 object->len = (size_t)(blob->ptr - start_ptr);
437 return TRUE;
438 }
439
440 if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0))
441 {
442 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
443 *level, obj.name, obj.type, *start_ptr);
444 logger->log_bytes(logger, RAW|LEVEL1, "", start_ptr, (u_int)(blob->ptr - start_ptr));
445 return FALSE;
446 }
447
448 logger->log(logger, CONTROL|LEVEL1, "L%d - %s:", ctx->level0+obj.level, obj.name);
449
450 /* In case of "SEQUENCE OF" or "SET OF" start a loop */
451 if (obj.flags & ASN1_LOOP)
452 {
453 if (blob1->len > 0)
454 {
455 /* at least one item, start the loop */
456 ctx->loopAddr[obj.level] = *objectID + 1;
457 }
458 else
459 {
460 /* no items, advance directly to end of loop */
461 do
462 (*objectID)++;
463 while (!((objects[*objectID].flags & ASN1_END)
464 && (objects[*objectID].level == obj.level)));
465 return TRUE;
466 }
467 }
468
469 if (obj.flags & ASN1_OBJ)
470 {
471 object->ptr = start_ptr;
472 object->len = (size_t)(blob->ptr - start_ptr);
473 logger->log_chunk(logger, RAW|LEVEL1, "", *object);
474 }
475 else if (obj.flags & ASN1_BODY)
476 {
477 *object = *blob1;
478 debug_asn1_simple_object(*object, obj.type);
479 }
480 return TRUE;
481 }
482
483 /*
484 * parse an ASN.1 simple type
485 */
486 bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
487 {
488 size_t len;
489
490 /* an ASN.1 object must possess at least a tag and length field */
491 if (object->len < 2)
492 {
493 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets",
494 level, name);
495 return FALSE;
496 }
497
498 if (*object->ptr != type)
499 {
500 logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
501 level, name, type, *object->ptr);
502 return FALSE;
503 }
504
505 len = asn1_length(object);
506
507 if (len == ASN1_INVALID_LENGTH || object->len < len)
508 {
509 logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large",
510 level, name);
511 return FALSE;
512 }
513
514 logger->log(logger, CONTROL|LEVEL1, "L%d - %s:", level, name);
515 debug_asn1_simple_object(*object, type);
516 return TRUE;
517 }
518
519 /*
520 * extracts an algorithmIdentifier
521 */
522 int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
523 {
524 asn1_ctx_t ctx;
525 chunk_t object;
526 u_int level;
527 int alg = OID_UNKNOWN;
528 int objectID = 0;
529
530 asn1_init(&ctx, blob, level0, FALSE);
531
532 while (objectID < ALGORITHM_ID_ROOF)
533 {
534 if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx))
535 return OID_UNKNOWN;
536
537 switch (objectID)
538 {
539 case ALGORITHM_ID_ALG:
540 alg = known_oid(object);
541 break;
542 case ALGORITHM_ID_PARAMETERS:
543 if (parameters != NULL)
544 *parameters = object;
545 break;
546 default:
547 break;
548 }
549 objectID++;
550 }
551 return alg;
552 }
553
554 /*
555 * tests if a blob contains a valid ASN.1 set or sequence
556 */
557 bool is_asn1(chunk_t blob)
558 {
559 u_int len;
560 u_char tag = *blob.ptr;
561
562 if (tag != ASN1_SEQUENCE && tag != ASN1_SET)
563 {
564 logger->log(logger, ERROR|LEVEL2, " file content is not binary ASN.1");
565 return FALSE;
566 }
567 len = asn1_length(&blob);
568 if (len != blob.len)
569 {
570 logger->log(logger, ERROR|LEVEL2, " file size does not match ASN.1 coded length");
571 return FALSE;
572 }
573 return TRUE;
574 }