Coverage Report

Created: 2023-03-26 06:22

/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
11.5k
{
43
11.5k
  u16 msg_len;
44
11.5k
  u8 *msg;
45
46
11.5k
  if (wpa->data_len - wpa->data_offset < 2) {
47
1.06k
    wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len");
48
1.06k
    eloop_terminate();
49
1.06k
    return NULL;
50
1.06k
  }
51
10.5k
  msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]);
52
10.5k
  wpa->data_offset += 2;
53
54
10.5k
  msg = os_malloc(msg_len);
55
10.5k
  if (!msg)
56
0
    return NULL;
57
10.5k
  if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) {
58
31
    wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)",
59
31
         msg_len);
60
31
    os_free(msg);
61
31
    eloop_terminate();
62
31
    return NULL;
63
31
  }
64
10.4k
  os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len);
65
10.4k
  wpa->data_offset += msg_len;
66
10.4k
  wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len);
67
68
10.4k
  *ret_len = msg_len;
69
10.4k
  return msg;
70
10.5k
}
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
10.4k
{
84
10.4k
  wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state);
85
10.4k
}
86
87
88
static void supp_eapol_rx(void *eloop_data, void *user_ctx)
89
10.4k
{
90
10.4k
  struct wpa *wpa = eloop_data;
91
92
10.4k
  wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame");
93
10.4k
  wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol,
94
10.4k
      wpa->auth_eapol_len, FRAME_ENCRYPTION_UNKNOWN);
95
10.4k
}
96
97
98
static int supp_read_msg(struct wpa *wpa)
99
11.5k
{
100
11.5k
  os_free(wpa->auth_eapol);
101
11.5k
  wpa->auth_eapol = read_msg(wpa, &wpa->auth_eapol_len);
102
11.5k
  if (!wpa->auth_eapol)
103
1.09k
    return -1;
104
10.4k
  eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL);
105
10.4k
  return 0;
106
11.5k
}
107
108
109
static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
110
         size_t len)
111
9.59k
{
112
9.59k
  struct wpa *wpa = ctx;
113
114
9.59k
  wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
115
9.59k
       "len=%lu)",
116
9.59k
       __func__, MAC2STR(dest), proto, (unsigned long) len);
117
118
9.59k
  return supp_read_msg(wpa);
119
9.59k
}
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
9.59k
{
125
9.59k
  struct ieee802_1x_hdr *hdr;
126
127
9.59k
  wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)",
128
9.59k
       __func__, type, data_len);
129
130
9.59k
  *msg_len = sizeof(*hdr) + data_len;
131
9.59k
  hdr = os_malloc(*msg_len);
132
9.59k
  if (hdr == NULL)
133
0
    return NULL;
134
135
9.59k
  hdr->version = 2;
136
9.59k
  hdr->type = type;
137
9.59k
  hdr->length = host_to_be16(data_len);
138
139
9.59k
  if (data)
140
0
    os_memcpy(hdr + 1, data, data_len);
141
9.59k
  else
142
9.59k
    os_memset(hdr + 1, 0, data_len);
143
144
9.59k
  if (data_pos)
145
9.59k
    *data_pos = hdr + 1;
146
147
9.59k
  return (u8 *) hdr;
148
9.59k
}
149
150
151
static int supp_get_beacon_ie(void *ctx)
152
258
{
153
258
  struct wpa *wpa = ctx;
154
258
  const u8 *ie;
155
258
  static const u8 wpaie[] = {
156
258
    0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00,
157
258
    0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50,
158
258
    0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02
159
258
  };
160
258
  static const u8 rsne[] = {
161
258
    0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
162
258
    0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00,
163
258
    0x00, 0x0f, 0xac, 0x02, 0xc0, 0x00
164
258
  };
165
166
258
  wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
167
168
258
  ie = wpa->wpa1 ? wpaie : rsne;
169
258
  if (ie[0] == WLAN_EID_RSN)
170
258
    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
258
}
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
194
{
180
194
  wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d "
181
194
       "set_tx=%d key_flag=0x%x link_id=%d)",
182
194
       __func__, alg, MAC2STR(addr), key_idx, set_tx, key_flag,
183
194
       link_id);
184
194
  wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len);
185
194
  wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len);
186
194
  return 0;
187
194
}
188
189
190
static int supp_mlme_setprotection(void *ctx, const u8 *addr,
191
           int protection_type, int key_type)
