Coverage Report

Created: 2025-04-24 06:18

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