Coverage Report

Created: 2026-06-15 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/tests/fuzzing/eapol-key-auth/eapol-key-auth.c
Line
Count
Source
1
/*
2
 * Testing tool for EAPOL-Key Authenticator 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 "ap/wpa_auth.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 supplicant */
28
  u8 *supp_eapol;
29
  size_t supp_eapol_len;
30
31
  struct wpa_auth_callbacks auth_cb;
32
  struct wpa_authenticator *auth_group;
33
  struct wpa_state_machine *auth;
34
35
  u8 supp_ie[80];
36
  size_t supp_ie_len;
37
38
  int key_request_done;
39
  int key_request_done1;
40
  int auth_sent;
41
};
42
43
44
const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
45
46
47
static int auth_read_msg(struct wpa *wpa);
48
static void supp_eapol_key_request(void *eloop_data, void *user_ctx);
49
50
51
static u8 * read_msg(struct wpa *wpa, size_t *ret_len)
52
5.03M
{
53
5.03M
  u16 msg_len;
54
5.03M
  u8 *msg;
55
56
5.03M
  if (wpa->data_len - wpa->data_offset < 2) {
57
855
    wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len");
58
855
    eloop_terminate();
59
855
    return NULL;
60
855
  }
61
5.03M
  msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]);
62
5.03M
  wpa->data_offset += 2;
63
64
5.03M
  msg = os_malloc(msg_len);
65
5.03M
  if (!msg)
66
0
    return NULL;
67
5.03M
  if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) {
68
386
    wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)",
69
386
         msg_len);
70
386
    os_free(msg);
71
386
    eloop_terminate();
72
386
    return NULL;
73
386
  }
74
5.03M
  os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len);
75
5.03M
  wpa->data_offset += msg_len;
76
5.03M
  wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len);
77
78
5.03M
  *ret_len = msg_len;
79
5.03M
  return msg;
80
5.03M
}
81
82
83
static void auth_eapol_rx(void *eloop_data, void *user_ctx)
84
5.02M
{
85
5.02M
  struct wpa *wpa = eloop_data;
86
87
5.02M
  wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame");
88
5.02M
  wpa->auth_sent = 0;
89
5.02M
  wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol,
90
5.02M
        wpa->supp_eapol_len);
91
5.02M
  if (!wpa->auth_sent) {
92
    /* Speed up process by not going through retransmit timeout */
93
5.02M
    wpa_printf(MSG_DEBUG,
94
5.02M
         "AUTH: No response was sent - process next message");
95
5.02M
    auth_read_msg(wpa);
96
5.02M
  }
97
5.02M
  if (wpa->wpa1 && wpa->key_request_done && !wpa->key_request_done1) {
98
0
    wpa->key_request_done1 = 1;
99
0
    eloop_register_timeout(0, 0, supp_eapol_key_request,
100
0
               wpa, NULL);
101
0
  }
102
103
5.02M
}
104
105
106
static void auth_logger(void *ctx, const u8 *addr, logger_level level,
107
      const char *txt)
108
58.8k
{
109
58.8k
  if (addr)
110
57.7k
    wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s",
111
57.7k
         MAC2STR(addr), txt);
112
1.12k
  else
113
1.12k
    wpa_printf(MSG_DEBUG, "AUTH: %s", txt);
114
58.8k
}
115
116
117
static int auth_read_msg(struct wpa *wpa)
118
5.03M
{
119
5.03M
  os_free(wpa->supp_eapol);
120
5.03M
  wpa->supp_eapol = read_msg(wpa, &wpa->supp_eapol_len);
121
5.03M
  if (!wpa->supp_eapol)
122
1.24k
    return -1;
123
5.03M
  eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL);
124
5.03M
  return 0;
125
5.03M
}
126
127
128
static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
129
         size_t data_len, int encrypt)
130
4.11k
{
131
4.11k
  struct wpa *wpa = ctx;
132
133
4.11k
  wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu "
134
4.11k
       "encrypt=%d)",
135
4.11k
       __func__, MAC2STR(addr), (unsigned long) data_len, encrypt);
