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