Coverage Report

Created: 2025-10-12 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/tests/fuzzing/asn1/asn1.c
Line
Count
Source
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
284k
{
18
284k
  switch (class) {
19
8.06k
  case ASN1_CLASS_UNIVERSAL:
20
8.06k
    return "Universal";
21
1.79k
  case ASN1_CLASS_APPLICATION:
22
1.79k
    return "Application";
23
1.74k
  case ASN1_CLASS_CONTEXT_SPECIFIC:
24
1.74k
    return "Context-specific";
25
272k
  case ASN1_CLASS_PRIVATE:
26
272k
    return "Private";
27
0
  default:
28
0
    return "?";
29
284k
  }
30
284k
}
31
32
33
static int asn1_parse(const u8 *buf, size_t len, int level)
34
3.75k
{
35
3.75k
  const u8 *pos, *prev, *end;
36
3.75k
  char prefix[10], str[100];
37
3.75k
  int _level;
38
3.75k
  struct asn1_hdr hdr;
39
3.75k
  struct asn1_oid oid;
40
3.75k
  u8 tmp;
41
42
3.75k
  _level = level;
43
3.75k
  if ((size_t) _level > sizeof(prefix) - 1)
44
791
    _level = sizeof(prefix) - 1;
45
3.75k
  memset(prefix, ' ', _level);
46
3.75k
  prefix[_level] = '\0';
47
48
3.75k
  pos = buf;
49
3.75k
  end = buf + len;
50
51
287k
  while (pos < end) {
52
284k
    if (asn1_get_next(pos, end - pos, &hdr) < 0)
53
372
      return -1;
54
55
284k
    prev = pos;
56
284k
    pos = hdr.payload;
57
58
284k
    wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) "
59
284k
         "Tag %u Length %u",
60
284k
         prefix, hdr.class, asn1_class_str(hdr.class),
61
284k
         hdr.constructed,
62
284k
         hdr.constructed ? "Constructed" : "Primitive",
63
284k
         hdr.tag, hdr.length);
64
65
284k
    if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
66
1.74k
        hdr.constructed) {
67
1.19k
      if (asn1_parse(pos, hdr.length, level + 1) < 0)
68
417
        return -1;
69
773
      pos += hdr.length;
70
773
    }
71
72
283k
    if (hdr.class != ASN1_CLASS_UNIVERSAL)
73
275k
      continue;
74
75
8.06k
    switch (hdr.tag) {
76
625
    case ASN1_TAG_EOC:
77
625
      if (hdr.length) {
78
6
        wpa_printf(MSG_DEBUG, "ASN.1: Non-zero "
79
6
             "end-of-contents length (%u)",
80
6
             hdr.length);
81
6
        return -1;
82
6
      }
83
619
      wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix);
84
619
      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
260
    case ASN1_TAG_INTEGER:
96
260
      wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER",
97
260
            pos, hdr.length);
98
260
      pos += hdr.length;
99
260
      break;
100
614
    case ASN1_TAG_BITSTRING:
101
614
      wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString",
102
614
            pos, hdr.length);
103
614
      pos += hdr.length;
104
614
      break;
105
292
    case ASN1_TAG_OCTETSTRING:
106
292
      wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString",
107
292
            pos, hdr.length);
108
292
      pos += hdr.length;
109
292
      break;
110
324
    case ASN1_TAG_NULL:
111
324
      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
324
      wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix);
117
324
      break;
118
1.59k
    case ASN1_TAG_OID:
119
1.59k
      if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) {
120
39
        wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID");
121
39
        return -1;
122
39
      }
123
1.55k
      asn1_oid_to_str(&oid, str, sizeof(str));
124
1.55k
      wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str);
125
1.55k
      pos += hdr.length;
126
1.55k
      break;
127
288
    case ANS1_TAG_RELATIVE_OID:
128
288
      wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID",
129
288
            pos, hdr.length);
130
288
      pos += hdr.length;
131
288
      break;
132
1.24k
    case ASN1_TAG_SEQUENCE:
133
1.24k
      wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix);
134
1.24k
      if (asn1_parse(pos, hdr.length, level + 1) < 0)
135
148
        return -1;
136
1.09k
      pos += hdr.length;
137
1.09k
      break;
138
411
    case ASN1_TAG_SET:
139
411
      wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix);
140
411
      if (asn1_parse(pos, hdr.length, level + 1) < 0)
141
98
        return -1;
142
313
      pos += hdr.length;
143
313
      break;
144
551
    case ASN1_TAG_PRINTABLESTRING:
145
551
      wpa_hexdump_ascii(MSG_MSGDUMP,
146
551
            "ASN.1: PrintableString",
147
551
            pos, hdr.length);
148
551
      pos += hdr.length;
149
551
      break;
150
236
    case ASN1_TAG_IA5STRING:
151
236
      wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String",
152
236
            pos, hdr.length);
153
236
      pos += hdr.length;
154
236
      break;
155
214
    case ASN1_TAG_UTCTIME:
156
214
      wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME",
157
214
            pos, hdr.length);
158
214
      pos += hdr.length;
159
214
      break;
160
204
    case ASN1_TAG_VISIBLESTRING:
161
204
      wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString",
162
204
            pos, hdr.length);
163
204
      pos += hdr.length;
164
204
      break;
165
156
    default:
166
156
      wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d",
167
156
           hdr.tag);
168
156
      return -1;
169
8.06k
    }
170
8.06k
  }
171
172
2.52k
  return 0;
173
3.75k
}
174
175
176
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
177
910
{
178
910
  wpa_fuzzer_set_debug_level();
179
180
910
  if (asn1_parse(data, size, 0) < 0)
181
573
    wpa_printf(MSG_DEBUG, "Failed to parse DER ASN.1");
182
183
910
  return 0;
184
910
}