Coverage Report

Created: 2025-04-24 06:18

/src/hostap/tests/fuzzing/eapol-key-supp/eapol-key-supp.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Testing tool for EAPOL-Key Supplicant 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 "utils/includes.h"
10
11
#include "utils/common.h"
12
#include "utils/eloop.h"
13
#include "rsn_supp/wpa.h"
14
#include "../fuzzer-common.h"
15
16
17
struct wpa {
18
  const u8 *data;
19
  size_t data_len;
20
  size_t data_offset;
21
  int wpa1;
22
23
  u8 auth_addr[ETH_ALEN];
24
  u8 supp_addr[ETH_ALEN];
25
  u8 psk[PMK_LEN];
26
27
  /* from authenticator */
28
  u8 *auth_eapol;
29
  size_t auth_eapol_len;
30
31
  struct wpa_sm *supp;
32
33
  u8 supp_ie[80];
34
  size_t supp_ie_len;
35
};
36
37
38
const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
39
40
41
static u8 * read_msg(struct wpa *wpa, size_t *ret_len)
42
12.3k
{
43
12.3k
  u16 msg_len;
44
12.3k
  u8 *msg;
45
46
12.3k
  if (wpa->data_len - wpa->data_offset < 2) {
47
1.15k
    wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len");
48
1.15k
    eloop_terminate();
49
1.15k
    return NULL;
50
1.15k
  }
51
11.2k
  msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]);
52
11.2k
  wpa->data_offset += 2;
53
54
11.2k
  msg = os_malloc(msg_len);
55
11.2k
  if (!msg)
56
0
    return NULL;
57
11.2k
  if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) {
58
29
    wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)",
59
29
         msg_len);
60
29
    os_free(msg);
61
29
    eloop_terminate();
62
29
    return NULL;
63
29
  }
64
11.1k
  os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len);
65
11.1k
  wpa->data_offset += msg_len;
66
11.1k
  wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len);
67
68
11.1k
  *ret_len = msg_len;
69
11.1k
  return msg;
70
11.2k
}
71
72
73
static int supp_get_bssid(void *ctx, u8 *bssid)
74
0
{
75
0
  struct wpa *wpa = ctx;
76
0
  wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
77
0
  os_memcpy(bssid, wpa->auth_addr, ETH_ALEN);
78
0
  return 0;
79
0
}
80
81
82
static void supp_set_state(void *ctx, enum wpa_states state)
83
11.3k
{
84
11.3k
  wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state);
85
11.3k
}
86
87
88
static void supp_eapol_rx(void *eloop_data, void *user_ctx)
89
11.1k
{
90
11.1k
  struct wpa *wpa = eloop_data;
91
92
11.1k
  wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame");
93
11.1k
  wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol,
94
11.1k
      wpa->auth_eapol_len, FRAME_ENCRYPTION_UNKNOWN);
95
11.1k
}
96
97
98
static int supp_read_msg(struct wpa *wpa)
99
12.3k
{
100
12.3k
  os_free(wpa->auth_eapol);
101
12.3k
  wpa->auth_eapol = read_msg(wpa, &wpa->auth_eapol_len);
102
12.3k
  if (!wpa->auth_eapol)
103
1.18k
    return -1;
104
11.1k
  eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL);
105
11.1k
  return 0;
106
12.3k
}
107
108
109
static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
110
         size_t len)
111
10.3k
{
112
10.3k
  struct wpa *wpa = ctx;
113
114
10.3k
  wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
115
10.3k
       "len=%lu)",
116
10.3k
       __func__, MAC2STR(dest), proto, (unsigned long) len);
117
118
10.3k
  return supp_read_msg(wpa);
119
10.3k
}
120
121
122
static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data,
123
           u16 data_len, size_t *msg_len, void **data_pos)
124
10.3k
{
125
10.3k
  struct ieee802_1x_hdr *hdr;
126
127
10.3k
  wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)",
128
10.3k
       __func__, type, data_len);
129
130
10.3k
  *msg_len = sizeof(*hdr) + data_len;
131
10.3k
  hdr = os_malloc(*msg_len);
132
10.3k
  if (hdr == NULL)
133
0
    return NULL;
134
135
10.3k
  hdr->version = 2;
136
10.3k
  hdr->type = type;
137
10.3k
  hdr->length = host_to_be16(data_len);
138
139
10.3k
  if (data)
140
0
    os_memcpy(hdr + 1, data, data_len);
141
10.3k
  else
142
10.3k
    os_memset(hdr + 1, 0, data_len);
143
144
10.3k
  if (data_pos)
145
10.3k
    *data_pos = hdr + 1;
146
147
10.3k
  return (u8 *) hdr;
148
10.3k
}
149
150
151
static int supp_get_beacon_ie(void *ctx)
152
270
{
153
270
  struct wpa *wpa = ctx;
154
270
  const u8 *ie;
155
270
  static const u8 wpaie[] = {
156
270
    0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00,
157
270
    0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50,
158
270
    0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02
159
270
  };
160
270
  static const u8 rsne[] = {
161
270
    0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
162
270
    0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00,
163
270
    0x00, 0x0f, 0xac, 0x02, 0xc0, 0x00
164
270
  };
165
166
270
  wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
167
168
270
  ie = wpa->wpa1 ? wpaie : rsne;
169
270
  if (ie[0] == WLAN_EID_RSN)
170
270
    return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]);
171
0
  return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]);
172
270
}
173
174
175
static int supp_set_key(void *ctx, int link_id, enum wpa_alg alg,
176
      const u8 *addr, int key_idx, int set_tx,
177
      const u8 *seq, size_t seq_len,
178
      const u8 *key, size_t key_len, enum key_flag key_flag)
