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