]>
git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/asn1/asn1.c
2 * Copyright (C) 2006 Martin Will
3 * Copyright (C) 2000-2016 Andreas Steffen
6 * Copyright (C) secunet Security Networks AG
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include <utils/debug.h>
27 #include "asn1_parser.h"
30 * Commonly used ASN1 values.
32 const chunk_t ASN1_INTEGER_0
= chunk_from_chars(0x02, 0x01, 0x00);
33 const chunk_t ASN1_INTEGER_1
= chunk_from_chars(0x02, 0x01, 0x01);
34 const chunk_t ASN1_INTEGER_2
= chunk_from_chars(0x02, 0x01, 0x02);
39 chunk_t
asn1_algorithmIdentifier_params(int oid
, chunk_t params
)
41 return asn1_wrap(ASN1_SEQUENCE
, "mm", asn1_build_known_oid(oid
), params
);
47 chunk_t
asn1_algorithmIdentifier(int oid
)
51 /* some algorithmIdentifiers have a NULL parameters field and some do not */
54 case OID_ECDSA_WITH_SHA1
:
55 case OID_ECDSA_WITH_SHA224
:
56 case OID_ECDSA_WITH_SHA256
:
57 case OID_ECDSA_WITH_SHA384
:
58 case OID_ECDSA_WITH_SHA512
:
61 parameters
= chunk_empty
;
64 parameters
= asn1_simple_object(ASN1_NULL
, chunk_empty
);
67 return asn1_algorithmIdentifier_params(oid
, parameters
);
73 int asn1_known_oid(chunk_t object
)
79 if (oid_names
[oid
].octet
== *object
.ptr
)
81 if (--object
.len
== 0 || oid_names
[oid
].down
== 0)
83 return oid
; /* found terminal symbol */
87 object
.ptr
++; oid
++; /* advance to next hex octet */
92 if (oid_names
[oid
].next
)
94 oid
= oid_names
[oid
].next
;
108 chunk_t
asn1_build_known_oid(int n
)
113 if (n
< 0 || n
>= OID_MAX
)
118 i
= oid_names
[n
].level
+ 1;
119 oid
= chunk_alloc(2 + i
);
120 oid
.ptr
[0] = ASN1_OID
;
125 if (oid_names
[n
].level
>= i
)
130 oid
.ptr
[--i
+ 2] = oid_names
[n
--].octet
;
138 * Returns the number of bytes required to encode the given OID node
140 static int bytes_required(u_int val
)
142 int shift
, required
= 1;
144 /* sufficient to handle 32 bit node numbers */
145 for (shift
= 28; shift
; shift
-= 7)
148 { /* do not encode leading zeroes */
158 chunk_t
asn1_oid_from_string(char *str
)
160 enumerator_t
*enumerator
;
164 int i
= 0, pos
= 0, req
, shift
;
165 u_int val
, first
= 0;
167 enumerator
= enumerator_create_token(str
, ".", "");
168 while (enumerator
->enumerate(enumerator
, &str
))
170 val
= strtoul(str
, &end
, 10);
171 req
= bytes_required(val
);
172 if (end
== str
|| pos
+ req
> buf_len
)
183 buf
[pos
++] = first
* 40 + val
;
186 for (shift
= (req
- 1) * 7; shift
; shift
-= 7)
188 buf
[pos
++] = 0x80 | ((val
>> shift
) & 0x7F);
190 buf
[pos
++] = val
& 0x7F;
193 enumerator
->destroy(enumerator
);
195 return chunk_clone(chunk_create(buf
, pos
));
201 char *asn1_oid_to_string(chunk_t oid
)
204 char buf
[len
], *pos
= buf
;
212 val
= oid
.ptr
[0] / 40;
213 written
= snprintf(buf
, len
, "%u.%u", val
, oid
.ptr
[0] - val
* 40);
214 oid
= chunk_skip(oid
, 1);
215 if (written
< 0 || written
>= len
)
225 val
= (val
<< 7) + (u_int
)(oid
.ptr
[0] & 0x7f);
227 if (oid
.ptr
[0] < 128)
229 written
= snprintf(pos
, len
, ".%u", val
);
230 if (written
< 0 || written
>= len
)
238 oid
= chunk_skip(oid
, 1);
240 return (val
== 0) ? strdup(buf
) : NULL
;
246 size_t asn1_length(chunk_t
*blob
)
253 DBG2(DBG_ASN
, "insufficient number of octets to parse ASN.1 length");
254 return ASN1_INVALID_LENGTH
;
257 /* read length field, skip tag and length */
263 { /* single length octet */
266 DBG2(DBG_ASN
, "length is larger than remaining blob size");
267 return ASN1_INVALID_LENGTH
;
272 /* composite length, determine number of length octets */
275 if (n
== 0 || n
> blob
->len
)
277 DBG2(DBG_ASN
, "number of length octets invalid");
278 return ASN1_INVALID_LENGTH
;
283 DBG2(DBG_ASN
, "number of length octets is larger than limit of"
284 " %d octets", (int)sizeof(len
));
285 return ASN1_INVALID_LENGTH
;
292 len
= 256*len
+ *blob
->ptr
++;
297 DBG2(DBG_ASN
, "length is larger than remaining blob size");
298 return ASN1_INVALID_LENGTH
;
306 int asn1_unwrap(chunk_t
*blob
, chunk_t
*inner
)
318 *blob
= chunk_skip(*blob
, 2);
320 if ((len
& 0x80) == 0)
321 { /* single length octet */
325 { /* composite length, determine number of length octets */
327 if (len
== 0 || len
> blob
->len
|| len
> sizeof(res
.len
))
334 res
.len
= 256 * res
.len
+ blob
->ptr
[0];
335 *blob
= chunk_skip(*blob
, 1);
338 if (res
.len
> blob
->len
)
343 *blob
= chunk_skip(*blob
, res
.len
);
344 /* updating inner not before we are finished allows a caller to pass
350 static const int days
[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
351 static const int tm_leap_1970
= 477;
354 * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calendar time
356 time_t asn1_to_time(const chunk_t
*utctime
, asn1_t type
)
358 int tm_year
, tm_mon
, tm_day
, tm_hour
, tm_min
, tm_sec
;
359 int tm_leap_4
, tm_leap_100
, tm_leap_400
, tm_leap
;
360 int tz_hour
, tz_min
, tz_offset
;
361 time_t tm_days
, tm_secs
;
362 char buf
[BUF_LEN
], *eot
= NULL
;
364 snprintf(buf
, sizeof(buf
), "%.*s", (int)utctime
->len
, utctime
->ptr
);
366 if ((eot
= strchr(buf
, 'Z')) != NULL
)
368 tz_offset
= 0; /* Zulu time with a zero time zone offset */
370 else if ((eot
= strchr(buf
, '+')) != NULL
)
372 if (sscanf(eot
+1, "%2d%2d", &tz_hour
, &tz_min
) != 2)
374 return 0; /* error in positive timezone offset format */
376 tz_offset
= 3600*tz_hour
+ 60*tz_min
; /* positive time zone offset */
378 else if ((eot
= strchr(buf
, '-')) != NULL
)
380 if (sscanf(eot
+1, "%2d%2d", &tz_hour
, &tz_min
) != 2)
382 return 0; /* error in negative timezone offset format */
384 tz_offset
= -3600*tz_hour
- 60*tz_min
; /* negative time zone offset */
388 return 0; /* error in time format */
391 /* parse ASN.1 time string */
393 const char* format
= (type
== ASN1_UTCTIME
)? "%2d%2d%2d%2d%2d":
396 if (sscanf(buf
, format
, &tm_year
, &tm_mon
, &tm_day
,
397 &tm_hour
, &tm_min
) != 5)
399 return 0; /* error in [yy]yymmddhhmm time format */
403 /* is there a seconds field? */
404 if ((eot
- buf
) == ((type
== ASN1_UTCTIME
)?12:14))
406 if (sscanf(eot
-2, "%2d", &tm_sec
) != 1)
408 return 0; /* error in ss seconds field format */
416 /* representation of two-digit years */
417 if (type
== ASN1_UTCTIME
)
419 tm_year
+= (tm_year
< 50) ? 2000 : 1900;
422 /* prevent obvious 32 bit integer overflows */
423 if (sizeof(time_t) == 4 && (tm_year
> 2038 || tm_year
< 1901))
425 return TIME_32_BIT_SIGNED_MAX
;
428 /* representation of months as 0..11*/
429 if (tm_mon
< 1 || tm_mon
> 12)
435 /* representation of days as 0..30 */
436 if (tm_day
< 1 || tm_day
> 31)
437 { /* we don't actually validate the day in relation to tm_year/tm_mon */
442 if (tm_hour
< 0 || tm_hour
> 23 ||
443 tm_min
< 0 || tm_min
> 59 ||
444 tm_sec
< 0 || tm_sec
> 60 /* allow leap seconds */)
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
;
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))
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
;
464 if (sizeof(time_t) == 4)
465 { /* has a 32 bit signed integer overflow occurred? */
466 if (tm_year
> 1970 && tm_secs
< 0)
467 { /* depending on the time zone, the first days in 1970 may result in
468 * a negative value, but dates after 1970 never will */
469 return TIME_32_BIT_SIGNED_MAX
;
471 if (tm_year
< 1969 && tm_secs
> 0)
472 { /* similarly, tm_secs is not positive for dates before 1970, except
473 * for the last days in 1969, depending on the time zone */
474 return TIME_32_BIT_SIGNED_MAX
;
481 * Convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
483 chunk_t
asn1_from_time(const time_t *time
, asn1_t type
)
488 chunk_t formatted_time
;
492 /* RFC 5280 says that dates through the year 2049 MUST be encoded as UTCTIME
493 * and dates in 2050 or later MUST be encoded as GENERALIZEDTIME. We only
494 * enforce the latter to avoid overflows but allow callers to force the
495 * encoding to GENERALIZEDTIME */
496 type
= (t
.tm_year
>= 150) ? ASN1_GENERALIZEDTIME
: type
;
497 if (type
== ASN1_GENERALIZEDTIME
)
499 format
= "%04d%02d%02d%02d%02d%02dZ";
502 else /* ASN1_UTCTIME */
504 format
= "%02d%02d%02d%02d%02d%02dZ";
505 offset
= (t
.tm_year
< 100) ? 0 : -100;
507 snprintf(buf
, BUF_LEN
, format
, t
.tm_year
+ offset
,
508 t
.tm_mon
+ 1, t
.tm_mday
, t
.tm_hour
, t
.tm_min
, t
.tm_sec
);
509 formatted_time
.ptr
= buf
;
510 formatted_time
.len
= strlen(buf
);
511 return asn1_simple_object(type
, formatted_time
);
517 void asn1_debug_simple_object(chunk_t object
, asn1_t type
, bool private)
524 oid
= asn1_known_oid(object
);
525 if (oid
== OID_UNKNOWN
)
527 char *oid_str
= asn1_oid_to_string(object
);
533 DBG2(DBG_ASN
, " %s", oid_str
);
538 DBG2(DBG_ASN
, " '%s'", oid_names
[oid
].name
);
541 case ASN1_UTF8STRING
:
543 case ASN1_PRINTABLESTRING
:
545 case ASN1_VISIBLESTRING
:
546 DBG2(DBG_ASN
, " '%.*s'", (int)object
.len
, object
.ptr
);
549 case ASN1_GENERALIZEDTIME
:
551 time_t time
= asn1_to_time(&object
, type
);
553 DBG2(DBG_ASN
, " '%T'", &time
, TRUE
);
561 DBG4(DBG_ASN
, "%B", &object
);
565 DBG3(DBG_ASN
, "%B", &object
);
570 * parse an ASN.1 simple type
572 bool asn1_parse_simple_object(chunk_t
*object
, asn1_t type
, u_int level
, const char* name
)
576 /* an ASN.1 object must possess at least a tag and length field */
579 DBG2(DBG_ASN
, "L%d - %s: ASN.1 object smaller than 2 octets", level
,
584 if (*object
->ptr
!= type
)
586 DBG2(DBG_ASN
, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
587 level
, name
, type
, *object
->ptr
);
591 len
= asn1_length(object
);
593 if (len
== ASN1_INVALID_LENGTH
)
595 DBG2(DBG_ASN
, "L%d - %s: length of ASN.1 object invalid or too large",
600 DBG2(DBG_ASN
, "L%d - %s:", level
, name
);
601 asn1_debug_simple_object(*object
, type
, FALSE
);
606 * Described in header
608 uint64_t asn1_parse_integer_uint64(chunk_t blob
)
613 for (i
= 0; i
< blob
.len
; i
++)
614 { /* if it is longer than 8 bytes, we just use the 8 LSBs */
616 val
|= (uint64_t)blob
.ptr
[i
];
622 * Described in header
624 chunk_t
asn1_integer_from_uint64(uint64_t val
)
626 u_char buf
[sizeof(val
)];
627 chunk_t enc
= chunk_empty
;
631 buf
[0] = (u_char
)val
;
632 return chunk_clone(chunk_create(buf
, 1));
634 for (enc
.ptr
= buf
+ sizeof(val
); val
; enc
.len
++, val
>>= 8)
635 { /* fill the buffer from the end */
636 *(--enc
.ptr
) = val
& 0xff;
638 return chunk_clone(enc
);
642 * Described in header
644 int asn1_parse_algorithmIdentifier(chunk_t blob
, int level0
, chunk_t
*parameters
)
647 int alg
= OID_UNKNOWN
;
649 if (asn1_unwrap(&blob
, &blob
) == ASN1_SEQUENCE
)
651 DBG2(DBG_ASN
, "L%d - algorithmIdentifier:", level0
);
653 if (asn1_unwrap(&blob
, &object
) == ASN1_OID
)
655 DBG2(DBG_ASN
, "L%d - algorithm:", level0
+1);
656 asn1_debug_simple_object(object
, ASN1_OID
, FALSE
);
657 alg
= asn1_known_oid(object
);
661 DBG2(DBG_ASN
, "L%d - parameters:", level0
+1);
662 DBG3(DBG_ASN
, "%B", &blob
);
674 * tests if a blob contains a valid ASN.1 set or sequence
676 bool is_asn1(chunk_t blob
)
681 if (!blob
.len
|| !blob
.ptr
)
687 if (tag
!= ASN1_SEQUENCE
&& tag
!= ASN1_SET
&& tag
!= ASN1_OCTET_STRING
)
689 DBG2(DBG_ASN
, " file content is not binary ASN.1");
693 len
= asn1_length(&blob
);
695 if (len
== ASN1_INVALID_LENGTH
)
706 /* some websites append a surplus newline character to the blob */
707 if (len
+ 1 == blob
.len
&& *(blob
.ptr
+ len
) == '\n')
712 DBG2(DBG_ASN
, " file size does not match ASN.1 coded length");
719 bool asn1_is_printablestring(chunk_t str
)
721 const char printablestring_charset
[] =
722 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
725 for (i
= 0; i
< str
.len
; i
++)
727 if (strchr(printablestring_charset
, str
.ptr
[i
]) == NULL
)
736 * codes ASN.1 lengths up to a size of 16'777'215 bytes
738 static void asn1_code_length(size_t length
, chunk_t
*code
)
742 code
->ptr
[0] = length
;
745 else if (length
< 256)
748 code
->ptr
[1] = (u_char
) length
;
751 else if (length
< 65536)
754 code
->ptr
[1] = length
>> 8;
755 code
->ptr
[2] = length
& 0x00ff;
761 code
->ptr
[1] = length
>> 16;
762 code
->ptr
[2] = (length
>> 8) & 0x00ff;
763 code
->ptr
[3] = length
& 0x0000ff;
769 * build an empty asn.1 object with tag and length fields already filled in
771 u_char
* asn1_build_object(chunk_t
*object
, asn1_t type
, size_t datalen
)
773 u_char length_buf
[4];
774 chunk_t length
= { length_buf
, 0 };
777 /* code the asn.1 length field */
778 asn1_code_length(datalen
, &length
);
780 /* allocate memory for the asn.1 TLV object */
781 object
->len
= 1 + length
.len
+ datalen
;
782 object
->ptr
= malloc(object
->len
);
784 /* set position pointer at the start of the object */
787 /* copy the asn.1 tag field and advance the pointer */
790 /* copy the asn.1 length field and advance the pointer */
791 memcpy(pos
, length
.ptr
, length
.len
);
798 * Build a simple ASN.1 object
800 chunk_t
asn1_simple_object(asn1_t tag
, chunk_t content
)
804 u_char
*pos
= asn1_build_object(&object
, tag
, content
.len
);
805 memcpy(pos
, content
.ptr
, content
.len
);
811 * Build an ASN.1 BIT_STRING object
813 chunk_t
asn1_bitstring(const char *mode
, chunk_t content
)
816 u_char
*pos
= asn1_build_object(&object
, ASN1_BIT_STRING
, 1 + content
.len
);
819 memcpy(pos
, content
.ptr
, content
.len
);
828 * Build an ASN.1 INTEGER object
830 chunk_t
asn1_integer(const char *mode
, chunk_t content
)
832 chunk_t zero
= chunk_from_chars(0x00), object
;
837 if (content
.len
== 0)
838 { /* make sure 0 is encoded properly */
844 move
= (*mode
== 'm');
847 /* ASN.1 integers must be positive numbers in two's complement */
848 len
= content
.len
+ ((*content
.ptr
& 0x80) ? 1 : 0);
849 pos
= asn1_build_object(&object
, ASN1_INTEGER
, len
);
850 if (len
> content
.len
)
854 memcpy(pos
, content
.ptr
, content
.len
);
864 * Build an ASN.1 object from a variable number of individual chunks.
865 * Depending on the mode, chunks either are moved ('m') or copied ('c').
867 chunk_t
asn1_wrap(asn1_t type
, const char *mode
, ...)
873 int count
= strlen(mode
);
875 /* sum up lengths of individual chunks */
876 va_start(chunks
, mode
);
878 for (i
= 0; i
< count
; i
++)
880 chunk_t ch
= va_arg(chunks
, chunk_t
);
881 construct
.len
+= ch
.len
;
885 /* allocate needed memory for construct */
886 pos
= asn1_build_object(&construct
, type
, construct
.len
);
888 /* copy or move the chunks */
889 va_start(chunks
, mode
);
890 for (i
= 0; i
< count
; i
++)
892 chunk_t ch
= va_arg(chunks
, chunk_t
);
894 memcpy(pos
, ch
.ptr
, ch
.len
);
915 * ASN.1 definition of time
917 static const asn1Object_t timeObjects
[] = {
918 { 0, "utcTime", ASN1_UTCTIME
, ASN1_OPT
|ASN1_BODY
}, /* 0 */
919 { 0, "end opt", ASN1_EOC
, ASN1_END
}, /* 1 */
920 { 0, "generalizeTime", ASN1_GENERALIZEDTIME
, ASN1_OPT
|ASN1_BODY
}, /* 2 */
921 { 0, "end opt", ASN1_EOC
, ASN1_END
}, /* 3 */
922 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
925 /* used by C11 timespec_get(), <time.h> */
929 #define TIME_GENERALIZED 2
932 * extracts and converts a UTCTIME or GENERALIZEDTIME object
934 time_t asn1_parse_time(chunk_t blob
, int level0
)
936 asn1_parser_t
*parser
;
941 parser
= asn1_parser_create(timeObjects
, blob
);
942 parser
->set_top_level(parser
, level0
);
944 while (parser
->iterate(parser
, &objectID
, &object
))
946 if (objectID
== TIME_UTC
|| objectID
== TIME_GENERALIZED
)
948 utc_time
= asn1_to_time(&object
, (objectID
== TIME_UTC
)
949 ? ASN1_UTCTIME
: ASN1_GENERALIZEDTIME
);
952 parser
->destroy(parser
);