2 * Copyright (C) 2006 Martin Will
3 * Copyright (C) 2000-2008 Andreas Steffen
5 * Hochschule fuer Technik Rapperswil
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>.
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
28 #include "asn1_parser.h"
31 * some common prefabricated ASN.1 constants
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 };
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
);
42 * some popular algorithmIdentifiers
45 static u_char ASN1_md2_id_str
[] = {
48 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02,
52 static u_char ASN1_md5_id_str
[] = {
55 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05,
59 static u_char ASN1_sha1_id_str
[] = {
62 0x2B, 0x0E,0x03, 0x02, 0x1A,
66 static u_char ASN1_sha256_id_str
[] = {
69 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
73 static u_char ASN1_sha384_id_str
[] = {
76 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
80 static u_char ASN1_sha512_id_str
[] = {
83 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
87 static u_char ASN1_md2WithRSA_id_str
[] = {
90 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x02,
94 static u_char ASN1_md5WithRSA_id_str
[] = {
97 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04,
101 static u_char ASN1_sha1WithRSA_id_str
[] = {
104 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
108 static u_char ASN1_sha256WithRSA_id_str
[] = {
111 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
115 static u_char ASN1_sha384WithRSA_id_str
[] = {
118 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C,
122 static u_char ASN1_sha512WithRSA_id_str
[] = {
125 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D,
129 static u_char ASN1_rsaEncryption_id_str
[] = {
132 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
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
);
153 chunk_t
asn1_algorithmIdentifier(int oid
)
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
;
178 return ASN1_sha256_id
;
180 return ASN1_sha384_id
;
182 return ASN1_sha512_id
;
191 int asn1_known_oid(chunk_t object
)
197 if (oid_names
[oid
].octet
== *object
.ptr
)
199 if (--object
.len
== 0 || oid_names
[oid
].down
== 0)
201 return oid
; /* found terminal symbol */
205 object
.ptr
++; oid
++; /* advance to next hex octet */
210 if (oid_names
[oid
].next
)
212 oid
= oid_names
[oid
].next
;
226 chunk_t
asn1_build_known_oid(int n
)
231 if (n
< 0 || n
>= OID_MAX
)
236 i
= oid_names
[n
].level
+ 1;
237 oid
= chunk_alloc(2 + i
);
238 oid
.ptr
[0] = ASN1_OID
;
243 if (oid_names
[n
].level
>= i
)
248 oid
.ptr
[--i
+ 2] = oid_names
[n
--].octet
;
258 size_t asn1_length(chunk_t
*blob
)
265 DBG2("insufficient number of octets to parse ASN.1 length");
266 return ASN1_INVALID_LENGTH
;
269 /* read length field, skip tag and length */
271 *blob
= chunk_skip(*blob
, 2);
274 { /* single length octet */
277 DBG2("length is larger than remaining blob size");
278 return ASN1_INVALID_LENGTH
;
283 /* composite length, determine number of length octets */
286 if (n
== 0 || n
> blob
->len
)
288 DBG2("number of length octets invalid");
289 return ASN1_INVALID_LENGTH
;
294 DBG2("number of length octets is larger than limit of %d octets",
296 return ASN1_INVALID_LENGTH
;
303 len
= 256*len
+ *blob
->ptr
++;
308 DBG2("length is larger than remaining blob size");
309 return ASN1_INVALID_LENGTH
;
317 int asn1_unwrap(chunk_t
*blob
, chunk_t
*inner
)
329 *blob
= chunk_skip(*blob
, 2);
331 if ((len
& 0x80) == 0)
332 { /* single length octet */
336 { /* composite length, determine number of length octets */
338 if (len
== 0 || len
> sizeof(res
.len
))
345 res
.len
= 256 * res
.len
+ blob
->ptr
[0];
346 *blob
= chunk_skip(*blob
, 1);
349 if (res
.len
> blob
->len
)
354 *blob
= chunk_skip(*blob
, res
.len
);
355 /* updating inner not before we are finished allows a caller to pass
361 #define TIME_MAX 0x7fffffff
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;
367 * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
369 time_t asn1_to_time(const chunk_t
*utctime
, asn1_t type
)
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
;
377 if ((eot
= memchr(utctime
->ptr
, 'Z', utctime
->len
)) != NULL
)
379 tz_offset
= 0; /* Zulu time with a zero time zone offset */
381 else if ((eot
= memchr(utctime
->ptr
, '+', utctime
->len
)) != NULL
)
383 if (sscanf(eot
+1, "%2d%2d", &tz_hour
, &tz_min
) != 2)
385 return 0; /* error in positive timezone offset format */
387 tz_offset
= 3600*tz_hour
+ 60*tz_min
; /* positive time zone offset */
389 else if ((eot
= memchr(utctime
->ptr
, '-', utctime
->len
)) != NULL
)
391 if (sscanf(eot
+1, "%2d%2d", &tz_hour
, &tz_min
) != 2)
393 return 0; /* error in negative timezone offset format */
395 tz_offset
= -3600*tz_hour
- 60*tz_min
; /* negative time zone offset */
399 return 0; /* error in time format */
402 /* parse ASN.1 time string */
404 const char* format
= (type
== ASN1_UTCTIME
)?
"%2d%2d%2d%2d%2d":
407 if (sscanf(utctime
->ptr
, format
, &tm_year
, &tm_mon
, &tm_day
,
408 &tm_hour
, &tm_min
) != 5)
410 return 0; /* error in [yy]yymmddhhmm time format */
414 /* is there a seconds field? */
415 if ((eot
- utctime
->ptr
) == ((type
== ASN1_UTCTIME
)?
12:14))
417 if (sscanf(eot
-2, "%2d", &tm_sec
) != 1)
419 return 0; /* error in ss seconds field format */
427 /* representation of two-digit years */
428 if (type
== ASN1_UTCTIME
)
430 tm_year
+= (tm_year
< 50) ?
2000 : 1900;
433 /* prevent large 32 bit integer overflows */
434 if (sizeof(time_t) == 4 && tm_year
> 2038)
439 /* representation of months as 0..11*/
440 if (tm_mon
< 1 || tm_mon
> 12)
442 return 0; /* error in month format */
446 /* representation of days as 0..30 */
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 /* has a 32 bit overflow occurred? */
465 return (tm_secs
< 0) ? TIME_MAX
: tm_secs
;
469 * Convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
471 chunk_t
asn1_from_time(const time_t *time
, asn1_t type
)
476 chunk_t formatted_time
;
480 if (type
== ASN1_GENERALIZEDTIME
)
482 format
= "%04d%02d%02d%02d%02d%02dZ";
485 else /* ASN1_UTCTIME */
487 format
= "%02d%02d%02d%02d%02d%02dZ";
488 offset
= (t
.tm_year
< 100)?
0 : -100;
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
);
500 void asn1_debug_simple_object(chunk_t object
, asn1_t type
, bool private)
507 oid
= asn1_known_oid(object
);
508 if (oid
!= OID_UNKNOWN
)
510 DBG2(" '%s'", oid_names
[oid
].name
);
514 case ASN1_UTF8STRING
:
516 case ASN1_PRINTABLESTRING
:
518 case ASN1_VISIBLESTRING
:
519 DBG2(" '%.*s'", (int)object
.len
, object
.ptr
);
522 case ASN1_GENERALIZEDTIME
:
524 time_t time
= asn1_to_time(&object
, type
);
526 DBG2(" '%T'", &time
, TRUE
);
543 * parse an ASN.1 simple type
545 bool asn1_parse_simple_object(chunk_t
*object
, asn1_t type
, u_int level
, const char* name
)
549 /* an ASN.1 object must possess at least a tag and length field */
552 DBG2("L%d - %s: ASN.1 object smaller than 2 octets", level
, name
);
556 if (*object
->ptr
!= type
)
558 DBG2("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
559 level
, name
, type
, *object
->ptr
);
563 len
= asn1_length(object
);
565 if (len
== ASN1_INVALID_LENGTH
|| object
->len
< len
)
567 DBG2("L%d - %s: length of ASN.1 object invalid or too large",
572 DBG2("L%d - %s:", level
, name
);
573 asn1_debug_simple_object(*object
, type
, FALSE
);
578 * ASN.1 definition of an algorithmIdentifier
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
}
587 #define ALGORITHM_ID_ALG 1
588 #define ALGORITHM_ID_PARAMETERS 2
593 int asn1_parse_algorithmIdentifier(chunk_t blob
, int level0
, chunk_t
*parameters
)
595 asn1_parser_t
*parser
;
598 int alg
= OID_UNKNOWN
;
600 parser
= asn1_parser_create(algorithmIdentifierObjects
, blob
);
601 parser
->set_top_level(parser
, level0
);
603 while (parser
->iterate(parser
, &objectID
, &object
))
607 case ALGORITHM_ID_ALG
:
608 alg
= asn1_known_oid(object
);
610 case ALGORITHM_ID_PARAMETERS
:
611 if (parameters
!= NULL
)
613 *parameters
= object
;
620 parser
->destroy(parser
);
625 * tests if a blob contains a valid ASN.1 set or sequence
627 bool is_asn1(chunk_t blob
)
630 u_char tag
= *blob
.ptr
;
632 if (tag
!= ASN1_SEQUENCE
&& tag
!= ASN1_SET
)
634 DBG2(" file content is not binary ASN.1");
638 len
= asn1_length(&blob
);
646 /* some websites append a surplus newline character to the blob */
647 if (len
+ 1 == blob
.len
&& *(blob
.ptr
+ len
) == '\n')
652 DBG2(" file size does not match ASN.1 coded length");
659 bool asn1_is_printablestring(chunk_t str
)
661 const char printablestring_charset
[] =
662 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
665 for (i
= 0; i
< str
.len
; i
++)
667 if (strchr(printablestring_charset
, str
.ptr
[i
]) == NULL
)
674 * codes ASN.1 lengths up to a size of 16'777'215 bytes
676 static void asn1_code_length(size_t length
, chunk_t
*code
)
680 code
->ptr
[0] = length
;
683 else if (length
< 256)
686 code
->ptr
[1] = (u_char
) length
;
689 else if (length
< 65536)
692 code
->ptr
[1] = length
>> 8;
693 code
->ptr
[2] = length
& 0x00ff;
699 code
->ptr
[1] = length
>> 16;
700 code
->ptr
[2] = (length
>> 8) & 0x00ff;
701 code
->ptr
[3] = length
& 0x0000ff;
707 * build an empty asn.1 object with tag and length fields already filled in
709 u_char
* asn1_build_object(chunk_t
*object
, asn1_t type
, size_t datalen
)
711 u_char length_buf
[4];
712 chunk_t length
= { length_buf
, 0 };
715 /* code the asn.1 length field */
716 asn1_code_length(datalen
, &length
);
718 /* allocate memory for the asn.1 TLV object */
719 object
->len
= 1 + length
.len
+ datalen
;
720 object
->ptr
= malloc(object
->len
);
722 /* set position pointer at the start of the object */
725 /* copy the asn.1 tag field and advance the pointer */
728 /* copy the asn.1 length field and advance the pointer */
729 memcpy(pos
, length
.ptr
, length
.len
);
736 * Build a simple ASN.1 object
738 chunk_t
asn1_simple_object(asn1_t tag
, chunk_t content
)
742 u_char
*pos
= asn1_build_object(&object
, tag
, content
.len
);
743 memcpy(pos
, content
.ptr
, content
.len
);
750 * Build an ASN.1 BIT_STRING object
752 chunk_t
asn1_bitstring(const char *mode
, chunk_t content
)
755 u_char
*pos
= asn1_build_object(&object
, ASN1_BIT_STRING
, 1 + content
.len
);
758 memcpy(pos
, content
.ptr
, content
.len
);
767 * Build an ASN.1 INTEGER object
769 chunk_t
asn1_integer(const char *mode
, chunk_t content
)
775 if (content
.len
== 0 || (content
.len
== 1 && *content
.ptr
== 0x00))
777 /* a zero ASN.1 integer does not have a value field */
782 /* ASN.1 integers must be positive numbers in two's complement */
783 len
= content
.len
+ ((*content
.ptr
& 0x80) ?
1 : 0);
785 pos
= asn1_build_object(&object
, ASN1_INTEGER
, len
);
786 if (len
> content
.len
)
792 memcpy(pos
, content
.ptr
, content
.len
);
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').
805 chunk_t
asn1_wrap(asn1_t type
, const char *mode
, ...)
811 int count
= strlen(mode
);
813 /* sum up lengths of individual chunks */
814 va_start(chunks
, mode
);
816 for (i
= 0; i
< count
; i
++)
818 chunk_t ch
= va_arg(chunks
, chunk_t
);
819 construct
.len
+= ch
.len
;
823 /* allocate needed memory for construct */
824 pos
= asn1_build_object(&construct
, type
, construct
.len
);
826 /* copy or move the chunks */
827 va_start(chunks
, mode
);
828 for (i
= 0; i
< count
; i
++)
830 chunk_t ch
= va_arg(chunks
, chunk_t
);
832 memcpy(pos
, ch
.ptr
, ch
.len
);
853 * ASN.1 definition of time
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
}
863 #define TIME_GENERALIZED 2
866 * extracts and converts a UTCTIME or GENERALIZEDTIME object
868 time_t asn1_parse_time(chunk_t blob
, int level0
)
870 asn1_parser_t
*parser
;
875 parser
= asn1_parser_create(timeObjects
, blob
);
876 parser
->set_top_level(parser
, level0
);
878 while (parser
->iterate(parser
, &objectID
, &object
))
880 if (objectID
== TIME_UTC
|| objectID
== TIME_GENERALIZED
)
882 utc_time
= asn1_to_time(&object
, (objectID
== TIME_UTC
)
883 ? ASN1_UTCTIME
: ASN1_GENERALIZEDTIME
);
886 parser
->destroy(parser
);