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