136
4.11k
  wpa->auth_sent = 1;
137
138
4.11k
  return auth_read_msg(wpa);
139
4.11k
}
140
141
142
static const u8 * auth_get_psk(void *ctx, const u8 *addr,
143
             const u8 *p2p_dev_addr, const u8 *prev_psk,
144
             size_t *psk_len, int *vlan_id)
145
5.20k
{
146
5.20k
  struct wpa *wpa = ctx;
147
148
5.20k
  wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
149
5.20k
       __func__, MAC2STR(addr), prev_psk);
150
5.20k
  if (vlan_id)
151
2.72k
    *vlan_id = 0;
152
5.20k
  if (psk_len)
153
3.96k
    *psk_len = PMK_LEN;
154
5.20k
  if (prev_psk)
155
257
    return NULL;
156
4.95k
  return wpa->psk;
157
5.20k
}
158
159
160
static void supp_eapol_key_request(void *eloop_data, void *user_ctx)
161
619
{
162
619
  struct wpa *wpa = eloop_data;
163
164
619
  wpa_printf(MSG_DEBUG, "SUPP: EAPOL-Key Request trigger");
165
619
  if (!eloop_is_timeout_registered(auth_eapol_rx, wpa, NULL))
166
0
    auth_read_msg(wpa);
167
619
}
168
169
170
static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
171
      const u8 *addr, int idx, u8 *key,
172
      size_t key_len, enum key_flag key_flag)
173
7.60k
{
174
7.60k
  struct wpa *wpa = ctx;
175
176
7.60k
  wpa_printf(MSG_DEBUG,
177
7.60k
       "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d key_flag=0x%x)",
178
7.60k
       __func__, vlan_id, alg, idx, (int) key_len, key_flag);
179
7.60k
  if (addr)
180
7.60k
    wpa_printf(MSG_DEBUG, "AUTH: addr=" MACSTR, MAC2STR(addr));
181
182
7.60k
  if (alg != WPA_ALG_NONE && idx == 0 && key_len > 0 &&
183
2.54k
      !wpa->key_request_done) {
184
624
    wpa_printf(MSG_DEBUG, "Test EAPOL-Key Request");
185
624
    wpa->key_request_done = 1;
186
624
    if (!wpa->wpa1)
187
624
      eloop_register_timeout(0, 0, supp_eapol_key_request,
188
624
                 wpa, NULL);
189
624
  }
190
191
7.60k
  return 0;
192
7.60k
}
193
194
195
static int auth_init_group(struct wpa *wpa)
196
1.24k
{
197
1.24k
  struct wpa_auth_config conf;
198
199
1.24k
  wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
200
201
1.24k
  os_memset(&conf, 0, sizeof(conf));
202
1.24k
  if (wpa->wpa1) {
203
0
    conf.wpa = 1;
204
0
    conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK;
205
0
    conf.wpa_pairwise = WPA_CIPHER_TKIP;
206
0
    conf.wpa_group = WPA_CIPHER_TKIP;
207
1.24k
  } else {
208
1.24k
    conf.wpa = 2;
209
1.24k
    conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK;
210
1.24k
    conf.wpa_pairwise = WPA_CIPHER_CCMP;
211
1.24k
    conf.rsn_pairwise = WPA_CIPHER_CCMP;
212
1.24k
    conf.wpa_group = WPA_CIPHER_CCMP;
213
1.24k
    conf.ieee80211w = 2;
214
1.24k
    conf.group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
215
1.24k
  }
216
1.24k
  conf.eapol_version = 2;
217
1.24k
  conf.wpa_group_update_count = 4;
218
1.24k
  conf.wpa_pairwise_update_count = 4;
219
220
1.24k
  wpa->auth_cb.logger = auth_logger;
221
1.24k
  wpa->auth_cb.send_eapol = auth_send_eapol;
222
1.24k
  wpa->auth_cb.get_psk = auth_get_psk;
223
1.24k
  wpa->auth_cb.set_key = auth_set_key;
224
225
1.24k
  wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &wpa->auth_cb, wpa);
