Coverage Report

Created: 2025-10-10 06:31

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
3.93M
{
53
3.93M
  u16 msg_len;
54
3.93M
  u8 *msg;
55
56
3.93M
  if (wpa->data_len - wpa->data_offset < 2) {
57
840
    wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len");
58
840
    eloop_terminate();
59
840
    return NULL;
60
840
  }
61
3.93M
  msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]);
62
3.93M
  wpa->data_offset += 2;
63
64
3.93M
  msg = os_malloc(msg_len);
65
3.93M
  if (!msg)
66
0
    return NULL;
67
3.93M
  if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) {
68
309
    wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)",
69
309
         msg_len);
70
309
    os_free(msg);
71
309
    eloop_terminate();
72
309
    return NULL;
73
309
  }
74
3.93M
  os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len);
75
3.93M
  wpa->data_offset += msg_len;
76
3.93M
  wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len);
77
78
3.93M
  *ret_len = msg_len;
79
3.93M
  return msg;
80
3.93M
}
81
82
83
static void auth_eapol_rx(void *eloop_data, void *user_ctx)
84
3.93M
{
85
3.93M
  struct wpa *wpa = eloop_data;
86
87
3.93M
  wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame");
88
3.93M
  wpa->auth_sent = 0;
89
3.93M
  wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol,
90
3.93M
        wpa->supp_eapol_len);
91
3.93M
  if (!wpa->auth_sent) {
92
    /* Speed up process by not going through retransmit timeout */
93
3.93M
    wpa_printf(MSG_DEBUG,
94
3.93M
         "AUTH: No response was sent - process next message");
95
3.93M
    auth_read_msg(wpa);
96
3.93M
  }
97
3.93M
  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
3.93M
}
104
105
106
static void auth_logger(void *ctx, const u8 *addr, logger_level level,
107
      const char *txt)
108
54.0k
{
109
54.0k
  if (addr)
110
52.9k
    wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s",
111
52.9k
         MAC2STR(addr), txt);
112
1.10k
  else
113
1.10k
    wpa_printf(MSG_DEBUG, "AUTH: %s", txt);
114
54.0k
}
115
116
117
static int auth_read_msg(struct wpa *wpa)
118
3.93M
{
119
3.93M
  os_free(wpa->supp_eapol);
120
3.93M
  wpa->supp_eapol = read_msg(wpa, &wpa->supp_eapol_len);
121
3.93M
  if (!wpa->supp_eapol)
122
1.14k
    return -1;
123
3.93M
  eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL);
124
3.93M
  return 0;
125
3.93M
}
126
127
128
static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
129
         size_t data_len, int encrypt)
130
2.59k
{
131
2.59k
  struct wpa *wpa = ctx;
132
133
2.59k
  wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu "
134
2.59k
       "encrypt=%d)",
135
2.59k
       __func__, MAC2STR(addr), (unsigned long) data_len, encrypt);
136
2.59k
  wpa->auth_sent = 1;
137
138
2.59k
  return auth_read_msg(wpa);
139
2.59k
}
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
3.62k
{
146
3.62k
  struct wpa *wpa = ctx;
147
148
3.62k
  wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
149
3.62k
       __func__, MAC2STR(addr), prev_psk);
150
3.62k
  if (vlan_id)
151
1.32k
    *vlan_id = 0;
152
3.62k
  if (psk_len)
153
2.47k
    *psk_len = PMK_LEN;
154
3.62k
  if (prev_psk)
155
231
    return NULL;
156
3.39k
  return wpa->psk;
157
3.62k
}
158
159
160
static void supp_eapol_key_request(void *eloop_data, void *user_ctx)
161
563
{
162
563
  struct wpa *wpa = eloop_data;
163
164
563
  wpa_printf(MSG_DEBUG, "SUPP: EAPOL-Key Request trigger");
165
563
  if (!eloop_is_timeout_registered(auth_eapol_rx, wpa, NULL))
166
0
    auth_read_msg(wpa);
167
563
}
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
5.87k
{
174
5.87k
  struct wpa *wpa = ctx;
175
176
5.87k
  wpa_printf(MSG_DEBUG,
177
5.87k
       "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d key_flag=0x%x)",
178
5.87k
       __func__, vlan_id, alg, idx, (int) key_len, key_flag);
179
5.87k
  if (addr)
180
5.87k
    wpa_printf(MSG_DEBUG, "AUTH: addr=" MACSTR, MAC2STR(addr));
181
182
5.87k
  if (alg != WPA_ALG_NONE && idx == 0 && key_len > 0 &&
183
1.16k
      !wpa->key_request_done) {
184
569
    wpa_printf(MSG_DEBUG, "Test EAPOL-Key Request");
185
569
    wpa->key_request_done = 1;
186
569
    if (!wpa->wpa1)
187
569
      eloop_register_timeout(0, 0, supp_eapol_key_request,
188
569
                 wpa, NULL);
189
569
  }
190
191
5.87k
  return 0;
192
5.87k
}
193
194
195
static int auth_init_group(struct wpa *wpa)
196
1.14k
{
197
1.14k
  struct wpa_auth_config conf;
198
199
1.14k
  wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
200
201
1.14k
  os_memset(&conf, 0, sizeof(conf));
202
1.14k
  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.14k
  } else {
208
1.14k
    conf.wpa = 2;
209
1.14k
    conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK;
210
1.14k
    conf.wpa_pairwise = WPA_CIPHER_CCMP;
211
1.14k
    conf.rsn_pairwise = WPA_CIPHER_CCMP;
212
1.14k
    conf.wpa_group = WPA_CIPHER_CCMP;
213
1.14k
    conf.ieee80211w = 2;
214
1.14k
    conf.group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
215
1.14k
  }
