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