/src/hostap/tests/fuzzing/asn1/asn1.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Fuzzing tool for ASN.1 routines |
3 | | * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "includes.h" |
10 | | |
11 | | #include "common.h" |
12 | | #include "tls/asn1.h" |
13 | | #include "../fuzzer-common.h" |
14 | | |
15 | | |
16 | | static const char * asn1_class_str(int class) |
17 | 283k | { |
18 | 283k | switch (class) { |
19 | 7.94k | case ASN1_CLASS_UNIVERSAL: |
20 | 7.94k | return "Universal"; |
21 | 929 | case ASN1_CLASS_APPLICATION: |
22 | 929 | return "Application"; |
23 | 1.75k | case ASN1_CLASS_CONTEXT_SPECIFIC: |
24 | 1.75k | return "Context-specific"; |
25 | 272k | case ASN1_CLASS_PRIVATE: |
26 | 272k | return "Private"; |
27 | 0 | default: |
28 | 0 | return "?"; |
29 | 283k | } |
30 | 283k | } |
31 | | |
32 | | |
33 | | static int asn1_parse(const u8 *buf, size_t len, int level) |
34 | 3.88k | { |
35 | 3.88k | const u8 *pos, *prev, *end; |
36 | 3.88k | char prefix[10], str[100]; |
37 | 3.88k | int _level; |
38 | 3.88k | struct asn1_hdr hdr; |
39 | 3.88k | struct asn1_oid oid; |
40 | 3.88k | u8 tmp; |
41 | | |
42 | 3.88k | _level = level; |
43 | 3.88k | if ((size_t) _level > sizeof(prefix) - 1) |
44 | 785 | _level = sizeof(prefix) - 1; |
45 | 3.88k | memset(prefix, ' ', _level); |
46 | 3.88k | prefix[_level] = '\0'; |
47 | | |
48 | 3.88k | pos = buf; |
49 | 3.88k | end = buf + len; |
50 | | |
51 | 286k | while (pos < end) { |
52 | 283k | if (asn1_get_next(pos, end - pos, &hdr) < 0) |
53 | 392 | return -1; |
54 | | |
55 | 283k | prev = pos; |
56 | 283k | pos = hdr.payload; |
57 | | |
58 | 283k | wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) " |
59 | 283k | "Tag %u Length %u", |
60 | 283k | prefix, hdr.class, asn1_class_str(hdr.class), |
61 | 283k | hdr.constructed, |
62 | 283k | hdr.constructed ? "Constructed" : "Primitive", |
63 | 283k | hdr.tag, hdr.length); |
64 | | |
65 | 283k | if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && |
66 | 283k | hdr.constructed) { |
67 | 1.19k | if (asn1_parse(pos, hdr.length, level + 1) < 0) |
68 | 461 | return -1; |
69 | 733 | pos += hdr.length; |
70 | 733 | } |
71 | | |
72 | 283k | if (hdr.class != ASN1_CLASS_UNIVERSAL) |
73 | 275k | continue; |
74 | | |
75 | 7.94k | switch (hdr.tag) { |
76 | 312 | case ASN1_TAG_EOC: |
77 | 312 | if (hdr.length) { |
78 | 21 | wpa_printf(MSG_DEBUG, "ASN.1: Non-zero " |
79 | 21 | "end-of-contents length (%u)", |
80 | 21 | hdr.length); |
81 | 21 | return -1; |
82 | 21 | } |
83 | 291 | wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix); |
84 | 291 | break; |
85 | 1.04k | case ASN1_TAG_BOOLEAN: |
86 | 1.04k | if (hdr.length != 1) { |
87 | 0 | wpa_printf(MSG_DEBUG, "ASN.1: Unexpected " |
88 | 0 | "Boolean length (%u)", hdr.length); |
89 | 0 | return -1; |
90 | 0 | } |
91 | 1.04k | tmp = *pos++; |
92 | 1.04k | wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s", |
93 | 1.04k | prefix, tmp ? "TRUE" : "FALSE"); |
94 | 1.04k | break; |
95 | 269 | case ASN1_TAG_INTEGER: |
96 | 269 | wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER", |
97 | 269 | pos, hdr.length); |
98 | 269 | pos += hdr.length; |
99 | 269 | break; |
100 | 608 | case ASN1_TAG_BITSTRING: |
101 | 608 | wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString", |
102 | 608 | pos, hdr.length); |
103 | 608 | pos += hdr.length; |
104 | 608 | break; |
105 | 274 | case ASN1_TAG_OCTETSTRING: |
106 | 274 | wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString", |
107 | 274 | pos, hdr.length); |
108 | 274 | pos += hdr.length; |
109 | 274 | break; |
110 | 347 | case ASN1_TAG_NULL: |
111 | 347 | if (hdr.length) { |
112 | 0 | wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null " |
113 | 0 | "length (%u)", hdr.length); |
114 | 0 | return -1; |
115 | 0 | } |
116 | 347 | wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix); |
117 | 347 | break; |
118 | 1.52k | case ASN1_TAG_OID: |
119 | 1.52k | if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) { |
120 | 40 | wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID"); |
121 | 40 | return -1; |
122 | 40 | } |
123 | 1.48k | asn1_oid_to_str(&oid, str, sizeof(str)); |
124 | 1.48k | wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str); |
125 | 1.48k | pos += hdr.length; |
126 | 1.48k | break; |
127 | 207 | case ANS1_TAG_RELATIVE_OID: |
128 | 207 | wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID", |
129 | 207 | pos, hdr.length); |
130 | 207 | pos += hdr.length; |
131 | 207 | break; |
132 | 1.20k | case ASN1_TAG_SEQUENCE: |
133 | 1.20k | wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix); |
134 | 1.20k | if (asn1_parse(pos, hdr.length, level + 1) < 0) |
135 | 146 | return -1; |
136 | 1.06k | pos += hdr.length; |
137 | 1.06k | break; |
138 | 530 | case ASN1_TAG_SET: |
139 | 530 | wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix); |
140 | 530 | if (asn1_parse(pos, hdr.length, level + 1) < 0) |
141 | 91 | return -1; |
142 | 439 | pos += hdr.length; |
143 | 439 | break; |
144 | 611 | case ASN1_TAG_PRINTABLESTRING: |
145 | 611 | wpa_hexdump_ascii(MSG_MSGDUMP, |
146 | 611 | "ASN.1: PrintableString", |
147 | 611 | pos, hdr.length); |
148 | 611 | pos += hdr.length; |
149 | 611 | break; |
150 | 364 | case ASN1_TAG_IA5STRING: |
151 | 364 | wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String", |
152 | 364 | pos, hdr.length); |
153 | 364 | pos += hdr.length; |
154 | 364 | break; |
155 | 272 | case ASN1_TAG_UTCTIME: |
156 | 272 | wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME", |
157 | 272 | pos, hdr.length); |
158 | 272 | pos += hdr.length; |
159 | 272 | break; |
160 | 205 | case ASN1_TAG_VISIBLESTRING: |
161 | 205 | wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString", |
162 | 205 | pos, hdr.length); |
163 | 205 | pos += hdr.length; |
164 | 205 | break; |
165 | 168 | default: |
166 | 168 | wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d", |
167 | 168 | hdr.tag); |
168 | 168 | return -1; |
169 | 7.94k | } |
170 | 7.94k | } |
171 | | |
172 | 2.57k | return 0; |
173 | 3.88k | } |
174 | | |
175 | | |
176 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
177 | 958 | { |
178 | 958 | wpa_fuzzer_set_debug_level(); |
179 | | |
180 | 958 | if (asn1_parse(data, size, 0) < 0) |
181 | 621 | wpa_printf(MSG_DEBUG, "Failed to parse DER ASN.1"); |
182 | | |
183 | 958 | return 0; |
184 | 958 | } |