226
1.24k
  if (!wpa->auth_group) {
227
0
    wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed");
228
0
    return -1;
229
0
  }
230
231
1.24k
  return 0;
232
1.24k
}
233
234
235
static int auth_init(struct wpa *wpa)
236
1.24k
{
237
1.24k
  const u8 *supp_ie;
238
1.24k
  size_t supp_ie_len;
239
1.24k
  static const u8 ie_rsn[] = {
240
1.24k
    0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
241
1.24k
    0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00,
242
1.24k
    0x00, 0x0f, 0xac, 0x02, 0x80, 0x00
243
1.24k
  };
244
1.24k
  static const u8 ie_wpa[] = {
245
1.24k
    0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00,
246
1.24k
    0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50,
247
1.24k
    0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02
248
1.24k
  };
249
250
1.24k
  if (wpa->wpa1) {
251
0
    supp_ie = ie_wpa;
252
0
    supp_ie_len = sizeof(ie_wpa);
253
1.24k
  } else {
254
1.24k
    supp_ie = ie_rsn;
255
1.24k
    supp_ie_len = sizeof(ie_rsn);
256
1.24k
  }
257
258
1.24k
  wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr, NULL);
259
1.24k
  if (!wpa->auth) {
260
0
    wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed");
261
0
    return -1;
262
0
  }
263
264
1.24k
  if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, supp_ie,
265
1.24k
        supp_ie_len, NULL, 0, NULL, 0, NULL, 0, NULL,
266
1.24k
        false) != WPA_IE_OK) {
267
0
    wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed");
268
0
    return -1;
269
0
  }
270
271
1.24k
  wpa_auth_sm_event(wpa->auth, WPA_ASSOC);
272
273
1.24k
  wpa_auth_sta_associated(wpa->auth_group, wpa->auth);
274
275
1.24k
  return 0;
276
1.24k
}
277
278
279
static void deinit(struct wpa *wpa)
280
1.24k
{
281
1.24k
  wpa_auth_sta_deinit(wpa->auth);
282
1.24k
  wpa_deinit(wpa->auth_group);
283
1.24k
  os_free(wpa->supp_eapol);
284
1.24k
  wpa->supp_eapol = NULL;
285
1.24k
}
286
287
288
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
289
1.24k
{
290
1.24k
  struct wpa wpa;
291
292
1.24k
  wpa_fuzzer_set_debug_level();
293
294
1.24k
  if (os_program_init())
295
0
    return -1;
296
297
1.24k
  os_memset(&wpa, 0, sizeof(wpa));
298
1.24k
  wpa.data = data;
299
1.24k
  wpa.data_len = size;
300
301
1.24k
  os_memset(wpa.auth_addr, 0x12, ETH_ALEN);
302
1.24k
  os_memset(wpa.supp_addr, 0x32, ETH_ALEN);
303
1.24k
  os_memset(wpa.psk, 0x44, PMK_LEN);
304
305
1.24k
  if (eloop_init()) {
306
0
    wpa_printf(MSG_ERROR, "Failed to initialize event loop");
307
0
    goto fail;
308
0
  }
309
310
1.24k
  if (auth_init_group(&wpa) < 0)
311
0
    goto fail;
312
313
1.24k
  if (auth_init(&wpa) < 0)
314
0
    goto fail;
315
316
1.24k
  wpa_printf(MSG_DEBUG, "Starting eloop");
317
1.24k
  eloop_run();
318
1.24k
  wpa_printf(MSG_DEBUG, "eloop done");
319
320
1.24k
fail:
321
1.24k
  deinit(&wpa);
322
323
1.24k
  eloop_destroy();
324
325
1.24k
  os_program_deinit();
326
327
1.24k
  return 0;
328
1.24k
}