merged the modularization branch (credentials) back to trunk
[strongswan.git] / src / libstrongswan / asn1 / asn1.c
1 /*
2 * Copyright (C) 2006 Martin Will
3 * Copyright (C) 2000-2008 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <time.h>
22
23 #include "asn1.h"
24
25 #include <library.h>
26 #include <debug.h>
27
28 /* some common prefabricated ASN.1 constants */
29 static u_char ASN1_INTEGER_0_str[] = { 0x02, 0x00 };
30 static u_char ASN1_INTEGER_1_str[] = { 0x02, 0x01, 0x01 };
31 static u_char ASN1_INTEGER_2_str[] = { 0x02, 0x01, 0x02 };
32
33 const chunk_t ASN1_INTEGER_0 = chunk_from_buf(ASN1_INTEGER_0_str);
34 const chunk_t ASN1_INTEGER_1 = chunk_from_buf(ASN1_INTEGER_1_str);
35 const chunk_t ASN1_INTEGER_2 = chunk_from_buf(ASN1_INTEGER_2_str);
36
37 /* some popular algorithmIdentifiers */
38
39 static u_char ASN1_md2_id_str[] = {
40 0x30, 0x0c,
41 0x06, 0x08,
42 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02,
43 0x05,0x00,
44 };
45
46 static u_char ASN1_md5_id_str[] = {
47 0x30, 0x0C,
48 0x06, 0x08,
49 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,
50 0x05, 0x00
51 };
52
53 static u_char ASN1_sha1_id_str[] = {
54 0x30, 0x09,
55 0x06, 0x05,
56 0x2B, 0x0E,0x03, 0x02, 0x1A,
57 0x05, 0x00
58 };
59
60 static u_char ASN1_sha256_id_str[] = {
61 0x30, 0x0d,
62 0x06, 0x09,
63 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
64 0x05, 0x00
65 };
66
67 static u_char ASN1_sha384_id_str[] = {
68 0x30, 0x0d,
69 0x06, 0x09,
70 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
71 0x05, 0x00
72 };
73
74 static u_char ASN1_sha512_id_str[] = {
75 0x30, 0x0d,
76 0x06, 0x09,
77 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
78 0x05,0x00
79 };
80
81 static u_char ASN1_md2WithRSA_id_str[] = {
82 0x30, 0x0D,
83 0x06, 0x09,
84 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x02,
85 0x05, 0x00
86 };
87
88 static u_char ASN1_md5WithRSA_id_str[] = {
89 0x30, 0x0D,
90 0x06, 0x09,
91 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04,
92 0x05, 0x00
93 };
94
95 static u_char ASN1_sha1WithRSA_id_str[] = {
96 0x30, 0x0D,
97 0x06, 0x09,
98 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
99 0x05, 0x00
100 };
101
102 static u_char ASN1_sha256WithRSA_id_str[] = {
103 0x30, 0x0D,
104 0x06, 0x09,
105 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
106 0x05, 0x00
107 };
108
109 static u_char ASN1_sha384WithRSA_id_str[] = {
110 0x30, 0x0D,
111 0x06, 0x09,
112 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C,
113 0x05, 0x00
114 };
115
116 static u_char ASN1_sha512WithRSA_id_str[] = {
117 0x30, 0x0D,
118 0x06, 0x09,
119 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D,
120 0x05, 0x00
121 };
122
123 static u_char ASN1_rsaEncryption_id_str[] = {
124 0x30, 0x0D,
125 0x06, 0x09,
126 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
127 0x05, 0x00
128 };
129
130 static const chunk_t ASN1_md2_id = chunk_from_buf(ASN1_md2_id_str);
131 static const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str);
132 static const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str);
133 static const chunk_t ASN1_sha256_id = chunk_from_buf(ASN1_sha256_id_str);
134 static const chunk_t ASN1_sha384_id = chunk_from_buf(ASN1_sha384_id_str);
135 static const chunk_t ASN1_sha512_id = chunk_from_buf(ASN1_sha512_id_str);
136 static const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str);
137 static const chunk_t ASN1_md2WithRSA_id = chunk_from_buf(ASN1_md2WithRSA_id_str);
138 static const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str);
139 static const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str);
140 static const chunk_t ASN1_sha256WithRSA_id = chunk_from_buf(ASN1_sha256WithRSA_id_str);
141 static const chunk_t ASN1_sha384WithRSA_id = chunk_from_buf(ASN1_sha384WithRSA_id_str);
142 static const chunk_t ASN1_sha512WithRSA_id = chunk_from_buf(ASN1_sha512WithRSA_id_str);
143
144 /* ASN.1 definiton of an algorithmIdentifier */
145 static const asn1Object_t algorithmIdentifierObjects[] = {
146 { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
147 { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
148 { 1, "parameters", ASN1_EOC, ASN1_RAW } /* 2 */
149 };
150
151 #define ALGORITHM_ID_ALG 1
152 #define ALGORITHM_ID_PARAMETERS 2
153 #define ALGORITHM_ID_ROOF 3
154
155 /**
156 * return the ASN.1 encoded algorithm identifier
157 */
158 chunk_t asn1_algorithmIdentifier(int oid)
159 {
160 switch (oid)
161 {
162 case OID_RSA_ENCRYPTION:
163 return ASN1_rsaEncryption_id;
164 case OID_MD2_WITH_RSA:
165 return ASN1_md2WithRSA_id;
166 case OID_MD5_WITH_RSA:
167 return ASN1_md5WithRSA_id;
168 case OID_SHA1_WITH_RSA:
169 return ASN1_sha1WithRSA_id;
170 case OID_SHA256_WITH_RSA:
171 return ASN1_sha256WithRSA_id;
172 case OID_SHA384_WITH_RSA:
173 return ASN1_sha384WithRSA_id;
174 case OID_SHA512_WITH_RSA:
175 return ASN1_sha512WithRSA_id;
176 case OID_MD2:
177 return ASN1_md2_id;
178 case OID_MD5:
179 return ASN1_md5_id;
180 case OID_SHA1:
181 return ASN1_sha1_id;
182 case OID_SHA256:
183 return ASN1_sha256_id;
184 case OID_SHA384:
185 return ASN1_sha384_id;
186 case OID_SHA512:
187 return ASN1_sha512_id;
188 default:
189 return chunk_empty;
190 }
191 }
192
193 /**
194 * If the oid is listed in the oid_names table then the corresponding
195 * position in the oid_names table is returned otherwise -1 is returned
196 */
197 int known_oid(chunk_t object)
198 {
199 int oid = 0;
200
201 while (object.len)
202 {
203 if (oid_names[oid].octet == *object.ptr)
204 {
205 if (--object.len == 0 || oid_names[oid].down == 0)
206 {
207 return oid; /* found terminal symbol */
208 }
209 else
210 {
211 object.ptr++; oid++; /* advance to next hex octet */
212 }
213 }
214 else
215 {
216 if (oid_names[oid].next)
217 oid = oid_names[oid].next;
218 else
219 return OID_UNKNOWN;
220 }
221 }
222 return -1;
223 }
224
225 /**
226 * Decodes the length in bytes of an ASN.1 object
227 */
228 u_int asn1_length(chunk_t *blob)
229 {
230 u_char n;
231 size_t len;
232
233 /* advance from tag field on to length field */
234 blob->ptr++;
235 blob->len--;
236
237 /* read first octet of length field */
238 n = *blob->ptr++;
239 blob->len--;
240
241 if ((n & 0x80) == 0)
242 {/* single length octet */
243 return n;
244 }
245
246 /* composite length, determine number of length octets */
247 n &= 0x7f;
248
249 if (n > blob->len)
250 {
251 DBG2("number of length octets is larger than ASN.1 object");
252 return ASN1_INVALID_LENGTH;
253 }
254
255 if (n > sizeof(len))
256 {
257 DBG2("number of length octets is larger than limit of %d octets",
258 (int)sizeof(len));
259 return ASN1_INVALID_LENGTH;
260 }
261
262 len = 0;
263
264 while (n-- > 0)
265 {
266 len = 256*len + *blob->ptr++;
267 blob->len--;
268 }
269 return len;
270 }
271
272 /**
273 * determines if a character string is of type ASN.1 printableString
274 */
275 bool is_printablestring(chunk_t str)
276 {
277 const char printablestring_charset[] =
278 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
279 u_int i;
280
281 for (i = 0; i < str.len; i++)
282 {
283 if (strchr(printablestring_charset, str.ptr[i]) == NULL)
284 return FALSE;
285 }
286 return TRUE;
287 }
288
289 /**
290 * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
291 */
292 time_t asn1totime(const chunk_t *utctime, asn1_t type)
293 {
294 struct tm t;
295 time_t tz_offset;
296 u_char *eot = NULL;
297
298 if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
299 {
300 tz_offset = 0; /* Zulu time with a zero time zone offset */
301 }
302 else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL)
303 {
304 int tz_hour, tz_min;
305
306 sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
307 tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
308 }
309 else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL)
310 {
311 int tz_hour, tz_min;
312
313 sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
314 tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */
315 }
316 else
317 {
318 return 0; /* error in time format */
319 }
320
321 {
322 const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
323 "%4d%2d%2d%2d%2d";
324
325 sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday,
326 &t.tm_hour, &t.tm_min);
327 }
328
329 /* is there a seconds field? */
330 if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14))
331 {
332 sscanf(eot-2, "%2d", &t.tm_sec);
333 }
334 else
335 {
336 t.tm_sec = 0;
337 }
338
339 /* representation of year */
340 if (t.tm_year >= 1900)
341 {
342 t.tm_year -= 1900;
343 }
344 else if (t.tm_year >= 100)
345 {
346 return 0;
347 }
348 else if (t.tm_year < 50)
349 {
350 t.tm_year += 100;
351 }
352
353 /* representation of month 0..11*/
354 t.tm_mon--;
355
356 /* set daylight saving time to off */
357 t.tm_isdst = 0;
358
359 /* compensate timezone */
360
361 return mktime(&t) - timezone - tz_offset;
362 }
363
364 /**
365 * Convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
366 */
367 chunk_t timetoasn1(const time_t *time, asn1_t type)
368 {
369 int offset;
370 const char *format;
371 char buf[BUF_LEN];
372 chunk_t formatted_time;
373 struct tm *t = gmtime(time);
374
375 if (type == ASN1_GENERALIZEDTIME)
376 {
377 format = "%04d%02d%02d%02d%02d%02dZ";
378 offset = 1900;
379 }
380 else /* ASN1_UTCTIME */
381 {
382 format = "%02d%02d%02d%02d%02d%02dZ";
383 offset = (t->tm_year < 100)? 0 : -100;
384 }
385 snprintf(buf, BUF_LEN, format, t->tm_year + offset,
386 t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
387 formatted_time.ptr = buf;
388 formatted_time.len = strlen(buf);
389 return asn1_simple_object(type, formatted_time);
390 }
391
392
393 /**
394 * Initializes the internal context of the ASN.1 parser
395 */
396 void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0,
397 bool implicit, bool private)
398 {
399 ctx->blobs[0] = blob;
400 ctx->level0 = level0;
401 ctx->implicit = implicit;
402 ctx->private = private;
403 memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr));
404 }
405
406 /**
407 * print the value of an ASN.1 simple object
408 */
409 static void debug_asn1_simple_object(chunk_t object, asn1_t type, bool private)
410 {
411 int oid;
412
413 switch (type)
414 {
415 case ASN1_OID:
416 oid = known_oid(object);
417 if (oid != OID_UNKNOWN)
418 {
419 DBG2(" '%s'", oid_names[oid].name);
420 return;
421 }
422 break;
423 case ASN1_UTF8STRING:
424 case ASN1_IA5STRING:
425 case ASN1_PRINTABLESTRING:
426 case ASN1_T61STRING:
427 case ASN1_VISIBLESTRING:
428 DBG2(" '%.*s'", (int)object.len, object.ptr);
429 return;
430 case ASN1_UTCTIME:
431 case ASN1_GENERALIZEDTIME:
432 {
433 time_t time = asn1totime(&object, type);
434
435 DBG2(" '%T'", &time);
436 }
437 return;
438 default:
439 break;
440 }
441 if (private)
442 {
443 DBG4("%B", &object);
444 }
445 else
446 {
447 DBG3("%B", &object);
448 }
449 }
450
451 /**
452 * Parses and extracts the next ASN.1 object
453 */
454 bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx)
455 {
456 asn1Object_t obj = objects[*objectID];
457 chunk_t *blob;
458 chunk_t *blob1;
459 u_char *start_ptr;
460
461 *object = chunk_empty;
462
463 if (obj.flags & ASN1_END) /* end of loop or option found */
464 {
465 if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0)
466 {
467 *objectID = ctx->loopAddr[obj.level]; /* another iteration */
468 obj = objects[*objectID];
469 }
470 else
471 {
472 ctx->loopAddr[obj.level] = 0; /* exit loop or option*/
473 return TRUE;
474 }
475 }
476
477 *level = ctx->level0 + obj.level;
478 blob = ctx->blobs + obj.level;
479 blob1 = blob + 1;
480 start_ptr = blob->ptr;
481
482 /* handle ASN.1 defaults values */
483 if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
484 {
485 /* field is missing */
486 DBG2("L%d - %s:", *level, obj.name);
487 if (obj.type & ASN1_CONSTRUCTED)
488 {
489 (*objectID)++ ; /* skip context-specific tag */
490 }
491 return TRUE;
492 }
493
494 /* handle ASN.1 options */
495
496 if ((obj.flags & ASN1_OPT)
497 && (blob->len == 0 || *start_ptr != obj.type))
498 {
499 /* advance to end of missing option field */
500 do
501 (*objectID)++;
502 while (!((objects[*objectID].flags & ASN1_END)
503 && (objects[*objectID].level == obj.level)));
504 return TRUE;
505 }
506
507 /* an ASN.1 object must possess at least a tag and length field */
508
509 if (blob->len < 2)
510 {
511 DBG1("L%d - %s: ASN.1 object smaller than 2 octets",
512 *level, obj.name);
513 return FALSE;
514 }
515
516 blob1->len = asn1_length(blob);
517
518 if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
519 {
520 DBG1("L%d - %s: length of ASN.1 object invalid or too large",
521 *level, obj.name);
522 return FALSE;
523 }
524
525 blob1->ptr = blob->ptr;
526 blob->ptr += blob1->len;
527 blob->len -= blob1->len;
528
529 /* return raw ASN.1 object without prior type checking */
530
531 if (obj.flags & ASN1_RAW)
532 {
533 DBG2("L%d - %s:", *level, obj.name);
534 object->ptr = start_ptr;
535 object->len = (size_t)(blob->ptr - start_ptr);
536 return TRUE;
537 }
538
539 if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0))
540 {
541 DBG1("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
542 *level, obj.name, obj.type, *start_ptr);
543 DBG3("%b", start_ptr, (u_int)(blob->ptr - start_ptr));
544 return FALSE;
545 }
546
547 DBG2("L%d - %s:", ctx->level0+obj.level, obj.name);
548
549 /* In case of "SEQUENCE OF" or "SET OF" start a loop */
550 if (obj.flags & ASN1_LOOP)
551 {
552 if (blob1->len > 0)
553 {
554 /* at least one item, start the loop */
555 ctx->loopAddr[obj.level] = *objectID + 1;
556 }
557 else
558 {
559 /* no items, advance directly to end of loop */
560 do
561 (*objectID)++;
562 while (!((objects[*objectID].flags & ASN1_END)
563 && (objects[*objectID].level == obj.level)));
564 return TRUE;
565 }
566 }
567
568 if (obj.flags & ASN1_OBJ)
569 {
570 object->ptr = start_ptr;
571 object->len = (size_t)(blob->ptr - start_ptr);
572 if (ctx->private)
573 {
574 DBG4("%B", object);
575 }
576 else
577 {
578 DBG3("%B", object);
579 }
580 }
581 else if (obj.flags & ASN1_BODY)
582 {
583 *object = *blob1;
584 debug_asn1_simple_object(*object, obj.type, ctx->private);
585 }
586 return TRUE;
587 }
588
589 /**
590 * parse an ASN.1 simple type
591 */
592 bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
593 {
594 size_t len;
595
596 /* an ASN.1 object must possess at least a tag and length field */
597 if (object->len < 2)
598 {
599 DBG2("L%d - %s: ASN.1 object smaller than 2 octets", level, name);
600 return FALSE;
601 }
602
603 if (*object->ptr != type)
604 {
605 DBG2("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
606 level, name, type, *object->ptr);
607 return FALSE;
608 }
609
610 len = asn1_length(object);
611
612 if (len == ASN1_INVALID_LENGTH || object->len < len)
613 {
614 DBG2("L%d - %s: length of ASN.1 object invalid or too large",
615 level, name);
616 return FALSE;
617 }
618
619 DBG2("L%d - %s:", level, name);
620 debug_asn1_simple_object(*object, type, FALSE);
621 return TRUE;
622 }
623
624 /**
625 * extracts an algorithmIdentifier
626 */
627 int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
628 {
629 asn1_ctx_t ctx;
630 chunk_t object;
631 u_int level;
632 int alg = OID_UNKNOWN;
633 int objectID = 0;
634
635 asn1_init(&ctx, blob, level0, FALSE, FALSE);
636
637 while (objectID < ALGORITHM_ID_ROOF)
638 {
639 if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx))
640 return OID_UNKNOWN;
641
642 switch (objectID)
643 {
644 case ALGORITHM_ID_ALG:
645 alg = known_oid(object);
646 break;
647 case ALGORITHM_ID_PARAMETERS:
648 if (parameters != NULL)
649 *parameters = object;
650 break;
651 default:
652 break;
653 }
654 objectID++;
655 }
656 return alg;
657 }
658
659 /*
660 * tests if a blob contains a valid ASN.1 set or sequence
661 */
662 bool is_asn1(chunk_t blob)
663 {
664 u_int len;
665 u_char tag = *blob.ptr;
666
667 if (tag != ASN1_SEQUENCE && tag != ASN1_SET)
668 {
669 DBG2(" file content is not binary ASN.1");
670 return FALSE;
671 }
672
673 len = asn1_length(&blob);
674
675 /* exact match */
676 if (len == blob.len)
677 {
678 return TRUE;
679 }
680
681 /* some websites append a surplus newline character to the blob */
682 if (len + 1 == blob.len && *(blob.ptr + len) == '\n')
683 {
684 return TRUE;
685 }
686
687 DBG2(" file size does not match ASN.1 coded length");
688 return FALSE;
689 }
690
691 /**
692 * codes ASN.1 lengths up to a size of 16'777'215 bytes
693 */
694 void code_asn1_length(size_t length, chunk_t *code)
695 {
696 if (length < 128)
697 {
698 code->ptr[0] = length;
699 code->len = 1;
700 }
701 else if (length < 256)
702 {
703 code->ptr[0] = 0x81;
704 code->ptr[1] = (u_char) length;
705 code->len = 2;
706 }
707 else if (length < 65536)
708 {
709 code->ptr[0] = 0x82;
710 code->ptr[1] = length >> 8;
711 code->ptr[2] = length & 0x00ff;
712 code->len = 3;
713 }
714 else
715 {
716 code->ptr[0] = 0x83;
717 code->ptr[1] = length >> 16;
718 code->ptr[2] = (length >> 8) & 0x00ff;
719 code->ptr[3] = length & 0x0000ff;
720 code->len = 4;
721 }
722 }
723
724 /**
725 * build an empty asn.1 object with tag and length fields already filled in
726 */
727 u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen)
728 {
729 u_char length_buf[4];
730 chunk_t length = { length_buf, 0 };
731 u_char *pos;
732
733 /* code the asn.1 length field */
734 code_asn1_length(datalen, &length);
735
736 /* allocate memory for the asn.1 TLV object */
737 object->len = 1 + length.len + datalen;
738 object->ptr = malloc(object->len);
739
740 /* set position pointer at the start of the object */
741 pos = object->ptr;
742
743 /* copy the asn.1 tag field and advance the pointer */
744 *pos++ = type;
745
746 /* copy the asn.1 length field and advance the pointer */
747 memcpy(pos, length.ptr, length.len);
748 pos += length.len;
749
750 return pos;
751 }
752
753 /**
754 * build a simple ASN.1 object
755 */
756 chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
757 {
758 chunk_t object;
759
760 u_char *pos = build_asn1_object(&object, tag, content.len);
761 memcpy(pos, content.ptr, content.len);
762 pos += content.len;
763
764 return object;
765 }
766
767 /**
768 * Build an ASN.1 BITSTRING object
769 */
770 chunk_t asn1_bitstring(const char *mode, chunk_t content)
771 {
772 chunk_t object;
773 u_char *pos = build_asn1_object(&object, ASN1_BIT_STRING, 1 + content.len);
774
775 *pos++ = 0x00;
776 memcpy(pos, content.ptr, content.len);
777 if (*mode == 'm')
778 {
779 free(content.ptr);
780 }
781 return object;
782 }
783
784 /**
785 * Build an ASN.1 object from a variable number of individual chunks.
786 * Depending on the mode, chunks either are moved ('m') or copied ('c').
787 */
788 chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
789 {
790 chunk_t construct;
791 va_list chunks;
792 u_char *pos;
793 int i;
794 int count = strlen(mode);
795
796 /* sum up lengths of individual chunks */
797 va_start(chunks, mode);
798 construct.len = 0;
799 for (i = 0; i < count; i++)
800 {
801 chunk_t ch = va_arg(chunks, chunk_t);
802 construct.len += ch.len;
803 }
804 va_end(chunks);
805
806 /* allocate needed memory for construct */
807 pos = build_asn1_object(&construct, type, construct.len);
808
809 /* copy or move the chunks */
810 va_start(chunks, mode);
811 for (i = 0; i < count; i++)
812 {
813 chunk_t ch = va_arg(chunks, chunk_t);
814
815 memcpy(pos, ch.ptr, ch.len);
816 pos += ch.len;
817
818 if (*mode++ == 'm')
819 {
820 free(ch.ptr);
821 }
822 }
823 va_end(chunks);
824
825 return construct;
826 }
827
828 /**
829 * ASN.1 definition of time
830 */
831 static const asn1Object_t timeObjects[] = {
832 { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */
833 { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
834 { 0, "generalizeTime",ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */
835 { 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */
836 };
837 #define TIME_UTC 0
838 #define TIME_GENERALIZED 2
839 #define TIME_ROOF 4
840
841 /**
842 * extracts and converts a UTCTIME or GENERALIZEDTIME object
843 */
844 time_t parse_time(chunk_t blob, int level0)
845 {
846 asn1_ctx_t ctx;
847 chunk_t object;
848 u_int level;
849 int objectID = 0;
850
851 asn1_init(&ctx, blob, level0, FALSE, FALSE);
852
853 while (objectID < TIME_ROOF)
854 {
855 if (!extract_object(timeObjects, &objectID, &object, &level, &ctx))
856 return 0;
857
858 if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
859 {
860 return asn1totime(&object, (objectID == TIME_UTC)
861 ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
862 }
863 objectID++;
864 }
865 return 0;
866 }