216
1.14k
  conf.eapol_version = 2;
217
1.14k
  conf.wpa_group_update_count = 4;
218
1.14k
  conf.wpa_pairwise_update_count = 4;
219
220
1.14k
  wpa->auth_cb.logger = auth_logger;
221
1.14k
  wpa->auth_cb.send_eapol = auth_send_eapol;
222
1.14k
  wpa->auth_cb.get_psk = auth_get_psk;
223
1.14k
  wpa->auth_cb.set_key = auth_set_key;
224
225
1.14k
  wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &wpa->auth_cb, wpa);
226
1.14k
  if (!wpa->auth_group) {
227
0
    wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed");
228
0
    return -1;
229
0
  }
230
231
1.14k
  return 0;
232
1.14k
}
233
234
235
static int auth_init(struct wpa *wpa)
236
1.14k
{
237
1.14k
  const u8 *supp_ie;
238
1.14k
  size_t supp_ie_len;
239
1.14k
  static const u8 ie_rsn[] = {
240
1.14k
    0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
241
1.14k
    0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00,
242
1.14k
    0x00, 0x0f, 0xac, 0x02, 0x80, 0x00
243
1.14k
  };
244
1.14k
  static const u8 ie_wpa[] = {
245
1.14k
    0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00,
246
1.14k
    0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50,
247
1.14k
    0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02
248
1.14k
  };
249
250
1.14k
  if (wpa->wpa1) {
251
0
    supp_ie = ie_wpa;
252
0
    supp_ie_len = sizeof(ie_wpa);
253
1.14k
  } else {
254
1.14k
    supp_ie = ie_rsn;
255
1.14k
    supp_ie_len = sizeof(ie_rsn);
256
1.14k
  }
257
258
1.14k
  wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr, NULL);
259
1.14k
  if (!wpa->auth) {
260
0
    wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed");
261
0
    return -1;
262
0
  }
263
264
1.14k
  if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, supp_ie,
265
1.14k
        supp_ie_len, NULL, 0, NULL, 0, NULL, 0, NULL,
266
1.14k
        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.14k
  wpa_auth_sm_event(wpa->auth, WPA_ASSOC);
272
273
1.14k
  wpa_auth_sta_associated(wpa->auth_group, wpa->auth);
274
275
1.14k
  return 0;
276
1.14k
}
277
278
279
static void deinit(struct wpa *wpa)
280
1.14k
{
281
1.14k
  wpa_auth_sta_deinit(wpa->auth);
282
1.14k
  wpa_deinit(wpa->auth_group);
283
1.14k
  os_free(wpa->supp_eapol);
284
1.14k
  wpa->supp_eapol = NULL;
285
1.14k
}
286
287
288
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
289
1.14k
{
290
1.14k
  struct wpa wpa;
291
292
1.14k
  wpa_fuzzer_set_debug_level();
293
294
1.14k
  if (os_program_init())
295
0
    return -1;
296
297
1.14k
  os_memset(&wpa, 0, sizeof(wpa));
298
1.14k
  wpa.data = data;
299
1.14k
  wpa.data_len = size;
300
301
1.14k
  os_memset(wpa.auth_addr, 0x12, ETH_ALEN);
302
1.14k
  os_memset(wpa.supp_addr, 0x32, ETH_ALEN);
303
1.14k
  os_memset(wpa.psk, 0x44, PMK_LEN);
304
305
1.14k
  if (eloop_init()) {
306
0
    wpa_printf(MSG_ERROR, "Failed to initialize event loop");
307
0
    goto fail;
308
0
  }
309
310
1.14k
  if (auth_init_group(&wpa) < 0)
311
0
    goto fail;
312
313
1.14k
  if (auth_init(&wpa) < 0)
314
0
    goto fail;
315
316
1.14k
  wpa_printf(MSG_DEBUG, "Starting eloop");
317
1.14k
  eloop_run();
318
1.14k
  wpa_printf(MSG_DEBUG, "eloop done");
319
320
1.14k
fail:
321
1.14k
  deinit(&wpa);
322
323
1.14k
  eloop_destroy();
324
325
1.14k
  os_program_deinit();
326
327
1.14k
  return 0;
328
1.14k
}