diff options
Diffstat (limited to 'contrib/wpa/tests/fuzzing')
91 files changed, 3027 insertions, 0 deletions
diff --git a/contrib/wpa/tests/fuzzing/README b/contrib/wpa/tests/fuzzing/README new file mode 100644 index 000000000000..9ba0f176f2cd --- /dev/null +++ b/contrib/wpa/tests/fuzzing/README @@ -0,0 +1,23 @@ +hostap.git fuzz testing +----------------------- + +These tools can be used for fuzz testing of various components used +within wpa_supplicant and hostapd. Each directory contains a fuzzing +tool that focuses on one input handler. Each tool can be compiled either +to work with the libFuzzer or as a separate tool that reads the input +from a file specified on the command line, e.g., for American fuzzy lop +(afl-fuzz). Example test corpus is included in */corpus directory. + +Example fuzzing with libFuzzer + +cd @TOOL@ +make clean +make LIBFUZZER=y +./@TOOL@ corpus + +Example fuzzing with afl-fuzz + +cd @TOOL@ +make clean +CC=afl-gcc make +afl-fuzz -i corpus -o findings -- $PWD/@TOOL@ @@ diff --git a/contrib/wpa/tests/fuzzing/ap-mgmt/.gitignore b/contrib/wpa/tests/fuzzing/ap-mgmt/.gitignore new file mode 100644 index 000000000000..8d79d3c8062d --- /dev/null +++ b/contrib/wpa/tests/fuzzing/ap-mgmt/.gitignore @@ -0,0 +1 @@ +ap-mgmt diff --git a/contrib/wpa/tests/fuzzing/ap-mgmt/Makefile b/contrib/wpa/tests/fuzzing/ap-mgmt/Makefile new file mode 100644 index 000000000000..74b6a02da3fd --- /dev/null +++ b/contrib/wpa/tests/fuzzing/ap-mgmt/Makefile @@ -0,0 +1,44 @@ +ALL=ap-mgmt +include ../rules.include + +CFLAGS += -DCONFIG_WNM +CFLAGS += -DCONFIG_INTERWORKING +CFLAGS += -DCONFIG_GAS +CFLAGS += -DCONFIG_HS20 +CFLAGS += -DIEEE8021X_EAPOL +CFLAGS += -DNEED_AP_MLME +CFLAGS += -DCONFIG_AIRTIME_POLICY + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/wps/libwps.a +LIBS += $(SRC)/eap_server/libeap_server.a +LIBS += $(SRC)/eap_common/libeap_common.a +LIBS += $(SRC)/l2_packet/libl2_packet.a +LIBS += $(SRC)/ap/libap.a +LIBS += $(SRC)/eapol_auth/libeapol_auth.a +LIBS += $(SRC)/radius/libradius.a +LIBS += $(SRC)/utils/libutils.a + +ELIBS += $(SRC)/crypto/libcrypto.a +ELIBS += $(SRC)/tls/libtls.a + +OBJS += $(SRC)/drivers/driver_common.o + +OBJS += ap-mgmt.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +ap-mgmt: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + +clean: common-clean + rm -f ap-mgmt *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/ap-mgmt/ap-mgmt.c b/contrib/wpa/tests/fuzzing/ap-mgmt/ap-mgmt.c new file mode 100644 index 000000000000..d49ac5f08aea --- /dev/null +++ b/contrib/wpa/tests/fuzzing/ap-mgmt/ap-mgmt.c @@ -0,0 +1,167 @@ +/* + * hostapd - Management frame fuzzer + * Copyright (c) 2015-2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "ap/hostapd.h" +#include "ap/hw_features.h" +#include "ap/ieee802_11.h" +#include "ap/sta_info.h" +#include "ap/ap_list.h" +#include "../fuzzer-common.h" + + +const struct wpa_driver_ops *const wpa_drivers[] = +{ + NULL +}; + + +struct arg_ctx { + const u8 *data; + size_t data_len; + struct hostapd_iface iface; + struct hostapd_data hapd; + struct wpa_driver_ops driver; + struct hostapd_config iconf; + struct hostapd_bss_config conf; +}; + + +static void test_send_mgmt(void *eloop_data, void *user_ctx) +{ + struct arg_ctx *ctx = eloop_data; + struct hostapd_frame_info fi; + const u8 *pos, *end; + + os_memset(&fi, 0, sizeof(fi)); + + pos = ctx->data; + end = pos + ctx->data_len; + + while (end - pos > 2) { + u16 flen; + + flen = WPA_GET_BE16(pos); + pos += 2; + if (end - pos < flen) + break; + wpa_hexdump(MSG_MSGDUMP, "fuzzer - frame", pos, flen); + ieee802_11_mgmt(&ctx->hapd, pos, flen, &fi); + pos += flen; + } + + eloop_terminate(); +} + + +static struct hostapd_hw_modes * gen_modes(void) +{ + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *chan; + + mode = os_zalloc(sizeof(struct hostapd_hw_modes)); + if (!mode) + return NULL; + + mode->mode = HOSTAPD_MODE_IEEE80211G; + chan = os_zalloc(sizeof(struct hostapd_channel_data)); + if (!chan) { + os_free(mode); + return NULL; + } + chan->chan = 1; + chan->freq = 2412; + mode->channels = chan; + mode->num_channels = 1; + + mode->rates = os_zalloc(sizeof(int)); + if (!mode->rates) { + os_free(chan); + os_free(mode); + return NULL; + } + mode->rates[0] = 10; + mode->num_rates = 1; + + return mode; +} + + +static int init_hapd(struct arg_ctx *ctx) +{ + struct hostapd_data *hapd = &ctx->hapd; + struct sta_info *sta; + struct hostapd_bss_config *bss; + + hapd->driver = &ctx->driver; + os_memcpy(hapd->own_addr, "\x02\x00\x00\x00\x03\x00", ETH_ALEN); + hapd->iface = &ctx->iface; + hapd->iface->conf = hostapd_config_defaults(); + if (!hapd->iface->conf) + return -1; + hapd->iface->hw_features = gen_modes(); + hapd->iface->num_hw_features = 1; + hapd->iface->current_mode = hapd->iface->hw_features; + hapd->iconf = hapd->iface->conf; + hapd->iconf->hw_mode = HOSTAPD_MODE_IEEE80211G; + hapd->iconf->channel = 1; + bss = hapd->conf = hapd->iconf->bss[0]; + hostapd_config_defaults_bss(hapd->conf); + os_memcpy(bss->ssid.ssid, "test", 4); + bss->ssid.ssid_len = 4; + bss->ssid.ssid_set = 1; + + sta = ap_sta_add(hapd, (u8 *) "\x02\x00\x00\x00\x00\x00"); + if (sta) + sta->flags |= WLAN_STA_ASSOC | WLAN_STA_WMM; + + return 0; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct arg_ctx ctx; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + return 0; + } + + os_memset(&ctx, 0, sizeof(ctx)); + ctx.data = data; + ctx.data_len = size; + + if (init_hapd(&ctx)) + goto fail; + + eloop_register_timeout(0, 0, test_send_mgmt, &ctx, NULL); + + wpa_printf(MSG_DEBUG, "Starting eloop"); + eloop_run(); + wpa_printf(MSG_DEBUG, "eloop done"); + hostapd_free_stas(&ctx.hapd); + hostapd_free_hw_features(ctx.hapd.iface->hw_features, + ctx.hapd.iface->num_hw_features); + +fail: + hostapd_config_free(ctx.hapd.iconf); + ap_list_deinit(&ctx.iface); + eloop_destroy(); + os_program_deinit(); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi-sae-ffc.dat b/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi-sae-ffc.dat Binary files differnew file mode 100644 index 000000000000..8c0059d5f322 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi-sae-ffc.dat diff --git a/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi-sae.dat b/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi-sae.dat Binary files differnew file mode 100644 index 000000000000..31a0d091dba9 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi-sae.dat diff --git a/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi.dat b/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi.dat Binary files differnew file mode 100644 index 000000000000..29d074e0c414 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/ap-mgmt/corpus/multi.dat diff --git a/contrib/wpa/tests/fuzzing/asn1/.gitignore b/contrib/wpa/tests/fuzzing/asn1/.gitignore new file mode 100644 index 000000000000..69d0e5c726be --- /dev/null +++ b/contrib/wpa/tests/fuzzing/asn1/.gitignore @@ -0,0 +1 @@ +asn1 diff --git a/contrib/wpa/tests/fuzzing/asn1/Makefile b/contrib/wpa/tests/fuzzing/asn1/Makefile new file mode 100644 index 000000000000..274641a406bb --- /dev/null +++ b/contrib/wpa/tests/fuzzing/asn1/Makefile @@ -0,0 +1,23 @@ +ALL=asn1 +include ../rules.include + +OBJS += $(SRC)/utils/common.o +OBJS += $(SRC)/utils/os_unix.o +OBJS += $(SRC)/utils/wpa_debug.o +OBJS += $(SRC)/utils/wpabuf.o +OBJS += $(SRC)/tls/asn1.o + +OBJS += asn1.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +asn1: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + +clean: common-clean + $(MAKE) -C $(SRC) clean + rm -f asn1 *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/asn1/asn1.c b/contrib/wpa/tests/fuzzing/asn1/asn1.c new file mode 100644 index 000000000000..2cd18fe994ef --- /dev/null +++ b/contrib/wpa/tests/fuzzing/asn1/asn1.c @@ -0,0 +1,184 @@ +/* + * Fuzzing tool for ASN.1 routines + * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "tls/asn1.h" +#include "../fuzzer-common.h" + + +static const char * asn1_class_str(int class) +{ + switch (class) { + case ASN1_CLASS_UNIVERSAL: + return "Universal"; + case ASN1_CLASS_APPLICATION: + return "Application"; + case ASN1_CLASS_CONTEXT_SPECIFIC: + return "Context-specific"; + case ASN1_CLASS_PRIVATE: + return "Private"; + default: + return "?"; + } +} + + +static int asn1_parse(const u8 *buf, size_t len, int level) +{ + const u8 *pos, *prev, *end; + char prefix[10], str[100]; + int _level; + struct asn1_hdr hdr; + struct asn1_oid oid; + u8 tmp; + + _level = level; + if ((size_t) _level > sizeof(prefix) - 1) + _level = sizeof(prefix) - 1; + memset(prefix, ' ', _level); + prefix[_level] = '\0'; + + pos = buf; + end = buf + len; + + while (pos < end) { + if (asn1_get_next(pos, end - pos, &hdr) < 0) + return -1; + + prev = pos; + pos = hdr.payload; + + wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) " + "Tag %u Length %u", + prefix, hdr.class, asn1_class_str(hdr.class), + hdr.constructed, + hdr.constructed ? "Constructed" : "Primitive", + hdr.tag, hdr.length); + + if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && + hdr.constructed) { + if (asn1_parse(pos, hdr.length, level + 1) < 0) + return -1; + pos += hdr.length; + } + + if (hdr.class != ASN1_CLASS_UNIVERSAL) + continue; + + switch (hdr.tag) { + case ASN1_TAG_EOC: + if (hdr.length) { + wpa_printf(MSG_DEBUG, "ASN.1: Non-zero " + "end-of-contents length (%u)", + hdr.length); + return -1; + } + wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix); + break; + case ASN1_TAG_BOOLEAN: + if (hdr.length != 1) { + wpa_printf(MSG_DEBUG, "ASN.1: Unexpected " + "Boolean length (%u)", hdr.length); + return -1; + } + tmp = *pos++; + wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s", + prefix, tmp ? "TRUE" : "FALSE"); + break; + case ASN1_TAG_INTEGER: + wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER", + pos, hdr.length); + pos += hdr.length; + break; + case ASN1_TAG_BITSTRING: + wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString", + pos, hdr.length); + pos += hdr.length; + break; + case ASN1_TAG_OCTETSTRING: + wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString", + pos, hdr.length); + pos += hdr.length; + break; + case ASN1_TAG_NULL: + if (hdr.length) { + wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null " + "length (%u)", hdr.length); + return -1; + } + wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix); + break; + case ASN1_TAG_OID: + if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) { + wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID"); + return -1; + } + asn1_oid_to_str(&oid, str, sizeof(str)); + wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str); + pos += hdr.length; + break; + case ANS1_TAG_RELATIVE_OID: + wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID", + pos, hdr.length); + pos += hdr.length; + break; + case ASN1_TAG_SEQUENCE: + wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix); + if (asn1_parse(pos, hdr.length, level + 1) < 0) + return -1; + pos += hdr.length; + break; + case ASN1_TAG_SET: + wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix); + if (asn1_parse(pos, hdr.length, level + 1) < 0) + return -1; + pos += hdr.length; + break; + case ASN1_TAG_PRINTABLESTRING: + wpa_hexdump_ascii(MSG_MSGDUMP, + "ASN.1: PrintableString", + pos, hdr.length); + pos += hdr.length; + break; + case ASN1_TAG_IA5STRING: + wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String", + pos, hdr.length); + pos += hdr.length; + break; + case ASN1_TAG_UTCTIME: + wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME", + pos, hdr.length); + pos += hdr.length; + break; + case ASN1_TAG_VISIBLESTRING: + wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString", + pos, hdr.length); + pos += hdr.length; + break; + default: + wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d", + hdr.tag); + return -1; + } + } + + return 0; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + wpa_fuzzer_set_debug_level(); + + if (asn1_parse(data, size, 0) < 0) + wpa_printf(MSG_DEBUG, "Failed to parse DER ASN.1"); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/asn1/corpus/ca.der b/contrib/wpa/tests/fuzzing/asn1/corpus/ca.der Binary files differnew file mode 100644 index 000000000000..09d5fa051bf3 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/asn1/corpus/ca.der diff --git a/contrib/wpa/tests/fuzzing/asn1/corpus/ocsp-multi-server-cache.der b/contrib/wpa/tests/fuzzing/asn1/corpus/ocsp-multi-server-cache.der Binary files differnew file mode 100644 index 000000000000..36be8118aa1d --- /dev/null +++ b/contrib/wpa/tests/fuzzing/asn1/corpus/ocsp-multi-server-cache.der diff --git a/contrib/wpa/tests/fuzzing/asn1/corpus/ocsp-req.der b/contrib/wpa/tests/fuzzing/asn1/corpus/ocsp-req.der Binary files differnew file mode 100644 index 000000000000..3a70e3872d4c --- /dev/null +++ b/contrib/wpa/tests/fuzzing/asn1/corpus/ocsp-req.der diff --git a/contrib/wpa/tests/fuzzing/build-test.sh b/contrib/wpa/tests/fuzzing/build-test.sh new file mode 100755 index 000000000000..26c94cca833d --- /dev/null +++ b/contrib/wpa/tests/fuzzing/build-test.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +error() +{ + echo "Build test failed" + exit 1 +} + +for i in *; do + if [ -d $i ]; then + cd $i + make clean + make -j8 || error + make clean + cd .. + fi +done + +echo "Build test succeeded" diff --git a/contrib/wpa/tests/fuzzing/dpp-uri/.gitignore b/contrib/wpa/tests/fuzzing/dpp-uri/.gitignore new file mode 100644 index 000000000000..6dd276499bef --- /dev/null +++ b/contrib/wpa/tests/fuzzing/dpp-uri/.gitignore @@ -0,0 +1 @@ +dpp-uri diff --git a/contrib/wpa/tests/fuzzing/dpp-uri/Makefile b/contrib/wpa/tests/fuzzing/dpp-uri/Makefile new file mode 100644 index 000000000000..1c1bab631a04 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/dpp-uri/Makefile @@ -0,0 +1,43 @@ +all: dpp-uri +include ../rules.include + +CFLAGS += -DCONFIG_DPP +CFLAGS += -DCONFIG_DPP2 +CFLAGS += -DCONFIG_SHA256 +CFLAGS += -DCONFIG_SHA384 +CFLAGS += -DCONFIG_SHA512 +CFLAGS += -DCONFIG_ECC +CFLAGS += -DCONFIG_OPENSSL_CMAC + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += $(SRC)/crypto/crypto_openssl.o + +OBJS += $(SRC)/crypto/aes-ctr.o +OBJS += $(SRC)/crypto/aes-siv.o +OBJS += $(SRC)/crypto/sha256-kdf.o +OBJS += $(SRC)/crypto/sha384-kdf.o +OBJS += $(SRC)/crypto/sha512-kdf.o +OBJS += $(SRC)/tls/asn1.o +OBJS += $(SRC)/common/dpp.o +OBJS += $(SRC)/common/dpp_auth.o +OBJS += $(SRC)/common/dpp_backup.o +OBJS += $(SRC)/common/dpp_crypto.o +OBJS += $(SRC)/common/dpp_pkex.o +OBJS += $(SRC)/common/dpp_reconfig.o +OBJS += $(SRC)/common/dpp_tcp.o + +OBJS += dpp-uri.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +dpp-uri: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto + +clean: common-clean + rm -f dpp-uri *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/dpp-uri/corpus/1.dat b/contrib/wpa/tests/fuzzing/dpp-uri/corpus/1.dat new file mode 100644 index 000000000000..b2387e09ad07 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/dpp-uri/corpus/1.dat @@ -0,0 +1 @@ +DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;;
\ No newline at end of file diff --git a/contrib/wpa/tests/fuzzing/dpp-uri/corpus/2.dat b/contrib/wpa/tests/fuzzing/dpp-uri/corpus/2.dat new file mode 100644 index 000000000000..ee2ff90dd360 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/dpp-uri/corpus/2.dat @@ -0,0 +1 @@ +DPP:C:81/1,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;;
\ No newline at end of file diff --git a/contrib/wpa/tests/fuzzing/dpp-uri/corpus/3.dat b/contrib/wpa/tests/fuzzing/dpp-uri/corpus/3.dat new file mode 100644 index 000000000000..ce7ad16f3329 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/dpp-uri/corpus/3.dat @@ -0,0 +1 @@ +DPP:I:SN=4774LH2b4044;M:010203040506;C:81/1,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;;
\ No newline at end of file diff --git a/contrib/wpa/tests/fuzzing/dpp-uri/dpp-uri.c b/contrib/wpa/tests/fuzzing/dpp-uri/dpp-uri.c new file mode 100644 index 000000000000..77db5b8bbf40 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/dpp-uri/dpp-uri.c @@ -0,0 +1,51 @@ +/* + * DPP URI fuzzer + * Copyright (c) 2020, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/dpp.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct dpp_global *dpp; + struct dpp_global_config config; + struct dpp_bootstrap_info *bi; + char *uri; + char buf[1000]; + int ret = -1; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + uri = os_malloc(size + 1); + if (!uri) + goto out; + os_memcpy(uri, data, size); + uri[size] = '\0'; + os_memset(&config, 0, sizeof(config)); + dpp = dpp_global_init(&config); + if (!dpp) + goto out; + + bi = dpp_add_qr_code(dpp, uri); + if (bi && dpp_bootstrap_info(dpp, bi->id, buf, sizeof(buf)) > 0) + wpa_printf(MSG_DEBUG, "DPP: %s", buf); + dpp_global_deinit(dpp); + + ret = 0; +out: + os_free(uri); + os_program_deinit(); + + return ret; +} diff --git a/contrib/wpa/tests/fuzzing/eap-aka-peer/.gitignore b/contrib/wpa/tests/fuzzing/eap-aka-peer/.gitignore new file mode 100644 index 000000000000..d11f75fe3bd9 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-aka-peer/.gitignore @@ -0,0 +1 @@ +eap-aka-peer diff --git a/contrib/wpa/tests/fuzzing/eap-aka-peer/Makefile b/contrib/wpa/tests/fuzzing/eap-aka-peer/Makefile new file mode 100644 index 000000000000..c964f186d146 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-aka-peer/Makefile @@ -0,0 +1,26 @@ +ALL=eap-aka-peer +include ../rules.include + +CFLAGS += -DIEEE8021X_EAPOL +CFLAGS += -DCONFIG_USIM_SIMULATOR + +OBJS += $(SRC)/eap_peer/eap_aka.o +OBJS += $(SRC)/eap_common/eap_sim_common.o +OBJS += $(SRC)/eap_common/eap_common.o +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += eap-aka-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eap-aka-peer: $(OBJS) $(LIBS) + $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + @$(E) " LD " $@ + +clean: common-clean + rm -f eap-aka-peer *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/eap-aka-peer/corpus/server.msg b/contrib/wpa/tests/fuzzing/eap-aka-peer/corpus/server.msg Binary files differnew file mode 100644 index 000000000000..64843912d838 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-aka-peer/corpus/server.msg diff --git a/contrib/wpa/tests/fuzzing/eap-aka-peer/eap-aka-peer.c b/contrib/wpa/tests/fuzzing/eap-aka-peer/eap-aka-peer.c new file mode 100644 index 000000000000..db06ed52b1de --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-aka-peer/eap-aka-peer.c @@ -0,0 +1,131 @@ +/* + * EAP-AKA peer fuzzer + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "eap_peer/eap_methods.h" +#include "eap_peer/eap_config.h" +#include "eap_peer/eap_i.h" +#include "../fuzzer-common.h" + +int eap_peer_sim_register(void); + +struct eap_method * registered_eap_method = NULL; + + +struct eap_method * eap_peer_method_alloc(int version, int vendor, + enum eap_type method, + const char *name) +{ + struct eap_method *eap; + eap = os_zalloc(sizeof(*eap)); + if (!eap) + return NULL; + eap->version = version; + eap->vendor = vendor; + eap->method = method; + eap->name = name; + return eap; +} + + +int eap_peer_method_register(struct eap_method *method) +{ + registered_eap_method = method; + return 0; +} + + +static struct eap_peer_config eap_aka_config = { + .identity = (u8 *) "0232010000000000", + .identity_len = 16, + .password = (u8 *) "90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123", + .password_len = 78, +}; + +struct eap_peer_config * eap_get_config(struct eap_sm *sm) +{ + return &eap_aka_config; +} + + +const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) +{ + static const char *id = "0232010000000000"; + + *len = os_strlen(id); + return (const u8 *) id; +} + + +const char * eap_get_config_phase1(struct eap_sm *sm) +{ + return NULL; +} + + +void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len) +{ +} + + +void eap_sm_request_identity(struct eap_sm *sm) +{ +} + + +void eap_sm_request_sim(struct eap_sm *sm, const char *req) +{ +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + const u8 *pos, *end; + struct eap_sm *sm; + void *priv; + struct eap_method_ret ret; + + wpa_fuzzer_set_debug_level(); + + eap_peer_aka_register(); + sm = os_zalloc(sizeof(*sm)); + if (!sm) + return 0; + priv = registered_eap_method->init(sm); + os_memset(&ret, 0, sizeof(ret)); + + pos = data; + end = pos + size; + + while (end - pos > 2) { + u16 flen; + struct wpabuf *buf, *req; + + flen = WPA_GET_BE16(pos); + pos += 2; + if (end - pos < flen) + break; + req = wpabuf_alloc_copy(pos, flen); + if (!req) + break; + wpa_hexdump_buf(MSG_MSGDUMP, "fuzzer - request", req); + buf = registered_eap_method->process(sm, priv, &ret, req); + wpa_hexdump_buf(MSG_MSGDUMP, "fuzzer - local response", buf); + wpabuf_free(req); + wpabuf_free(buf); + pos += flen; + } + + registered_eap_method->deinit(sm, priv); + os_free(registered_eap_method); + os_free(sm); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/.gitignore b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/.gitignore new file mode 100644 index 000000000000..3368b213cf0c --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/.gitignore @@ -0,0 +1 @@ +eap-mschapv2-peer diff --git a/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/Makefile b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/Makefile new file mode 100644 index 000000000000..7290e90c62b7 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/Makefile @@ -0,0 +1,25 @@ +ALL=eap-mschapv2-peer +include ../rules.include + +CFLAGS += -DIEEE8021X_EAPOL + +OBJS += $(SRC)/eap_peer/eap_mschapv2.o +OBJS += $(SRC)/eap_peer/mschapv2.o +OBJS += $(SRC)/eap_common/eap_common.o +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += eap-mschapv2-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eap-mschapv2-peer: $(OBJS) $(LIBS) + $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + @$(E) " LD " $@ + +clean: common-clean + rm -f eap-mschapv2-peer *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/corpus/server.msg b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/corpus/server.msg Binary files differnew file mode 100644 index 000000000000..50ff9d19e3a5 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/corpus/server.msg diff --git a/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/eap-mschapv2-peer.c b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/eap-mschapv2-peer.c new file mode 100644 index 000000000000..8dc794cf867d --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-mschapv2-peer/eap-mschapv2-peer.c @@ -0,0 +1,152 @@ +/* + * EAP-SIM peer fuzzer + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "eap_peer/eap_methods.h" +#include "eap_peer/eap_config.h" +#include "eap_peer/eap_i.h" +#include "../fuzzer-common.h" + +int eap_peer_sim_register(void); + +struct eap_method * registered_eap_method = NULL; + + +struct eap_method * eap_peer_method_alloc(int version, int vendor, + enum eap_type method, + const char *name) +{ + struct eap_method *eap; + eap = os_zalloc(sizeof(*eap)); + if (!eap) + return NULL; + eap->version = version; + eap->vendor = vendor; + eap->method = method; + eap->name = name; + return eap; +} + + +int eap_peer_method_register(struct eap_method *method) +{ + registered_eap_method = method; + return 0; +} + + +static struct eap_peer_config eap_mschapv2_config = { + .identity = (u8 *) "user", + .identity_len = 4, + .password = (u8 *) "password", + .password_len = 8, +}; + +struct eap_peer_config * eap_get_config(struct eap_sm *sm) +{ + return &eap_mschapv2_config; +} + + +const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) +{ + static const char *id = "user"; + + *len = os_strlen(id); + return (const u8 *) id; +} + + +const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len) +{ + struct eap_peer_config *config = eap_get_config(sm); + + *len = config->password_len; + return config->password; +} + + +const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash) +{ + struct eap_peer_config *config = eap_get_config(sm); + + *len = config->password_len; + if (hash) + *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH); + return config->password; +} + + +const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len) +{ + *len = 3; + return (const u8 *) "new"; +} + + +void eap_sm_request_identity(struct eap_sm *sm) +{ +} + + +void eap_sm_request_password(struct eap_sm *sm) +{ +} + + +void eap_sm_request_new_password(struct eap_sm *sm) +{ +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + const u8 *pos, *end; + struct eap_sm *sm; + void *priv; + struct eap_method_ret ret; + + wpa_fuzzer_set_debug_level(); + + eap_peer_mschapv2_register(); + sm = os_zalloc(sizeof(*sm)); + if (!sm) + return 0; + priv = registered_eap_method->init(sm); + os_memset(&ret, 0, sizeof(ret)); + + pos = data; + end = pos + size; + + while (end - pos > 2) { + u16 flen; + struct wpabuf *buf, *req; + + flen = WPA_GET_BE16(pos); + pos += 2; + if (end - pos < flen) + break; + req = wpabuf_alloc_copy(pos, flen); + if (!req) + break; + wpa_hexdump_buf(MSG_MSGDUMP, "fuzzer - request", req); + buf = registered_eap_method->process(sm, priv, &ret, req); + wpa_hexdump_buf(MSG_MSGDUMP, "fuzzer - local response", buf); + wpabuf_free(req); + wpabuf_free(buf); + pos += flen; + } + + registered_eap_method->deinit(sm, priv); + os_free(registered_eap_method); + os_free(sm); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/eap-sim-peer/.gitignore b/contrib/wpa/tests/fuzzing/eap-sim-peer/.gitignore new file mode 100644 index 000000000000..ea94e26e2eb8 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-sim-peer/.gitignore @@ -0,0 +1 @@ +eap-sim-peer diff --git a/contrib/wpa/tests/fuzzing/eap-sim-peer/Makefile b/contrib/wpa/tests/fuzzing/eap-sim-peer/Makefile new file mode 100644 index 000000000000..9e728e4f476b --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-sim-peer/Makefile @@ -0,0 +1,26 @@ +ALL=eap-sim-peer +include ../rules.include + +CFLAGS += -DIEEE8021X_EAPOL +CFLAGS += -DCONFIG_SIM_SIMULATOR + +OBJS += $(SRC)/eap_peer/eap_sim.o +OBJS += $(SRC)/eap_common/eap_sim_common.o +OBJS += $(SRC)/eap_common/eap_common.o +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += eap-sim-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eap-sim-peer: $(OBJS) $(LIBS) + $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + @$(E) " LD " $@ + +clean: common-clean + rm -f eap-sim-peer *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/eap-sim-peer/corpus/server.msg b/contrib/wpa/tests/fuzzing/eap-sim-peer/corpus/server.msg Binary files differnew file mode 100644 index 000000000000..adb9f6c6fea9 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-sim-peer/corpus/server.msg diff --git a/contrib/wpa/tests/fuzzing/eap-sim-peer/eap-sim-peer.c b/contrib/wpa/tests/fuzzing/eap-sim-peer/eap-sim-peer.c new file mode 100644 index 000000000000..b6798ee47869 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eap-sim-peer/eap-sim-peer.c @@ -0,0 +1,125 @@ +/* + * EAP-SIM peer fuzzer + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "eap_peer/eap_methods.h" +#include "eap_peer/eap_config.h" +#include "eap_peer/eap_i.h" +#include "../fuzzer-common.h" + +int eap_peer_sim_register(void); + +struct eap_method * registered_eap_method = NULL; + + +struct eap_method * eap_peer_method_alloc(int version, int vendor, + enum eap_type method, + const char *name) +{ + struct eap_method *eap; + eap = os_zalloc(sizeof(*eap)); + if (!eap) + return NULL; + eap->version = version; + eap->vendor = vendor; + eap->method = method; + eap->name = name; + return eap; +} + + +int eap_peer_method_register(struct eap_method *method) +{ + registered_eap_method = method; + return 0; +} + + +static struct eap_peer_config eap_sim_config = { + .identity = (u8 *) "1232010000000000", + .identity_len = 16, + .password = (u8 *) "90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581", + .password_len = 65, +}; + +struct eap_peer_config * eap_get_config(struct eap_sm *sm) +{ + return &eap_sim_config; +} + + +const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) +{ + static const char *id = "1232010000000000"; + + *len = os_strlen(id); + return (const u8 *) id; +} + + +void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len) +{ +} + + +void eap_sm_request_identity(struct eap_sm *sm) +{ +} + + +void eap_sm_request_sim(struct eap_sm *sm, const char *req) +{ +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + const u8 *pos, *end; + struct eap_sm *sm; + void *priv; + struct eap_method_ret ret; + + wpa_fuzzer_set_debug_level(); + + eap_peer_sim_register(); + sm = os_zalloc(sizeof(*sm)); + if (!sm) + return 0; + priv = registered_eap_method->init(sm); + os_memset(&ret, 0, sizeof(ret)); + + pos = data; + end = pos + size; + + while (end - pos > 2) { + u16 flen; + struct wpabuf *buf, *req; + + flen = WPA_GET_BE16(pos); + pos += 2; + if (end - pos < flen) + break; + req = wpabuf_alloc_copy(pos, flen); + if (!req) + break; + wpa_hexdump_buf(MSG_MSGDUMP, "fuzzer - request", req); + buf = registered_eap_method->process(sm, priv, &ret, req); + wpa_hexdump_buf(MSG_MSGDUMP, "fuzzer - local response", buf); + wpabuf_free(req); + wpabuf_free(buf); + pos += flen; + } + + registered_eap_method->deinit(sm, priv); + os_free(registered_eap_method); + os_free(sm); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/eapol-key-auth/.gitignore b/contrib/wpa/tests/fuzzing/eapol-key-auth/.gitignore new file mode 100644 index 000000000000..f693f2cd05c0 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-auth/.gitignore @@ -0,0 +1 @@ +eapol-key-auth diff --git a/contrib/wpa/tests/fuzzing/eapol-key-auth/Makefile b/contrib/wpa/tests/fuzzing/eapol-key-auth/Makefile new file mode 100644 index 000000000000..bd15b91f2394 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-auth/Makefile @@ -0,0 +1,34 @@ +ALL=eapol-key-auth +include ../rules.include + +CFLAGS += -DCONFIG_IEEE80211R_AP +CFLAGS += -DCONFIG_IEEE80211R +CFLAGS += -DCONFIG_TDLS + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/eap_common/libeap_common.a +LIBS += $(SRC)/l2_packet/libl2_packet.a +LIBS += $(SRC)/utils/libutils.a +LIBS += $(SRC)/wps/libwps.a +LIBS += $(SRC)/eapol_auth/libeapol_auth.a +LIBS += $(SRC)/eap_server/libeap_server.a +LIBS += $(SRC)/ap/libap.a +LIBS += $(SRC)/radius/libradius.a + +OBJS += $(SRC)/drivers/driver_common.o + +OBJS += eapol-key-auth.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eapol-key-auth: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group + +clean: common-clean + rm -f eapol-key-auth *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/eapol-key-auth/corpus/supp.msg b/contrib/wpa/tests/fuzzing/eapol-key-auth/corpus/supp.msg Binary files differnew file mode 100644 index 000000000000..437d45175448 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-auth/corpus/supp.msg diff --git a/contrib/wpa/tests/fuzzing/eapol-key-auth/eapol-key-auth.c b/contrib/wpa/tests/fuzzing/eapol-key-auth/eapol-key-auth.c new file mode 100644 index 000000000000..bb46422c6dbc --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-auth/eapol-key-auth.c @@ -0,0 +1,328 @@ +/* + * Testing tool for EAPOL-Key Authenticator routines + * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "ap/wpa_auth.h" +#include "../fuzzer-common.h" + + +struct wpa { + const u8 *data; + size_t data_len; + size_t data_offset; + int wpa1; + + u8 auth_addr[ETH_ALEN]; + u8 supp_addr[ETH_ALEN]; + u8 psk[PMK_LEN]; + + /* from supplicant */ + u8 *supp_eapol; + size_t supp_eapol_len; + + struct wpa_auth_callbacks auth_cb; + struct wpa_authenticator *auth_group; + struct wpa_state_machine *auth; + + u8 supp_ie[80]; + size_t supp_ie_len; + + int key_request_done; + int key_request_done1; + int auth_sent; +}; + + +const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; + + +static int auth_read_msg(struct wpa *wpa); +static void supp_eapol_key_request(void *eloop_data, void *user_ctx); + + +static u8 * read_msg(struct wpa *wpa, size_t *ret_len) +{ + u16 msg_len; + u8 *msg; + + if (wpa->data_len - wpa->data_offset < 2) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); + eloop_terminate(); + return NULL; + } + msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]); + wpa->data_offset += 2; + + msg = os_malloc(msg_len); + if (!msg) + return NULL; + if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", + msg_len); + os_free(msg); + eloop_terminate(); + return NULL; + } + os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len); + wpa->data_offset += msg_len; + wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len); + + *ret_len = msg_len; + return msg; +} + + +static void auth_eapol_rx(void *eloop_data, void *user_ctx) +{ + struct wpa *wpa = eloop_data; + + wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame"); + wpa->auth_sent = 0; + wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol, + wpa->supp_eapol_len); + if (!wpa->auth_sent) { + /* Speed up process by not going through retransmit timeout */ + wpa_printf(MSG_DEBUG, + "AUTH: No response was sent - process next message"); + auth_read_msg(wpa); + } + if (wpa->wpa1 && wpa->key_request_done && !wpa->key_request_done1) { + wpa->key_request_done1 = 1; + eloop_register_timeout(0, 0, supp_eapol_key_request, + wpa, NULL); + } + +} + + +static void auth_logger(void *ctx, const u8 *addr, logger_level level, + const char *txt) +{ + if (addr) + wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s", + MAC2STR(addr), txt); + else + wpa_printf(MSG_DEBUG, "AUTH: %s", txt); +} + + +static int auth_read_msg(struct wpa *wpa) +{ + os_free(wpa->supp_eapol); + wpa->supp_eapol = read_msg(wpa, &wpa->supp_eapol_len); + if (!wpa->supp_eapol) + return -1; + eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL); + return 0; +} + + +static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, + size_t data_len, int encrypt) +{ + struct wpa *wpa = ctx; + + wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu " + "encrypt=%d)", + __func__, MAC2STR(addr), (unsigned long) data_len, encrypt); + wpa->auth_sent = 1; + + return auth_read_msg(wpa); +} + + +static const u8 * auth_get_psk(void *ctx, const u8 *addr, + const u8 *p2p_dev_addr, const u8 *prev_psk, + size_t *psk_len, int *vlan_id) +{ + struct wpa *wpa = ctx; + + wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", + __func__, MAC2STR(addr), prev_psk); + if (vlan_id) + *vlan_id = 0; + if (psk_len) + *psk_len = PMK_LEN; + if (prev_psk) + return NULL; + return wpa->psk; +} + + +static void supp_eapol_key_request(void *eloop_data, void *user_ctx) +{ + struct wpa *wpa = eloop_data; + + wpa_printf(MSG_DEBUG, "SUPP: EAPOL-Key Request trigger"); + if (!eloop_is_timeout_registered(auth_eapol_rx, wpa, NULL)) + auth_read_msg(wpa); +} + + +static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, + const u8 *addr, int idx, u8 *key, + size_t key_len, enum key_flag key_flag) +{ + struct wpa *wpa = ctx; + + wpa_printf(MSG_DEBUG, + "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d key_flag=0x%x)", + __func__, vlan_id, alg, idx, (int) key_len, key_flag); + if (addr) + wpa_printf(MSG_DEBUG, "AUTH: addr=" MACSTR, MAC2STR(addr)); + + if (alg != WPA_ALG_NONE && idx == 0 && key_len > 0 && + !wpa->key_request_done) { + wpa_printf(MSG_DEBUG, "Test EAPOL-Key Request"); + wpa->key_request_done = 1; + if (!wpa->wpa1) + eloop_register_timeout(0, 0, supp_eapol_key_request, + wpa, NULL); + } + + return 0; +} + + +static int auth_init_group(struct wpa *wpa) +{ + struct wpa_auth_config conf; + + wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine"); + + os_memset(&conf, 0, sizeof(conf)); + if (wpa->wpa1) { + conf.wpa = 1; + conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; + conf.wpa_pairwise = WPA_CIPHER_TKIP; + conf.wpa_group = WPA_CIPHER_TKIP; + } else { + conf.wpa = 2; + conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; + conf.wpa_pairwise = WPA_CIPHER_CCMP; + conf.rsn_pairwise = WPA_CIPHER_CCMP; + conf.wpa_group = WPA_CIPHER_CCMP; + conf.ieee80211w = 2; + conf.group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; + } + conf.eapol_version = 2; + conf.wpa_group_update_count = 4; + conf.wpa_pairwise_update_count = 4; + + wpa->auth_cb.logger = auth_logger; + wpa->auth_cb.send_eapol = auth_send_eapol; + wpa->auth_cb.get_psk = auth_get_psk; + wpa->auth_cb.set_key = auth_set_key; + + wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &wpa->auth_cb, wpa); + if (!wpa->auth_group) { + wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); + return -1; + } + + return 0; +} + + +static int auth_init(struct wpa *wpa) +{ + const u8 *supp_ie; + size_t supp_ie_len; + static const u8 ie_rsn[] = { + 0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, + 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, + 0x00, 0x0f, 0xac, 0x02, 0x80, 0x00 + }; + static const u8 ie_wpa[] = { + 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, + 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02 + }; + + if (wpa->wpa1) { + supp_ie = ie_wpa; + supp_ie_len = sizeof(ie_wpa); + } else { + supp_ie = ie_rsn; + supp_ie_len = sizeof(ie_rsn); + } + + wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr, NULL); + if (!wpa->auth) { + wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); + return -1; + } + + if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, supp_ie, + supp_ie_len, NULL, 0, NULL, 0, NULL, 0) != + WPA_IE_OK) { + wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); + return -1; + } + + wpa_auth_sm_event(wpa->auth, WPA_ASSOC); + + wpa_auth_sta_associated(wpa->auth_group, wpa->auth); + + return 0; +} + + +static void deinit(struct wpa *wpa) +{ + wpa_auth_sta_deinit(wpa->auth); + wpa_deinit(wpa->auth_group); + os_free(wpa->supp_eapol); + wpa->supp_eapol = NULL; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct wpa wpa; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return -1; + + os_memset(&wpa, 0, sizeof(wpa)); + wpa.data = data; + wpa.data_len = size; + + os_memset(wpa.auth_addr, 0x12, ETH_ALEN); + os_memset(wpa.supp_addr, 0x32, ETH_ALEN); + os_memset(wpa.psk, 0x44, PMK_LEN); + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + goto fail; + } + + if (auth_init_group(&wpa) < 0) + goto fail; + + if (auth_init(&wpa) < 0) + goto fail; + + wpa_printf(MSG_DEBUG, "Starting eloop"); + eloop_run(); + wpa_printf(MSG_DEBUG, "eloop done"); + +fail: + deinit(&wpa); + + eloop_destroy(); + + os_program_deinit(); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/eapol-key-supp/.gitignore b/contrib/wpa/tests/fuzzing/eapol-key-supp/.gitignore new file mode 100644 index 000000000000..dcbbbdb02651 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-supp/.gitignore @@ -0,0 +1 @@ +eapol-key-supp diff --git a/contrib/wpa/tests/fuzzing/eapol-key-supp/Makefile b/contrib/wpa/tests/fuzzing/eapol-key-supp/Makefile new file mode 100644 index 000000000000..949e2efe991c --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-supp/Makefile @@ -0,0 +1,30 @@ +ALL=eapol-key-supp +include ../rules.include + +CFLAGS += -DCONFIG_IEEE80211R_AP +CFLAGS += -DCONFIG_IEEE80211R +CFLAGS += -DCONFIG_TDLS + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/rsn_supp/librsn_supp.a +LIBS += $(SRC)/eapol_supp/libeapol_supp.a +LIBS += $(SRC)/eap_peer/libeap_peer.a +LIBS += $(SRC)/eap_common/libeap_common.a +LIBS += $(SRC)/l2_packet/libl2_packet.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += eapol-key-supp.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eapol-key-supp: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group + +clean: common-clean + rm -f eapol-key-supp *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/eapol-key-supp/corpus/auth.msg b/contrib/wpa/tests/fuzzing/eapol-key-supp/corpus/auth.msg Binary files differnew file mode 100644 index 000000000000..00ae53dff88e --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-supp/corpus/auth.msg diff --git a/contrib/wpa/tests/fuzzing/eapol-key-supp/eapol-key-supp.c b/contrib/wpa/tests/fuzzing/eapol-key-supp/eapol-key-supp.c new file mode 100644 index 000000000000..487c889d7a6d --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-key-supp/eapol-key-supp.c @@ -0,0 +1,331 @@ +/* + * Testing tool for EAPOL-Key Supplicant routines + * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "rsn_supp/wpa.h" +#include "../fuzzer-common.h" + + +struct wpa { + const u8 *data; + size_t data_len; + size_t data_offset; + int wpa1; + + u8 auth_addr[ETH_ALEN]; + u8 supp_addr[ETH_ALEN]; + u8 psk[PMK_LEN]; + + /* from authenticator */ + u8 *auth_eapol; + size_t auth_eapol_len; + + struct wpa_sm *supp; + + u8 supp_ie[80]; + size_t supp_ie_len; +}; + + +const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; + + +static u8 * read_msg(struct wpa *wpa, size_t *ret_len) +{ + u16 msg_len; + u8 *msg; + + if (wpa->data_len - wpa->data_offset < 2) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); + eloop_terminate(); + return NULL; + } + msg_len = WPA_GET_BE16(&wpa->data[wpa->data_offset]); + wpa->data_offset += 2; + + msg = os_malloc(msg_len); + if (!msg) + return NULL; + if (msg_len > 0 && wpa->data_len - wpa->data_offset < msg_len) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", + msg_len); + os_free(msg); + eloop_terminate(); + return NULL; + } + os_memcpy(msg, &wpa->data[wpa->data_offset], msg_len); + wpa->data_offset += msg_len; + wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len); + + *ret_len = msg_len; + return msg; +} + + +static int supp_get_bssid(void *ctx, u8 *bssid) +{ + struct wpa *wpa = ctx; + wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); + os_memcpy(bssid, wpa->auth_addr, ETH_ALEN); + return 0; +} + + +static void supp_set_state(void *ctx, enum wpa_states state) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state); +} + + +static void supp_eapol_rx(void *eloop_data, void *user_ctx) +{ + struct wpa *wpa = eloop_data; + + wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame"); + wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol, + wpa->auth_eapol_len); +} + + +static int supp_read_msg(struct wpa *wpa) +{ + os_free(wpa->auth_eapol); + wpa->auth_eapol = read_msg(wpa, &wpa->auth_eapol_len); + if (!wpa->auth_eapol) + return -1; + eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); + return 0; +} + + +static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, + size_t len) +{ + struct wpa *wpa = ctx; + + wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " + "len=%lu)", + __func__, MAC2STR(dest), proto, (unsigned long) len); + + return supp_read_msg(wpa); +} + + +static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, + u16 data_len, size_t *msg_len, void **data_pos) +{ + struct ieee802_1x_hdr *hdr; + + wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", + __func__, type, data_len); + + *msg_len = sizeof(*hdr) + data_len; + hdr = os_malloc(*msg_len); + if (hdr == NULL) + return NULL; + + hdr->version = 2; + hdr->type = type; + hdr->length = host_to_be16(data_len); + + if (data) + os_memcpy(hdr + 1, data, data_len); + else + os_memset(hdr + 1, 0, data_len); + + if (data_pos) + *data_pos = hdr + 1; + + return (u8 *) hdr; +} + + +static int supp_get_beacon_ie(void *ctx) +{ + struct wpa *wpa = ctx; + const u8 *ie; + static const u8 wpaie[] = { + 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, + 0x00, 0x50, 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, + 0xf2, 0x02, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x02 + }; + static const u8 rsne[] = { + 0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, + 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, + 0x00, 0x0f, 0xac, 0x02, 0xc0, 0x00 + }; + + wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); + + ie = wpa->wpa1 ? wpaie : rsne; + if (ie[0] == WLAN_EID_RSN) + return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]); + return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]); +} + + +static int supp_set_key(void *ctx, enum wpa_alg alg, + const u8 *addr, int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len, enum key_flag key_flag) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " + "set_tx=%d key_flag=0x%x)", + __func__, alg, MAC2STR(addr), key_idx, set_tx, key_flag); + wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); + wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); + return 0; +} + + +static int supp_mlme_setprotection(void *ctx, const u8 *addr, + int protection_type, int key_type) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " + "key_type=%d)", + __func__, MAC2STR(addr), protection_type, key_type); + return 0; +} + + +static void supp_cancel_auth_timeout(void *ctx) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); +} + + +static void * supp_get_network_ctx(void *ctx) +{ + return (void *) 1; +} + + +static void supp_deauthenticate(void *ctx, u16 reason_code) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s(%d)", __func__, reason_code); +} + + +static enum wpa_states supp_get_state(void *ctx) +{ + return WPA_COMPLETED; +} + + +static int supp_init(struct wpa *wpa) +{ + struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); + + if (!ctx) + return -1; + + ctx->ctx = wpa; + ctx->msg_ctx = wpa; + ctx->set_state = supp_set_state; + ctx->get_bssid = supp_get_bssid; + ctx->ether_send = supp_ether_send; + ctx->get_beacon_ie = supp_get_beacon_ie; + ctx->alloc_eapol = supp_alloc_eapol; + ctx->set_key = supp_set_key; + ctx->mlme_setprotection = supp_mlme_setprotection; + ctx->cancel_auth_timeout = supp_cancel_auth_timeout; + ctx->get_network_ctx = supp_get_network_ctx; + ctx->deauthenticate = supp_deauthenticate; + ctx->get_state = supp_get_state; + wpa->supp = wpa_sm_init(ctx); + if (!wpa->supp) { + wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); + return -1; + } + + wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr); + if (wpa->wpa1) { + wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 0); + wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_WPA); + wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, + WPA_CIPHER_TKIP); + wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_TKIP); + wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, + WPA_KEY_MGMT_PSK); + } else { + wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1); + wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); + wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, + WPA_CIPHER_CCMP); + wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); + wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, + WPA_KEY_MGMT_PSK); + wpa_sm_set_param(wpa->supp, WPA_PARAM_MFP, + MGMT_FRAME_PROTECTION_OPTIONAL); + } + wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN, NULL, NULL); + + wpa->supp_ie_len = sizeof(wpa->supp_ie); + if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie, + &wpa->supp_ie_len) < 0) { + wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" + " failed"); + return -1; + } + + wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr); + supp_read_msg(wpa); + + return 0; +} + + +static void deinit(struct wpa *wpa) +{ + wpa_sm_deinit(wpa->supp); + os_free(wpa->auth_eapol); + wpa->auth_eapol = NULL; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct wpa wpa; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return -1; + + os_memset(&wpa, 0, sizeof(wpa)); + wpa.data = data; + wpa.data_len = size; + + os_memset(wpa.auth_addr, 0x12, ETH_ALEN); + os_memset(wpa.supp_addr, 0x32, ETH_ALEN); + os_memset(wpa.psk, 0x44, PMK_LEN); + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + goto fail; + } + + if (supp_init(&wpa) < 0) + goto fail; + + wpa_printf(MSG_DEBUG, "Starting eloop"); + eloop_run(); + wpa_printf(MSG_DEBUG, "eloop done"); + +fail: + deinit(&wpa); + + eloop_destroy(); + + os_program_deinit(); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/eapol-supp/.gitignore b/contrib/wpa/tests/fuzzing/eapol-supp/.gitignore new file mode 100644 index 000000000000..e370093d82a3 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-supp/.gitignore @@ -0,0 +1 @@ +eapol-supp diff --git a/contrib/wpa/tests/fuzzing/eapol-supp/Makefile b/contrib/wpa/tests/fuzzing/eapol-supp/Makefile new file mode 100644 index 000000000000..ea32346b2df1 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-supp/Makefile @@ -0,0 +1,28 @@ +ALL=eapol-supp +include ../rules.include + +CFLAGS += -DIEEE8021X_EAPOL + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/rsn_supp/librsn_supp.a +LIBS += $(SRC)/eapol_supp/libeapol_supp.a +LIBS += $(SRC)/eap_peer/libeap_peer.a +LIBS += $(SRC)/eap_common/libeap_common.a +LIBS += $(SRC)/l2_packet/libl2_packet.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += eapol-supp.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eapol-supp: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group + +clean: common-clean + rm -f eapol-supp *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eap-req-identity.dat b/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eap-req-identity.dat Binary files differnew file mode 100644 index 000000000000..768b27754167 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eap-req-identity.dat diff --git a/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eap-req-sim.dat b/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eap-req-sim.dat Binary files differnew file mode 100644 index 000000000000..eb854aae01fd --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eap-req-sim.dat diff --git a/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eapol-key-m1.dat b/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eapol-key-m1.dat Binary files differnew file mode 100644 index 000000000000..937721c5013d --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-supp/corpus/eapol-key-m1.dat diff --git a/contrib/wpa/tests/fuzzing/eapol-supp/eapol-supp.c b/contrib/wpa/tests/fuzzing/eapol-supp/eapol-supp.c new file mode 100644 index 000000000000..94e0147adf15 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/eapol-supp/eapol-supp.c @@ -0,0 +1,198 @@ +/* + * wpa_supplicant - EAPOL fuzzer + * Copyright (c) 2015-2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "eapol_supp/eapol_supp_sm.h" +#include "rsn_supp/wpa.h" +#include "rsn_supp/wpa_i.h" +#include "../fuzzer-common.h" + + +struct arg_ctx { + const u8 *data; + size_t data_len; + struct wpa_sm *wpa; + struct eapol_sm *eapol; +}; + + +static void test_send_eapol(void *eloop_data, void *user_ctx) +{ + struct arg_ctx *ctx = eloop_data; + u8 src[ETH_ALEN] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 }; + u8 wpa_ie[200]; + size_t wpa_ie_len; + + wpa_hexdump(MSG_MSGDUMP, "fuzzer - EAPOL", ctx->data, ctx->data_len); + + eapol_sm_notify_portEnabled(ctx->eapol, true); + + wpa_sm_set_param(ctx->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN); + wpa_sm_set_param(ctx->wpa, WPA_PARAM_RSN_ENABLED, 1); + wpa_sm_set_param(ctx->wpa, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); + wpa_sm_set_param(ctx->wpa, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); + wpa_sm_set_param(ctx->wpa, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); + + wpa_ie_len = sizeof(wpa_ie); + wpa_sm_set_assoc_wpa_ie_default(ctx->wpa, wpa_ie, &wpa_ie_len); + + if (eapol_sm_rx_eapol(ctx->eapol, src, ctx->data, ctx->data_len) <= 0) + wpa_sm_rx_eapol(ctx->wpa, src, ctx->data, ctx->data_len); + + eloop_terminate(); +} + + +static void * get_network_ctx(void *arg) +{ + return (void *) 1; +} + + +static void set_state(void *arg, enum wpa_states state) +{ +} + + +static void deauthenticate(void *arg, u16 reason_code) +{ +} + + +static u8 * alloc_eapol(void *arg, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos) +{ + struct ieee802_1x_hdr *hdr; + + *msg_len = sizeof(*hdr) + data_len; + hdr = os_malloc(*msg_len); + if (hdr == NULL) + return NULL; + + hdr->version = 2; + hdr->type = type; + hdr->length = host_to_be16(data_len); + + if (data) + os_memcpy(hdr + 1, data, data_len); + else + os_memset(hdr + 1, 0, data_len); + + if (data_pos) + *data_pos = hdr + 1; + + return (u8 *) hdr; +} + + +static int ether_send(void *arg, const u8 *dest, u16 proto, + const u8 *buf, size_t len) +{ + return 0; +} + + +static int get_bssid(void *ctx, u8 *bssid) +{ + return -1; +} + + +static int eapol_send(void *ctx, int type, const u8 *buf, size_t len) +{ + return 0; +} + + +static int init_wpa(struct arg_ctx *arg) +{ + struct wpa_sm_ctx *ctx; + + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); + return -1; + } + + ctx->ctx = arg; + ctx->msg_ctx = arg; + ctx->get_network_ctx = get_network_ctx; + ctx->set_state = set_state; + ctx->deauthenticate = deauthenticate; + ctx->alloc_eapol = alloc_eapol; + ctx->ether_send = ether_send; + ctx->get_bssid = get_bssid; + + arg->wpa = wpa_sm_init(ctx); + if (!arg->wpa) + return -1; + arg->wpa->pmk_len = PMK_LEN; + return 0; +} + + +static int init_eapol(struct arg_ctx *arg) +{ + struct eapol_ctx *ctx; + + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); + return -1; + } + + ctx->ctx = arg; + ctx->msg_ctx = arg; + ctx->eapol_send = eapol_send; + + arg->eapol = eapol_sm_init(ctx); + return arg->eapol ? 0 : -1; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct arg_ctx ctx; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + return 0; + } + + os_memset(&ctx, 0, sizeof(ctx)); + ctx.data = data; + ctx.data_len = size; + if (init_wpa(&ctx) || init_eapol(&ctx)) + goto fail; + + eloop_register_timeout(0, 0, test_send_eapol, &ctx, NULL); + + wpa_printf(MSG_DEBUG, "Starting eloop"); + eloop_run(); + wpa_printf(MSG_DEBUG, "eloop done"); + +fail: + if (ctx.wpa) + wpa_sm_deinit(ctx.wpa); + if (ctx.eapol) + eapol_sm_deinit(ctx.eapol); + + eloop_destroy(); + os_program_deinit(); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/fuzzer-common.c b/contrib/wpa/tests/fuzzing/fuzzer-common.c new file mode 100644 index 000000000000..43b91e19a512 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/fuzzer-common.c @@ -0,0 +1,56 @@ +/* + * Common helper functions for fuzzing tools + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" + + +void wpa_fuzzer_set_debug_level(void) +{ + static int first = 1; + + if (first) { + char *env; + + first = 0; + env = getenv("WPADEBUG"); + if (env) + wpa_debug_level = atoi(env); + else + wpa_debug_level = MSG_ERROR + 1; + + wpa_debug_show_keys = 1; + } +} + + +#ifndef TEST_LIBFUZZER +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +int main(int argc, char *argv[]) +{ + char *data; + size_t len; + + if (argc < 2) { + printf("usage: %s <file>\n", argv[0]); + return -1; + } + + data = os_readfile(argv[1], &len); + if (!data) { + printf("Could not read '%s'\n", argv[1]); + return -1; + } + + LLVMFuzzerTestOneInput((const uint8_t *) data, len); + os_free(data); + return 0; +} +#endif /* !TEST_LIBFUZZER */ diff --git a/contrib/wpa/tests/fuzzing/fuzzer-common.h b/contrib/wpa/tests/fuzzing/fuzzer-common.h new file mode 100644 index 000000000000..80ebfd28ba76 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/fuzzer-common.h @@ -0,0 +1,14 @@ +/* + * Common helper functions for fuzzing tools + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef FUZZER_COMMON_H +#define FUZZER_COMMON_H + +void wpa_fuzzer_set_debug_level(void); + +#endif /* FUZZER_COMMON_H */ diff --git a/contrib/wpa/tests/fuzzing/json/.gitignore b/contrib/wpa/tests/fuzzing/json/.gitignore new file mode 100644 index 000000000000..3c840093b758 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/json/.gitignore @@ -0,0 +1 @@ +json diff --git a/contrib/wpa/tests/fuzzing/json/Makefile b/contrib/wpa/tests/fuzzing/json/Makefile new file mode 100644 index 000000000000..9dd51a5f22ef --- /dev/null +++ b/contrib/wpa/tests/fuzzing/json/Makefile @@ -0,0 +1,23 @@ +ALL=json +include ../rules.include + +OBJS += $(SRC)/utils/base64.o +OBJS += $(SRC)/utils/common.o +OBJS += $(SRC)/utils/json.o +OBJS += $(SRC)/utils/os_unix.o +OBJS += $(SRC)/utils/wpa_debug.o +OBJS += $(SRC)/utils/wpabuf.o + +OBJS += json.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +json: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + +clean: common-clean + rm -f json *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/json/corpus/1.json b/contrib/wpa/tests/fuzzing/json/corpus/1.json new file mode 100644 index 000000000000..16c8b963cc14 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/json/corpus/1.json @@ -0,0 +1 @@ +{"a":[[]],"b":1,"c":"q","d":{"e":[{}]}} diff --git a/contrib/wpa/tests/fuzzing/json/corpus/2.json b/contrib/wpa/tests/fuzzing/json/corpus/2.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/contrib/wpa/tests/fuzzing/json/corpus/2.json @@ -0,0 +1 @@ +{} diff --git a/contrib/wpa/tests/fuzzing/json/corpus/3.json b/contrib/wpa/tests/fuzzing/json/corpus/3.json new file mode 100644 index 000000000000..573541ac9702 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/json/corpus/3.json @@ -0,0 +1 @@ +0 diff --git a/contrib/wpa/tests/fuzzing/json/json.c b/contrib/wpa/tests/fuzzing/json/json.c new file mode 100644 index 000000000000..af6c5e74cd54 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/json/json.c @@ -0,0 +1,38 @@ +/* + * JSON parser - test program + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/json.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct json_token *root; + char *txt; + size_t buflen = 10000; + + wpa_fuzzer_set_debug_level(); + + root = json_parse((const char *) data, size); + if (!root) { + wpa_printf(MSG_DEBUG, "JSON parsing failed"); + return 0; + } + + txt = os_zalloc(buflen); + if (txt) { + json_print_tree(root, txt, buflen); + wpa_printf(MSG_DEBUG, "%s", txt); + os_free(txt); + } + json_free(root); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/p2p/.gitignore b/contrib/wpa/tests/fuzzing/p2p/.gitignore new file mode 100644 index 000000000000..8bea15da48ef --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/.gitignore @@ -0,0 +1 @@ +p2p diff --git a/contrib/wpa/tests/fuzzing/p2p/Makefile b/contrib/wpa/tests/fuzzing/p2p/Makefile new file mode 100644 index 000000000000..acac9d38f1b1 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/Makefile @@ -0,0 +1,23 @@ +ALL=p2p +include ../rules.include + +LIBS += $(SRC)/utils/libutils.a +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/p2p/libp2p.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/wps/libwps.a + +OBJS += p2p.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +p2p: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: common-clean + rm -f p2p *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/p2p/corpus/go-neg-req.dat b/contrib/wpa/tests/fuzzing/p2p/corpus/go-neg-req.dat Binary files differnew file mode 100644 index 000000000000..ed06834d71a1 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/corpus/go-neg-req.dat diff --git a/contrib/wpa/tests/fuzzing/p2p/corpus/invitation-req.dat b/contrib/wpa/tests/fuzzing/p2p/corpus/invitation-req.dat Binary files differnew file mode 100644 index 000000000000..5991f3e6e3f9 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/corpus/invitation-req.dat diff --git a/contrib/wpa/tests/fuzzing/p2p/corpus/p2ps-pd-req.dat b/contrib/wpa/tests/fuzzing/p2p/corpus/p2ps-pd-req.dat Binary files differnew file mode 100644 index 000000000000..7e1b6d91dead --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/corpus/p2ps-pd-req.dat diff --git a/contrib/wpa/tests/fuzzing/p2p/corpus/proberesp-go.dat b/contrib/wpa/tests/fuzzing/p2p/corpus/proberesp-go.dat Binary files differnew file mode 100644 index 000000000000..8541652ff955 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/corpus/proberesp-go.dat diff --git a/contrib/wpa/tests/fuzzing/p2p/corpus/proberesp.dat b/contrib/wpa/tests/fuzzing/p2p/corpus/proberesp.dat Binary files differnew file mode 100644 index 000000000000..8d997d1c5e13 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/corpus/proberesp.dat diff --git a/contrib/wpa/tests/fuzzing/p2p/p2p.c b/contrib/wpa/tests/fuzzing/p2p/p2p.c new file mode 100644 index 000000000000..fc83c3561c1a --- /dev/null +++ b/contrib/wpa/tests/fuzzing/p2p/p2p.c @@ -0,0 +1,178 @@ +/* + * wpa_supplicant - P2P fuzzer + * Copyright (c) 2015, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "p2p/p2p.h" +#include "../fuzzer-common.h" + + +static void debug_print(void *ctx, int level, const char *msg) +{ + wpa_printf(level, "P2P: %s", msg); +} + + +static void find_stopped(void *ctx) +{ +} + + +static int start_listen(void *ctx, unsigned int freq, + unsigned int duration, + const struct wpabuf *probe_resp_ie) +{ + return 0; +} + + +static void stop_listen(void *ctx) +{ +} + + +static void dev_found(void *ctx, const u8 *addr, + const struct p2p_peer_info *info, + int new_device) +{ +} + + +static void dev_lost(void *ctx, const u8 *dev_addr) +{ +} + + +static int send_action(void *ctx, unsigned int freq, const u8 *dst, + const u8 *src, const u8 *bssid, const u8 *buf, + size_t len, unsigned int wait_time, int *scheduled) +{ + *scheduled = 0; + return 0; +} + + +static void send_action_done(void *ctx) +{ +} + + +static void go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id, + u8 go_intent) +{ +} + + +static struct p2p_data * init_p2p(void) +{ + struct p2p_config p2p; + + os_memset(&p2p, 0, sizeof(p2p)); + p2p.max_peers = 100; + p2p.passphrase_len = 8; + p2p.channels.reg_classes = 1; + p2p.channels.reg_class[0].reg_class = 81; + p2p.channels.reg_class[0].channel[0] = 1; + p2p.channels.reg_class[0].channel[1] = 2; + p2p.channels.reg_class[0].channels = 2; + p2p.debug_print = debug_print; + p2p.find_stopped = find_stopped; + p2p.start_listen = start_listen; + p2p.stop_listen = stop_listen; + p2p.dev_found = dev_found; + p2p.dev_lost = dev_lost; + p2p.send_action = send_action; + p2p.send_action_done = send_action_done; + p2p.go_neg_req_rx = go_neg_req_rx; + + return p2p_init(&p2p); +} + + +struct arg_ctx { + const u8 *data; + size_t data_len; + struct p2p_data *p2p; + int count; +}; + + +static void test_send(void *eloop_data, void *user_ctx) +{ + struct arg_ctx *ctx = eloop_data; + struct os_reltime rx_time; + + wpa_hexdump(MSG_MSGDUMP, "fuzzer - IEs", ctx->data, ctx->data_len); + + os_memset(&rx_time, 0, sizeof(rx_time)); + p2p_scan_res_handler(ctx->p2p, (u8 *) "\x02\x00\x00\x00\x01\x00", 2412, + &rx_time, 0, ctx->data, ctx->data_len); + p2p_scan_res_handled(ctx->p2p, 0); + + p2p_probe_req_rx(ctx->p2p, (u8 *) "\x02\x00\x00\x00\x01\x00", + (u8 *) "\x02\x00\x00\x00\x00\x00", + (u8 *) "\x02\x00\x00\x00\x00\x00", + ctx->data, ctx->data_len, 2412, 0); + + if (ctx->data_len >= IEEE80211_HDRLEN + 1) { + struct os_reltime rx_time; + const struct ieee80211_mgmt *mgmt; + + mgmt = (const struct ieee80211_mgmt *) ctx->data; + os_memset(&rx_time, 0, sizeof(rx_time)); + p2p_rx_action(ctx->p2p, mgmt->da, mgmt->sa, mgmt->bssid, + mgmt->u.action.category, + (const u8 *) ctx->data + IEEE80211_HDRLEN + 1, + ctx->data_len - IEEE80211_HDRLEN - 1, 2412); + } + + eloop_terminate(); +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct p2p_data *p2p; + struct arg_ctx ctx; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return -1; + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + return 0; + } + + p2p = init_p2p(); + if (!p2p) { + wpa_printf(MSG_ERROR, "P2P init failed"); + return 0; + } + + os_memset(&ctx, 0, sizeof(ctx)); + ctx.p2p = p2p; + ctx.data = data; + ctx.data_len = size; + + eloop_register_timeout(0, 0, test_send, &ctx, NULL); + + wpa_printf(MSG_DEBUG, "Starting eloop"); + eloop_run(); + wpa_printf(MSG_DEBUG, "eloop done"); + + p2p_deinit(p2p); + eloop_destroy(); + os_program_deinit(); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/rules.include b/contrib/wpa/tests/fuzzing/rules.include new file mode 100644 index 000000000000..e2cf577af811 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/rules.include @@ -0,0 +1,31 @@ +FUZZ_RULES := $(lastword $(MAKEFILE_LIST)) +include $(dir $(FUZZ_RULES))../../src/build.rules + +FUZZ_CFLAGS = + +ifdef LIBFUZZER +CC ?= clang +#FUZZ_FLAGS ?= -fsanitize=fuzzer,address,signed-integer-overflow,unsigned-integer-overflow +FUZZ_FLAGS ?= -fsanitize=fuzzer,address +ifndef CFLAGS +FUZZ_CFLAGS += $(FUZZ_FLAGS) +endif +endif + +FUZZ_CFLAGS += -DCONFIG_NO_RANDOM_POOL -DTEST_FUZZ +export FUZZ_CFLAGS +CFLAGS ?= -MMD -O2 -Wall -g +CFLAGS += $(FUZZ_CFLAGS) +ifdef LIBFUZZER +CFLAGS += -DTEST_LIBFUZZER +LDFLAGS += $(FUZZ_FLAGS) +endif + +WPAS_SRC=../../../wpa_supplicant +SRC=../../../src + +CFLAGS += -I$(SRC) -I$(SRC)/utils -I$(WPAS_SRC) +OBJS += ../fuzzer-common.o + +# for the lib builds +export TEST_FUZZ=y diff --git a/contrib/wpa/tests/fuzzing/sae/.gitignore b/contrib/wpa/tests/fuzzing/sae/.gitignore new file mode 100644 index 000000000000..1bb959165a21 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/.gitignore @@ -0,0 +1 @@ +sae diff --git a/contrib/wpa/tests/fuzzing/sae/Makefile b/contrib/wpa/tests/fuzzing/sae/Makefile new file mode 100644 index 000000000000..ee4b0c0b6a22 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/Makefile @@ -0,0 +1,28 @@ +ALL=sae +include ../rules.include + +CFLAGS += -DCONFIG_SHA256 +CFLAGS += -DCONFIG_ECC + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += $(SRC)/crypto/crypto_openssl.o +OBJS += $(SRC)/crypto/dh_groups.o +OBJS += $(SRC)/crypto/sha256-prf.o +OBJS += $(SRC)/crypto/sha256-kdf.o +OBJS += $(SRC)/common/dragonfly.o + +OBJS += sae.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +sae: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto + +clean: common-clean + rm -f sae *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat Binary files differnew file mode 100644 index 000000000000..cd129a474a72 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat diff --git a/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat Binary files differnew file mode 100644 index 000000000000..b2886c70d209 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat diff --git a/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat Binary files differnew file mode 100644 index 000000000000..5ca903ed2016 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat diff --git a/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-token.dat b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-token.dat Binary files differnew file mode 100644 index 000000000000..b25cc49f8e10 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-token.dat diff --git a/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-valid.dat b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-valid.dat Binary files differnew file mode 100644 index 000000000000..eadfa4993b89 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/corpus/sae-commit-valid.dat diff --git a/contrib/wpa/tests/fuzzing/sae/sae.c b/contrib/wpa/tests/fuzzing/sae/sae.c new file mode 100644 index 000000000000..8819a4abbc8f --- /dev/null +++ b/contrib/wpa/tests/fuzzing/sae/sae.c @@ -0,0 +1,39 @@ +/* + * SAE fuzzer + * Copyright (c) 2020, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/sae.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct sae_data sae; + u16 res; + const u8 *token = NULL; + size_t token_len = 0; + int groups[] = { 19, 0 }; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + os_memset(&sae, 0, sizeof(sae)); + res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 0); + wpa_printf(MSG_DEBUG, "sae_parse_commit(0): %u", res); + sae_clear_data(&sae); + res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 1); + wpa_printf(MSG_DEBUG, "sae_parse_commit(1): %u", res); + sae_clear_data(&sae); + os_program_deinit(); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/tls-client/.gitignore b/contrib/wpa/tests/fuzzing/tls-client/.gitignore new file mode 100644 index 000000000000..b41f93681f4d --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-client/.gitignore @@ -0,0 +1 @@ +tls-client diff --git a/contrib/wpa/tests/fuzzing/tls-client/Makefile b/contrib/wpa/tests/fuzzing/tls-client/Makefile new file mode 100644 index 000000000000..84cfa0431566 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-client/Makefile @@ -0,0 +1,32 @@ +ALL=tls-client +include ../rules.include + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/rsn_supp/librsn_supp.a +LIBS += $(SRC)/eapol_supp/libeapol_supp.a +LIBS += $(SRC)/eap_peer/libeap_peer.a +LIBS += $(SRC)/eap_common/libeap_common.a +LIBS += $(SRC)/l2_packet/libl2_packet.a +LIBS += $(SRC)/utils/libutils.a + +ELIBS += $(SRC)/crypto/libcrypto.a +ELIBS += $(SRC)/tls/libtls.a + +OBJS += tls-client.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +tls-client: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + +clean: common-clean + rm -f tls-client *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/tls-client/corpus/server.msg b/contrib/wpa/tests/fuzzing/tls-client/corpus/server.msg Binary files differnew file mode 100644 index 000000000000..0f842fdf75e1 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-client/corpus/server.msg diff --git a/contrib/wpa/tests/fuzzing/tls-client/tls-client.c b/contrib/wpa/tests/fuzzing/tls-client/tls-client.c new file mode 100644 index 000000000000..b15b71984883 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-client/tls-client.c @@ -0,0 +1,154 @@ +/* + * Testing tool for TLSv1 client routines + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/tls.h" +#include "../fuzzer-common.h" + +#ifndef CERTDIR +#define CERTDIR "../../hwsim/auth_serv/" +#endif + +struct context { + const u8 *data; + size_t data_len; + size_t data_offset; +}; + + +static struct wpabuf * read_msg(struct context *ctx) +{ + u16 msg_len; + struct wpabuf *msg; + + if (ctx->data_len - ctx->data_offset < 2) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); + return NULL; + } + msg_len = WPA_GET_BE16(&ctx->data[ctx->data_offset]); + ctx->data_offset += 2; + + msg = wpabuf_alloc(msg_len); + if (!msg) + return NULL; + if (msg_len > 0 && ctx->data_len - ctx->data_offset < msg_len) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", + msg_len); + wpabuf_free(msg); + return NULL; + } + wpabuf_put_data(msg, &ctx->data[ctx->data_offset], msg_len); + ctx->data_offset += msg_len; + wpa_hexdump_buf(MSG_DEBUG, "TEST: Read message from file", msg); + + return msg; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct context ctx; + struct tls_config conf; + void *tls_client; + struct tls_connection_params params; + struct tls_connection *conn_client = NULL; + int ret = -1; + struct wpabuf *in = NULL, *out = NULL, *appl; + + wpa_fuzzer_set_debug_level(); + + os_memset(&ctx, 0, sizeof(ctx)); + ctx.data = data; + ctx.data_len = size; + + os_memset(&conf, 0, sizeof(conf)); + tls_client = tls_init(&conf); + if (!tls_client) + goto fail; + + os_memset(¶ms, 0, sizeof(params)); + params.ca_cert = CERTDIR "ca.pem"; + params.client_cert = CERTDIR "server.pem"; + params.private_key = CERTDIR "server.key"; + params.dh_file = CERTDIR "dh.conf"; + + conn_client = tls_connection_init(tls_client); + if (!conn_client) + goto fail; + + in = NULL; + for (;;) { + appl = NULL; + out = tls_connection_handshake(tls_client, conn_client, in, + &appl); + wpabuf_free(in); + in = NULL; + if (!out) + goto fail; + if (tls_connection_get_failed(tls_client, conn_client)) { + wpa_printf(MSG_ERROR, "TLS handshake failed"); + goto fail; + } + if (tls_connection_established(tls_client, conn_client)) + break; + + appl = NULL; + in = read_msg(&ctx); + wpabuf_free(out); + out = NULL; + if (!in) + goto fail; + if (tls_connection_established(tls_client, conn_client)) + break; + } + + wpabuf_free(in); + in = wpabuf_alloc(100); + if (!in) + goto fail; + wpabuf_put_str(in, "PING"); + wpabuf_free(out); + out = tls_connection_encrypt(tls_client, conn_client, in); + wpabuf_free(in); + in = NULL; + if (!out) + goto fail; + + wpabuf_free(in); + in = wpabuf_alloc(100); + if (!in) + goto fail; + wpabuf_put_str(in, "PONG"); + wpabuf_free(out); + out = read_msg(&ctx); + wpabuf_free(in); + in = NULL; + if (!out) + goto fail; + + in = tls_connection_decrypt(tls_client, conn_client, out); + wpabuf_free(out); + out = NULL; + if (!in) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "Client decrypted ApplData", in); + + ret = 0; +fail: + if (tls_client) { + if (conn_client) + tls_connection_deinit(tls_client, conn_client); + tls_deinit(tls_client); + } + wpabuf_free(in); + wpabuf_free(out); + + return ret; +} diff --git a/contrib/wpa/tests/fuzzing/tls-server/.gitignore b/contrib/wpa/tests/fuzzing/tls-server/.gitignore new file mode 100644 index 000000000000..341256f57f3f --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-server/.gitignore @@ -0,0 +1 @@ +tls-server diff --git a/contrib/wpa/tests/fuzzing/tls-server/Makefile b/contrib/wpa/tests/fuzzing/tls-server/Makefile new file mode 100644 index 000000000000..8e2400310397 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-server/Makefile @@ -0,0 +1,32 @@ +ALL=tls-server +include ../rules.include + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/rsn_supp/librsn_supp.a +LIBS += $(SRC)/eapol_supp/libeapol_supp.a +LIBS += $(SRC)/eap_peer/libeap_peer.a +LIBS += $(SRC)/eap_common/libeap_common.a +LIBS += $(SRC)/l2_packet/libl2_packet.a +LIBS += $(SRC)/utils/libutils.a + +ELIBS += $(SRC)/crypto/libcrypto.a +ELIBS += $(SRC)/tls/libtls.a + +OBJS += tls-server.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +tls-server: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + +clean: common-clean + rm -f tls-server *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/tls-server/corpus/client.msg b/contrib/wpa/tests/fuzzing/tls-server/corpus/client.msg Binary files differnew file mode 100644 index 000000000000..cb390143b0ea --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-server/corpus/client.msg diff --git a/contrib/wpa/tests/fuzzing/tls-server/tls-server.c b/contrib/wpa/tests/fuzzing/tls-server/tls-server.c new file mode 100644 index 000000000000..d64cd7ad9756 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/tls-server/tls-server.c @@ -0,0 +1,157 @@ +/* + * Testing tool for TLSv1 server routines + * Copyright (c) 2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/tls.h" +#include "../fuzzer-common.h" + +#ifndef CERTDIR +#define CERTDIR "../../hwsim/auth_serv/" +#endif + +struct context { + const u8 *data; + size_t data_len; + size_t data_offset; +}; + + +static struct wpabuf * read_msg(struct context *ctx) +{ + u16 msg_len; + struct wpabuf *msg; + + if (ctx->data_len - ctx->data_offset < 2) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); + return NULL; + } + msg_len = WPA_GET_BE16(&ctx->data[ctx->data_offset]); + ctx->data_offset += 2; + + msg = wpabuf_alloc(msg_len); + if (!msg) + return NULL; + if (msg_len > 0 && ctx->data_len - ctx->data_offset < msg_len) { + wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", + msg_len); + wpabuf_free(msg); + return NULL; + } + wpabuf_put_data(msg, &ctx->data[ctx->data_offset], msg_len); + ctx->data_offset += msg_len; + wpa_hexdump_buf(MSG_DEBUG, "TEST: Read message from file", msg); + + return msg; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct context ctx; + struct tls_config conf; + void *tls_server; + struct tls_connection_params params; + struct tls_connection *conn_server = NULL; + int ret = -1; + struct wpabuf *in = NULL, *out = NULL, *appl; + + wpa_fuzzer_set_debug_level(); + + os_memset(&ctx, 0, sizeof(ctx)); + ctx.data = data; + ctx.data_len = size; + + os_memset(&conf, 0, sizeof(conf)); + tls_server = tls_init(&conf); + if (!tls_server) + goto fail; + + os_memset(¶ms, 0, sizeof(params)); + params.ca_cert = CERTDIR "ca.pem"; + params.client_cert = CERTDIR "server.pem"; + params.private_key = CERTDIR "server.key"; + params.dh_file = CERTDIR "dh.conf"; + + if (tls_global_set_params(tls_server, ¶ms)) { + wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); + goto fail; + } + + conn_server = tls_connection_init(tls_server); + if (!conn_server) + goto fail; + + in = NULL; + for (;;) { + appl = NULL; + out = read_msg(&ctx); + wpabuf_free(in); + in = NULL; + if (!out) + goto fail; + + appl = NULL; + in = tls_connection_server_handshake(tls_server, conn_server, + out, &appl); + wpabuf_free(out); + out = NULL; + if (!in) + goto fail; + if (tls_connection_get_failed(tls_server, conn_server)) { + wpa_printf(MSG_ERROR, "TLS handshake failed"); + goto fail; + } + if (tls_connection_established(tls_server, conn_server)) + break; + } + + wpabuf_free(in); + in = wpabuf_alloc(100); + if (!in) + goto fail; + wpabuf_put_str(in, "PING"); + wpabuf_free(out); + out = read_msg(&ctx); + wpabuf_free(in); + in = NULL; + if (!out) + goto fail; + + in = tls_connection_decrypt(tls_server, conn_server, out); + wpabuf_free(out); + out = NULL; + if (!in) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "Server decrypted ApplData", in); + + wpabuf_free(in); + in = wpabuf_alloc(100); + if (!in) + goto fail; + wpabuf_put_str(in, "PONG"); + wpabuf_free(out); + out = tls_connection_encrypt(tls_server, conn_server, in); + wpabuf_free(in); + in = NULL; + if (!out) + goto fail; + + ret = 0; +fail: + if (tls_server) { + if (conn_server) + tls_connection_deinit(tls_server, conn_server); + tls_deinit(tls_server); + } + wpabuf_free(in); + wpabuf_free(out); + + return ret; +} diff --git a/contrib/wpa/tests/fuzzing/wnm/.gitignore b/contrib/wpa/tests/fuzzing/wnm/.gitignore new file mode 100644 index 000000000000..0e1d383dc444 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/wnm/.gitignore @@ -0,0 +1 @@ +wnm diff --git a/contrib/wpa/tests/fuzzing/wnm/Makefile b/contrib/wpa/tests/fuzzing/wnm/Makefile new file mode 100644 index 000000000000..60d27b3a1535 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/wnm/Makefile @@ -0,0 +1,60 @@ +ALL=wnm +include ../rules.include + +CFLAGS += -DCONFIG_WNM +CFLAGS += -DCONFIG_INTERWORKING +CFLAGS += -DCONFIG_GAS +CFLAGS += -DCONFIG_HS20 +CFLAGS += -DIEEE8021X_EAPOL + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/rsn_supp/librsn_supp.a +LIBS += $(SRC)/eapol_supp/libeapol_supp.a +LIBS += $(SRC)/eap_peer/libeap_peer.a +LIBS += $(SRC)/eap_common/libeap_common.a +LIBS += $(SRC)/l2_packet/libl2_packet.a +LIBS += $(SRC)/utils/libutils.a + +ELIBS += $(SRC)/crypto/libcrypto.a +ELIBS += $(SRC)/tls/libtls.a + +OBJS += $(WPAS_SRC)/bssid_ignore.o +OBJS += $(WPAS_SRC)/bss.o +OBJS += $(WPAS_SRC)/config.o +OBJS += $(WPAS_SRC)/config_file.o +OBJS += $(WPAS_SRC)/eap_register.o +OBJS += $(WPAS_SRC)/events.o +OBJS += $(WPAS_SRC)/gas_query.o +OBJS += $(WPAS_SRC)/hs20_supplicant.o +OBJS += $(WPAS_SRC)/interworking.o +OBJS += $(WPAS_SRC)/notify.o +OBJS += $(WPAS_SRC)/offchannel.o +OBJS += $(WPAS_SRC)/op_classes.o +OBJS += $(WPAS_SRC)/robust_av.o +OBJS += $(WPAS_SRC)/rrm.o +OBJS += $(WPAS_SRC)/scan.o +OBJS += $(WPAS_SRC)/wmm_ac.o +OBJS += $(WPAS_SRC)/wnm_sta.o +OBJS += $(WPAS_SRC)/wpa_supplicant.o +OBJS += $(WPAS_SRC)/wpas_glue.o +OBJS += $(SRC)/drivers/driver_common.o +OBJS += $(SRC)/drivers/drivers.o + +OBJS += wnm.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +wnm: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + +clean: common-clean + rm -f wnm *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/wnm/corpus/bss-tm-req.dat b/contrib/wpa/tests/fuzzing/wnm/corpus/bss-tm-req.dat Binary files differnew file mode 100644 index 000000000000..14510bb3ad11 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/wnm/corpus/bss-tm-req.dat diff --git a/contrib/wpa/tests/fuzzing/wnm/corpus/oss-fuzz-0001.dat b/contrib/wpa/tests/fuzzing/wnm/corpus/oss-fuzz-0001.dat Binary files differnew file mode 100644 index 000000000000..53fdf659c438 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/wnm/corpus/oss-fuzz-0001.dat diff --git a/contrib/wpa/tests/fuzzing/wnm/corpus/oss-fuzz-0002.dat b/contrib/wpa/tests/fuzzing/wnm/corpus/oss-fuzz-0002.dat Binary files differnew file mode 100644 index 000000000000..cb700936fad5 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/wnm/corpus/oss-fuzz-0002.dat diff --git a/contrib/wpa/tests/fuzzing/wnm/corpus/wnm-notif.dat b/contrib/wpa/tests/fuzzing/wnm/corpus/wnm-notif.dat Binary files differnew file mode 100644 index 000000000000..c234d3ad5b69 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/wnm/corpus/wnm-notif.dat diff --git a/contrib/wpa/tests/fuzzing/wnm/wnm.c b/contrib/wpa/tests/fuzzing/wnm/wnm.c new file mode 100644 index 000000000000..7afc648e442a --- /dev/null +++ b/contrib/wpa/tests/fuzzing/wnm/wnm.c @@ -0,0 +1,99 @@ +/* + * wpa_supplicant - WNM fuzzer + * Copyright (c) 2015-2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "rsn_supp/wpa.h" +#include "rsn_supp/wpa_i.h" +#include "wpa_supplicant_i.h" +#include "bss.h" +#include "wnm_sta.h" +#include "../../../wpa_supplicant/config.h" +#include "../fuzzer-common.h" + + +struct arg_ctx { + const u8 *data; + size_t data_len; + struct wpa_supplicant wpa_s; + struct wpa_bss bss; + struct wpa_driver_ops driver; + struct wpa_sm wpa; + struct wpa_config conf; +}; + + +static void test_send_wnm(void *eloop_data, void *user_ctx) +{ + struct arg_ctx *ctx = eloop_data; + const struct ieee80211_mgmt *mgmt; + + wpa_hexdump(MSG_MSGDUMP, "fuzzer - WNM", ctx->data, ctx->data_len); + + mgmt = (const struct ieee80211_mgmt *) ctx->data; + ieee802_11_rx_wnm_action(&ctx->wpa_s, mgmt, ctx->data_len); + + eloop_terminate(); +} + + +static int init_wpa(struct arg_ctx *ctx) +{ + ctx->wpa_s.wpa_state = WPA_COMPLETED; + os_memcpy(ctx->wpa_s.bssid, "\x02\x00\x00\x00\x03\x00", ETH_ALEN); + ctx->wpa_s.current_bss = &ctx->bss; + ctx->wpa_s.driver = &ctx->driver; + ctx->wpa_s.wpa = &ctx->wpa; + ctx->wpa_s.conf = &ctx->conf; + + return 0; +} + + +static void deinit_wpa(struct arg_ctx *ctx) +{ + wnm_deallocate_memory(&ctx->wpa_s); +} + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct arg_ctx ctx; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + if (eloop_init()) { + wpa_printf(MSG_ERROR, "Failed to initialize event loop"); + return 0; + } + + os_memset(&ctx, 0, sizeof(ctx)); + ctx.data = data; + ctx.data_len = size; + if (init_wpa(&ctx)) + goto fail; + + eloop_register_timeout(0, 0, test_send_wnm, &ctx, NULL); + + wpa_printf(MSG_DEBUG, "Starting eloop"); + eloop_run(); + wpa_printf(MSG_DEBUG, "eloop done"); + deinit_wpa(&ctx); + +fail: + eloop_destroy(); + os_program_deinit(); + + return 0; +} diff --git a/contrib/wpa/tests/fuzzing/x509/.gitignore b/contrib/wpa/tests/fuzzing/x509/.gitignore new file mode 100644 index 000000000000..490a5d71f3f2 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/x509/.gitignore @@ -0,0 +1 @@ +x509 diff --git a/contrib/wpa/tests/fuzzing/x509/Makefile b/contrib/wpa/tests/fuzzing/x509/Makefile new file mode 100644 index 000000000000..306473c3dba3 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/x509/Makefile @@ -0,0 +1,27 @@ +ALL=x509 +include ../rules.include + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/crypto/libcrypto.a +LIBS += $(SRC)/tls/libtls.a +LIBS += $(SRC)/utils/libutils.a + +ELIBS += $(SRC)/crypto/libcrypto.a +ELIBS += $(SRC)/tls/libtls.a + +OBJS += x509.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +x509: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) + +clean: common-clean + rm -f x509 *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/contrib/wpa/tests/fuzzing/x509/corpus/ca.der b/contrib/wpa/tests/fuzzing/x509/corpus/ca.der Binary files differnew file mode 100644 index 000000000000..09d5fa051bf3 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/x509/corpus/ca.der diff --git a/contrib/wpa/tests/fuzzing/x509/corpus/oss-fuzz-15408 b/contrib/wpa/tests/fuzzing/x509/corpus/oss-fuzz-15408 new file mode 100644 index 000000000000..a6f74c54623f --- /dev/null +++ b/contrib/wpa/tests/fuzzing/x509/corpus/oss-fuzz-15408 @@ -0,0 +1 @@ +00 0
0/10 1 0 0
3 6 91 1 2Z
3 6 7 6 1 2Z0/10 1 0 00
P0N0 0 0U0!
\ No newline at end of file diff --git a/contrib/wpa/tests/fuzzing/x509/x509.c b/contrib/wpa/tests/fuzzing/x509/x509.c new file mode 100644 index 000000000000..2969fea3e287 --- /dev/null +++ b/contrib/wpa/tests/fuzzing/x509/x509.c @@ -0,0 +1,25 @@ +/* + * Testing tool for X.509v3 routines + * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "tls/x509v3.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct x509_certificate *cert; + + wpa_fuzzer_set_debug_level(); + + cert = x509_certificate_parse(data, size); + x509_certificate_free(cert); + return 0; +} |