179
535
{
180
535
  wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d "
181
535
       "set_tx=%d key_flag=0x%x link_id=%d)",
182
535
       __func__, alg, MAC2STR(addr), key_idx, set_tx, key_flag,
183
535
       link_id);
184
535
  wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len);
185
535
  wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len);
186
535
  return 0;
187
535
}
188
189
190
static int supp_mlme_setprotection(void *ctx, const u8 *addr,
191
           int protection_type, int key_type)
192
449
{
193
449
  wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d "
194
449
       "key_type=%d)",
195
449
       __func__, MAC2STR(addr), protection_type, key_type);
196
449
  return 0;
197
449
}
198
199
200
static void supp_cancel_auth_timeout(void *ctx)
201
0
{
202
0
  wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
203
0
}
204
205
206
static void * supp_get_network_ctx(void *ctx)
207
9.79k
{
208
9.79k
  return (void *) 1;
209
9.79k
}
210
211
212
static void supp_deauthenticate(void *ctx, u16 reason_code)
213
2.31k
{
214
2.31k
  wpa_printf(MSG_DEBUG, "SUPP: %s(%d)", __func__, reason_code);
215
2.31k
}
216
217
218
static enum wpa_states supp_get_state(void *ctx)
219
0
{
220
0
  return WPA_COMPLETED;
221
0
}
222
223
224
static int supp_init(struct wpa *wpa)
225
2.02k
{
226
2.02k
  struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx));
227
228
2.02k
  if (!ctx)
229
0
    return -1;
230
231
2.02k
  ctx->ctx = wpa;
232
2.02k
  ctx->msg_ctx = wpa;
233
2.02k
  ctx->set_state = supp_set_state;
234
2.02k
  ctx->get_bssid = supp_get_bssid;
235
2.02k
  ctx->ether_send = supp_ether_send;
236
2.02k
  ctx->get_beacon_ie = supp_get_beacon_ie;
237
2.02k
  ctx->alloc_eapol = supp_alloc_eapol;
238
2.02k
  ctx->set_key = supp_set_key;
239
2.02k
  ctx->mlme_setprotection = supp_mlme_setprotection;
240
2.02k
  ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
241
2.02k
  ctx->get_network_ctx = supp_get_network_ctx;
242
2.02k
  ctx->deauthenticate = supp_deauthenticate;
243
2.02k
  ctx->get_state = supp_get_state;
244
2.02k
  wpa->supp = wpa_sm_init(ctx);
245
2.02k
  if (!wpa->supp) {
246
0
    wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
247
0
    return -1;
248
0
  }
249
250
2.02k
  wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr);
251
2.02k
  if (wpa->wpa1) {
252
0
    wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 0);
253
0
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_WPA);
254
0
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE,
255
0
         WPA_CIPHER_TKIP);
256
0
    wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_TKIP);
257
0
    wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT,
258
0
         WPA_KEY_MGMT_PSK);
259
2.02k
  } else {
260
2.02k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1);
261
2.02k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN);
262
2.02k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE,
263
2.02k
         WPA_CIPHER_CCMP);
264
2.02k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
265
2.02k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT,
266
2.02k
         WPA_KEY_MGMT_PSK);
267
2.02k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_MFP,
268
2.02k
         MGMT_FRAME_PROTECTION_OPTIONAL);
269
2.02k
  }
270
2.02k
  wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN, NULL, NULL);
271
272
2.02k
  wpa->supp_ie_len = sizeof(wpa->supp_ie);
273
2.02k
  if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie,
274
2.02k
              &wpa->supp_ie_len) < 0) {
275
0
    wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()"
276
0
         " failed");
277
0
    return -1;
278
0
  }
279
280
2.02k
  wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr);
281
2.02k
  supp_read_msg(wpa);
282
283
2.02k
  return 0;
284
2.02k
}
285
286
287
static void deinit(struct wpa *wpa)
288
2.02k
{
289
2.02k
  wpa_sm_deinit(wpa->supp);
290
2.02k
  os_free(wpa->auth_eapol);
291
2.02k
  wpa->auth_eapol = NULL;
292
2.02k
}
293
294
295
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
296
2.02k
{
297
2.02k
  struct wpa wpa;
298
299
2.02k
  wpa_fuzzer_set_debug_level();
300
301
2.02k
  if (os_program_init())
302
0
    return -1;
303
304
2.02k
  os_memset(&wpa, 0, sizeof(wpa));
305
2.02k
  wpa.data = data;
306
2.02k
  wpa.data_len = size;
307
308
2.02k
  os_memset(wpa.auth_addr, 0x12, ETH_ALEN);
309
2.02k
  os_memset(wpa.supp_addr, 0x32, ETH_ALEN);
310
2.02k
  os_memset(wpa.psk, 0x44, PMK_LEN);
311
312
2.02k
  if (eloop_init()) {
313
0
    wpa_printf(MSG_ERROR, "Failed to initialize event loop");
314
0
    goto fail;
315
0
  }
316
317
2.02k
  if (supp_init(&wpa) < 0)
318
0
    goto fail;
319
320
2.02k
  wpa_printf(MSG_DEBUG, "Starting eloop");
321
2.02k
  eloop_run();
322
2.02k
  wpa_printf(MSG_DEBUG, "eloop done");
323
324
2.02k
fail:
325
2.02k
  deinit(&wpa);
326
327
2.02k
  eloop_destroy();
328
329
2.02k
  os_program_deinit();
330
331
2.02k
  return 0;
332
2.02k
}