192
270
{
193
270
  wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d "
194
270
       "key_type=%d)",
195
270
       __func__, MAC2STR(addr), protection_type, key_type);
196
270
  return 0;
197
270
}
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.25k
{
208
9.25k
  return (void *) 1;
209
9.25k
}
210
211
212
static void supp_deauthenticate(void *ctx, u16 reason_code)
213
2.05k
{
214
2.05k
  wpa_printf(MSG_DEBUG, "SUPP: %s(%d)", __func__, reason_code);
215
2.05k
}
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
1.96k
{
226
1.96k
  struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx));
227
228
1.96k
  if (!ctx)
229
0
    return -1;
230
231
1.96k
  ctx->ctx = wpa;
232
1.96k
  ctx->msg_ctx = wpa;
233
1.96k
  ctx->set_state = supp_set_state;
234
1.96k
  ctx->get_bssid = supp_get_bssid;
235
1.96k
  ctx->ether_send = supp_ether_send;
236
1.96k
  ctx->get_beacon_ie = supp_get_beacon_ie;
237
1.96k
  ctx->alloc_eapol = supp_alloc_eapol;
238
1.96k
  ctx->set_key = supp_set_key;
239
1.96k
  ctx->mlme_setprotection = supp_mlme_setprotection;
240
1.96k
  ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
241
1.96k
  ctx->get_network_ctx = supp_get_network_ctx;
242
1.96k
  ctx->deauthenticate = supp_deauthenticate;
243
1.96k
  ctx->get_state = supp_get_state;
244
1.96k
  wpa->supp = wpa_sm_init(ctx);
245
1.96k
  if (!wpa->supp) {
246
0
    wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
247
0
    return -1;
248
0
  }
249
250
1.96k
  wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr);
251
1.96k
  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
1.96k
  } else {
260
1.96k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1);
261
1.96k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN);
262
1.96k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE,
263
1.96k
         WPA_CIPHER_CCMP);
264
1.96k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
265
1.96k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT,
266
1.96k
         WPA_KEY_MGMT_PSK);
267
1.96k
    wpa_sm_set_param(wpa->supp, WPA_PARAM_MFP,
268
1.96k
         MGMT_FRAME_PROTECTION_OPTIONAL);
269
1.96k
  }
270
1.96k
  wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN, NULL, NULL);
271
272
1.96k
  wpa->supp_ie_len = sizeof(wpa->supp_ie);
273
1.96k
  if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie,
274
1.96k
              &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
1.96k
  wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr);
281
1.96k
  supp_read_msg(wpa);
282
283
1.96k
  return 0;
284
1.96k
}
285
286
287
static void deinit(struct wpa *wpa)
288
1.96k
{
289
1.96k
  wpa_sm_deinit(wpa->supp);
290
1.96k
  os_free(wpa->auth_eapol);
291
1.96k
  wpa->auth_eapol = NULL;
292
1.96k
}
293
294
295
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
296
1.96k
{
297
1.96k
  struct wpa wpa;
298
299
1.96k
  wpa_fuzzer_set_debug_level();
300
301
1.96k
  if (os_program_init())
302
0
    return -1;
303
304
1.96k
  os_memset(&wpa, 0, sizeof(wpa));
305
1.96k
  wpa.data = data;
306
1.96k
  wpa.data_len = size;
307
308
1.96k
  os_memset(wpa.auth_addr, 0x12, ETH_ALEN);
309
1.96k
  os_memset(wpa.supp_addr, 0x32, ETH_ALEN);
310
1.96k
  os_memset(wpa.psk, 0x44, PMK_LEN);
311
312
1.96k
  if (eloop_init()) {
313
0
    wpa_printf(MSG_ERROR, "Failed to initialize event loop");
314
0
    goto fail;
315
0
  }
316
317
1.96k
  if (supp_init(&wpa) < 0)
318
0
    goto fail;
319
320
1.96k
  wpa_printf(MSG_DEBUG, "Starting eloop");
321
1.96k
  eloop_run();
322
1.96k
  wpa_printf(MSG_DEBUG, "eloop done");
323
324
1.96k
fail:
325
1.96k
  deinit(&wpa);
326
327
1.96k
  eloop_destroy();
328
329
1.96k
  os_program_deinit();
330
331
1.96k
  return 0;
332
1.96k
}