diff --git a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 index 5df2d65f0e8..858cc69588f 100644 --- a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 +++ b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 @@ -1 +1 @@ -b3fb4157d7fc6cd3455f40020bb6b69e5bab4bbdb6ce66d5bc7095146ba5a49e /usr/local/bin/tox-bootstrapd +42f29a351f27d994d14bab0e6288fcb839220af9878ce37a49fbd120b07d16dc /usr/local/bin/tox-bootstrapd diff --git a/testing/fuzzing/BUILD.bazel b/testing/fuzzing/BUILD.bazel index 87cd5725ebe..1135a72c5c0 100644 --- a/testing/fuzzing/BUILD.bazel +++ b/testing/fuzzing/BUILD.bazel @@ -1,19 +1,18 @@ load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") -cc_library( - name = "fuzz_adapter", - srcs = ["fuzz_adapter.c"], - hdrs = ["fuzz_adapter.h"], - visibility = ["//c-toxcore:__subpackages__"], -) +package(features = ["layering_check"]) cc_library( name = "fuzz_support", srcs = ["fuzz_support.cc"], hdrs = ["fuzz_support.h"], visibility = ["//c-toxcore:__subpackages__"], - deps = ["//c-toxcore/toxcore:tox"], + deps = [ + "//c-toxcore/toxcore:crypto_core", + "//c-toxcore/toxcore:network", + "//c-toxcore/toxcore:tox", + ], ) cc_library( @@ -31,6 +30,9 @@ cc_fuzz_test( deps = [ ":fuzz_support", "//c-toxcore/toxcore:tox", + "//c-toxcore/toxcore:tox_dispatch", + "//c-toxcore/toxcore:tox_events", + "//c-toxcore/toxcore:util", ], ) diff --git a/testing/fuzzing/CMakeLists.txt b/testing/fuzzing/CMakeLists.txt index 588c130144f..5c00c764ec0 100644 --- a/testing/fuzzing/CMakeLists.txt +++ b/testing/fuzzing/CMakeLists.txt @@ -2,7 +2,7 @@ target_compile_definitions(toxcore_static PUBLIC "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION") # Override network and random functions -add_library(fuzz_adapter fuzz_adapter.c fuzz_support.cc fuzz_support.h) +add_library(fuzz_support fuzz_support.cc fuzz_support.h) set(LIBFUZZER_LINKER_FLAGS) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") @@ -13,14 +13,14 @@ endif() # Fuzzes the toxsave API add_executable(toxsave_fuzzer toxsave_harness.cc) -target_link_libraries(toxsave_fuzzer toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(toxsave_fuzzer toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) # Fuzzes the bootstrap process add_executable(bootstrap_fuzzer bootstrap_harness.cc) -target_link_libraries(bootstrap_fuzzer toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(bootstrap_fuzzer toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) add_executable(DHT_fuzz_test ../../toxcore/DHT_fuzz_test.cc) -target_link_libraries(DHT_fuzz_test toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(DHT_fuzz_test toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) add_executable(tox_events_fuzz_test ../../toxcore/tox_events_fuzz_test.cc) -target_link_libraries(tox_events_fuzz_test toxcore_static fuzz_adapter ${LIBFUZZER_LINKER_FLAGS}) +target_link_libraries(tox_events_fuzz_test toxcore_static fuzz_support ${LIBFUZZER_LINKER_FLAGS}) diff --git a/testing/fuzzing/bootstrap_harness.cc b/testing/fuzzing/bootstrap_harness.cc index 49869e2955d..6d897f3a5d0 100644 --- a/testing/fuzzing/bootstrap_harness.cc +++ b/testing/fuzzing/bootstrap_harness.cc @@ -3,23 +3,124 @@ #include #include "../../toxcore/tox.h" +#include "../../toxcore/tox_dispatch.h" +#include "../../toxcore/tox_events.h" #include "../../toxcore/tox_private.h" -#include "fuzz_adapter.h" +#include "../../toxcore/tox_struct.h" +#include "../../toxcore/util.h" #include "fuzz_support.h" +namespace { + +void setup_callbacks(Tox_Dispatch *dispatch) +{ + tox_events_callback_conference_connected( + dispatch, [](Tox *tox, const Tox_Event_Conference_Connected *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_connected( + dispatch, [](Tox *tox, const Tox_Event_Conference_Connected *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_invite( + dispatch, [](Tox *tox, const Tox_Event_Conference_Invite *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_message( + dispatch, [](Tox *tox, const Tox_Event_Conference_Message *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_peer_list_changed(dispatch, + [](Tox *tox, const Tox_Event_Conference_Peer_List_Changed *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_peer_name( + dispatch, [](Tox *tox, const Tox_Event_Conference_Peer_Name *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_conference_title( + dispatch, [](Tox *tox, const Tox_Event_Conference_Title *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_chunk_request( + dispatch, [](Tox *tox, const Tox_Event_File_Chunk_Request *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_recv( + dispatch, [](Tox *tox, const Tox_Event_File_Recv *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_recv_chunk( + dispatch, [](Tox *tox, const Tox_Event_File_Recv_Chunk *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_file_recv_control( + dispatch, [](Tox *tox, const Tox_Event_File_Recv_Control *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_connection_status( + dispatch, [](Tox *tox, const Tox_Event_Friend_Connection_Status *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_lossless_packet( + dispatch, [](Tox *tox, const Tox_Event_Friend_Lossless_Packet *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_lossy_packet( + dispatch, [](Tox *tox, const Tox_Event_Friend_Lossy_Packet *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_message( + dispatch, [](Tox *tox, const Tox_Event_Friend_Message *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_name( + dispatch, [](Tox *tox, const Tox_Event_Friend_Name *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_read_receipt( + dispatch, [](Tox *tox, const Tox_Event_Friend_Read_Receipt *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_request( + dispatch, [](Tox *tox, const Tox_Event_Friend_Request *event, void *user_data) { + Tox_Err_Friend_Add err; + tox_friend_add_norequest(tox, tox_event_friend_request_get_public_key(event), &err); + assert(err == TOX_ERR_FRIEND_ADD_OK || err == TOX_ERR_FRIEND_ADD_OWN_KEY + || err == TOX_ERR_FRIEND_ADD_ALREADY_SENT + || err == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM); + }); + tox_events_callback_friend_status( + dispatch, [](Tox *tox, const Tox_Event_Friend_Status *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_status_message( + dispatch, [](Tox *tox, const Tox_Event_Friend_Status_Message *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_friend_typing( + dispatch, [](Tox *tox, const Tox_Event_Friend_Typing *event, void *user_data) { + assert(event == nullptr); + }); + tox_events_callback_self_connection_status( + dispatch, [](Tox *tox, const Tox_Event_Self_Connection_Status *event, void *user_data) { + assert(event == nullptr); + }); +} + +} + extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - network_adapter_init(data, size); + Fuzz_Data input{data, size}; - uint64_t clock = 0; - auto sys = fuzz_system(clock); - assert(sys->mono_time_callback != nullptr); - assert(sys->mono_time_user_data != nullptr); + Fuzz_System sys(input); + assert(sys.rng != nullptr); Tox_Options *opts = tox_options_new(nullptr); assert(opts != nullptr); - tox_options_set_operating_system(opts, sys.get()); + tox_options_set_operating_system(opts, sys.sys.get()); Tox_Err_New error_new; Tox *tox = tox_new(opts, &error_new); @@ -34,19 +135,25 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) const bool success = tox_bootstrap(tox, "127.0.0.1", 12345, pub_key, nullptr); assert(success); - /* - * The iteration count here is a magic value in the literal sense, too small - * and coverage will be bad, too big and fuzzing will not be efficient. - * NOTE: This should be fine tuned after gathering some experience. - */ - - for (uint32_t i = 0; i < 50; ++i) { - tox_iterate(tox, nullptr); - // Move the clock forward a decent amount so all the time-based checks - // trigger more quickly. - clock += 200; + tox_events_init(tox); + + Tox_Dispatch *dispatch = tox_dispatch_new(nullptr); + assert(dispatch != nullptr); + setup_callbacks(dispatch); + + while (input.size > 0) { + Tox_Err_Events_Iterate error_iterate; + Tox_Events *events = tox_events_iterate(tox, true, &error_iterate); + assert(tox_events_equal(events, events)); + tox_dispatch_invoke(dispatch, events, tox, nullptr); + tox_events_free(events); + // Move the clock forward a random amount so all the time-based checks + // trigger more quickly. Move by at least 20ms (iteration interval) so + // at least something happens. + sys.clock += max_u16(20, random_u08(sys.rng.get())); } + tox_dispatch_free(dispatch); tox_kill(tox); return 0; // Non-zero return values are reserved for future use. } diff --git a/testing/fuzzing/fuzz_adapter.c b/testing/fuzzing/fuzz_adapter.c deleted file mode 100644 index 82fd64534c7..00000000000 --- a/testing/fuzzing/fuzz_adapter.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "fuzz_adapter.h" - -struct fuzz_buf { - /* Fuzz data buffer */ - const uint8_t *cur; - const uint8_t *end; -}; - -static struct fuzz_buf data; - -#include -#include -#include - - -void network_adapter_init(const uint8_t *buf, size_t length) -{ - data.cur = buf; - data.end = buf + length; -} - -ssize_t fuzz_sendto(int sockfd, const void *buf, size_t len, - int flags, const struct sockaddr *addr, - socklen_t addrlen) -{ - return len; -} - -ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags) -{ - return len; -} - -static ssize_t recv_common(void *buf, size_t buf_len) -{ - if (data.cur + 2 >= data.end) { - return -1; - } - - uint16_t fuzz_len = (data.cur[0] << 8) | data.cur[1]; - data.cur += 2; - - size_t available = data.end - data.cur; - - size_t res = fuzz_len > available ? available : fuzz_len; - res = buf_len > res ? res : buf_len; - - memcpy(buf, data.cur, res); - data.cur += res; - - return res; -} - -ssize_t fuzz_recvfrom(int sockfd, void *buf, size_t len, - int flags, struct sockaddr *src_addr, - socklen_t *addr_len) -{ - if (src_addr && addr_len && (sizeof(struct sockaddr) <= *addr_len)) { - *src_addr = (struct sockaddr) { - 0 - }; - // Dummy Addr - src_addr->sa_family = AF_INET; - - // We want an AF_INET address with dummy values - struct sockaddr_in *addr_in = (struct sockaddr_in *)(void *)src_addr; - addr_in->sin_port = 12356; - addr_in->sin_addr.s_addr = INADDR_LOOPBACK + 1; - *addr_len = sizeof(struct sockaddr); - } - - return recv_common(buf, len); -} - -ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags) -{ - return recv_common(buf, len); -} - -void fuzz_random_bytes(uint8_t *rnd, size_t length) -{ - // Amount of data is limited - size_t available = data.end - data.cur; - size_t bytes_read = length > available ? available : length; - // Initialize everything to make MSAN and others happy - memset(rnd, 0, length); - memcpy(rnd, data.cur, bytes_read); - data.cur += bytes_read; -} diff --git a/testing/fuzzing/fuzz_adapter.h b/testing/fuzzing/fuzz_adapter.h deleted file mode 100644 index 91fdbc7680e..00000000000 --- a/testing/fuzzing/fuzz_adapter.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2021 The TokTok team. - */ - -#ifndef C_TOXCORE_TESTING_FUZZING_FUZZ_ADAPTER_H -#define C_TOXCORE_TESTING_FUZZING_FUZZ_ADAPTER_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Init function for the fuzzing harness - * @param buf Begin of fuzz data - * @param length Length of buf - */ -void network_adapter_init(const uint8_t *buf, size_t length); - -/* The following functions intercept calls to standard network functions for fuzzing purposes and return data from the fuzz buffer. */ - -ssize_t fuzz_sendto(int sockfd, const void *buf, size_t len, - int flags, const struct sockaddr *addr, - socklen_t addrlen); - -ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags); - -ssize_t fuzz_recvfrom(int sockfd, void *buf, size_t len, - int flags, struct sockaddr *src_addr, - socklen_t *addr_len); - -ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags); - -/* The following functions intercept generation of random data */ -void fuzz_random_bytes(uint8_t *rnd, size_t length); - -#ifdef __cplusplus -} -#endif - -#endif // C_TOXCORE_TESTING_FUZZING_FUZZ_ADAPTER_H diff --git a/testing/fuzzing/fuzz_support.cc b/testing/fuzzing/fuzz_support.cc index b3e8ed3227e..761951a2799 100644 --- a/testing/fuzzing/fuzz_support.cc +++ b/testing/fuzzing/fuzz_support.cc @@ -4,18 +4,130 @@ #include "fuzz_support.h" +#include +#include + +#include #include #include "../../toxcore/crypto_core.h" #include "../../toxcore/network.h" #include "../../toxcore/tox_private.h" -std::unique_ptr fuzz_system(uint64_t &clock) +// TODO(iphydf): Put this somewhere shared. +struct Network_Addr { + struct sockaddr_storage addr; + size_t size; +}; + +static int recv_common(Fuzz_Data &input, void *buf, size_t buf_len) { - auto sys = std::make_unique(); - sys->mono_time_callback = [](void *user_data) { return *static_cast(user_data); }; - sys->mono_time_user_data = &clock; - sys->rng = system_random(); // TODO(iphydf): Put fuzz_random here. - sys->ns = system_network(); // TODO(iphydf): Put fuzz_network here. - return sys; + if (input.size < 2) { + return -1; + } + + uint16_t fuzz_len = (input.data[0] << 8) | input.data[1]; + input.data += 2; + input.size -= 2; + + size_t available = input.size; + + size_t res = fuzz_len > available ? available : fuzz_len; + res = buf_len > res ? res : buf_len; + + memcpy(buf, input.data, res); + input.data += res; + input.size -= res; + + return res; } + +static const Network_Funcs fuzz_network_funcs = { + .close = [](void *obj, int sock) { return 0; }, + .accept = [](void *obj, int sock) { return 2; }, + .bind = [](void *obj, int sock, const Network_Addr *addr) { return 0; }, + .listen = [](void *obj, int sock, int backlog) { return 0; }, + .recvbuf = + [](void *obj, int sock) { + // TODO(iphydf): Return something sensible here (from the fuzzer): number of + // bytes to be read from the socket. + return 0; + }, + .recv = + [](void *obj, int sock, uint8_t *buf, size_t len) { + // Receive data from the fuzzer. + return recv_common(static_cast(obj)->data, buf, len); + }, + .recvfrom = + [](void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) { + addr->addr = sockaddr_storage{}; + // Dummy Addr + addr->addr.ss_family = AF_INET; + + // We want an AF_INET address with dummy values + sockaddr_in *addr_in = reinterpret_cast(&addr->addr); + addr_in->sin_port = 12356; + addr_in->sin_addr.s_addr = INADDR_LOOPBACK + 1; + addr->size = sizeof(struct sockaddr); + + return recv_common(static_cast(obj)->data, buf, len); + }, + .send = + [](void *obj, int sock, const uint8_t *buf, size_t len) { + // Always succeed. + return static_cast(len); + }, + .sendto = + [](void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) { + // Always succeed. + return static_cast(len); + }, + .socket = [](void *obj, int domain, int type, int proto) { return 1; }, + .socket_nonblock = [](void *obj, int sock, bool nonblock) { return 0; }, + .getsockopt = + [](void *obj, int sock, int level, int optname, void *optval, size_t *optlen) { + memset(optval, 0, *optlen); + return 0; + }, + .setsockopt = [](void *obj, int sock, int level, int optname, const void *optval, + size_t optlen) { return 0; }, +}; + +static const Random_Funcs fuzz_random_funcs = { + .random_bytes = + [](void *obj, uint8_t *bytes, size_t length) { + Fuzz_System *sys = static_cast(obj); + // Amount of data is limited + size_t available = sys->data.size; + size_t bytes_read = length > available ? available : length; + // Initialize everything to make MSAN and others happy + std::memset(bytes, 0, length); + std::memcpy(bytes, sys->data.data, bytes_read); + sys->data.data += bytes_read; + sys->data.size -= bytes_read; + }, + .random_uniform = + [](void *obj, uint32_t upper_bound) { + Fuzz_System *sys = static_cast(obj); + uint32_t randnum; + sys->rng->funcs->random_bytes( + sys, reinterpret_cast(&randnum), sizeof(randnum)); + return randnum % upper_bound; + }, +}; + +Fuzz_System::Fuzz_System(Fuzz_Data &input) + : clock(0) + , data(input) + , sys(std::make_unique()) + , ns(std::make_unique(Network{&fuzz_network_funcs, this})) + , rng(std::make_unique(Random{&fuzz_random_funcs, this})) +{ + sys->mono_time_callback + = [](void *user_data) { return static_cast(user_data)->clock; }; + sys->mono_time_user_data = this; + sys->ns = ns.get(); + sys->rng = rng.get(); +} + +Fuzz_System::~Fuzz_System() { } diff --git a/testing/fuzzing/fuzz_support.h b/testing/fuzzing/fuzz_support.h index a8a1d8dab75..b25a8076a16 100644 --- a/testing/fuzzing/fuzz_support.h +++ b/testing/fuzzing/fuzz_support.h @@ -97,6 +97,18 @@ void fuzz_select_target(const uint8_t *data, std::size_t size, Args &&... args) return fuzz_select_target(selector, input, std::forward(args)...); } -std::unique_ptr fuzz_system(uint64_t &clock); +struct Network; +struct Random; + +struct Fuzz_System { + uint64_t clock; + Fuzz_Data &data; + std::unique_ptr sys; + std::unique_ptr ns; + std::unique_ptr rng; + + Fuzz_System(Fuzz_Data &input); + ~Fuzz_System(); +}; #endif // C_TOXCORE_TESTING_FUZZING_FUZZ_SUPPORT_H diff --git a/testing/fuzzing/toxsave_harness.cc b/testing/fuzzing/toxsave_harness.cc index 068c9d9a97c..4020a0b5405 100644 --- a/testing/fuzzing/toxsave_harness.cc +++ b/testing/fuzzing/toxsave_harness.cc @@ -16,9 +16,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) assert(tox_options != nullptr); assert(error_options == TOX_ERR_OPTIONS_NEW_OK); - uint64_t clock = 0; - auto sys = fuzz_system(clock); - tox_options_set_operating_system(tox_options, sys.get()); + Fuzz_Data input{data + size, 0}; // empty data, since we use it all for savedata. + Fuzz_System sys(input); + tox_options_set_operating_system(tox_options, sys.sys.get()); // pass test data to Tox tox_options_set_savedata_data(tox_options, data, size); diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index c852eb0580d..de7229b708e 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -64,7 +64,6 @@ cc_library( visibility = ["//c-toxcore:__subpackages__"], deps = [ ":ccompat", - "//c-toxcore/testing/fuzzing:fuzz_adapter", "@libsodium", ], ) @@ -136,7 +135,6 @@ cc_library( ], deps = [ ":ccompat", - "//c-toxcore/testing/fuzzing:fuzz_adapter", "@pthread", ], ) @@ -160,6 +158,7 @@ cc_library( "//c-toxcore/auto_tests:__pkg__", "//c-toxcore/other:__pkg__", "//c-toxcore/other/bootstrap_daemon:__pkg__", + "//c-toxcore/testing/fuzzing:__pkg__", "//c-toxcore/toxav:__pkg__", ], deps = [ @@ -178,6 +177,7 @@ cc_library( "//c-toxcore/auto_tests:__pkg__", "//c-toxcore/other:__pkg__", "//c-toxcore/other/bootstrap_daemon:__pkg__", + "//c-toxcore/testing/fuzzing:__pkg__", "//c-toxcore/toxav:__pkg__", ], deps = [ @@ -186,7 +186,6 @@ cc_library( ":logger", ":mono_time", ":util", - "//c-toxcore/testing/fuzzing:fuzz_adapter", "@libsodium", "@psocket", "@pthread", diff --git a/toxcore/ccompat.c b/toxcore/ccompat.c index 30e689d06dd..30e90b99356 100644 --- a/toxcore/ccompat.c +++ b/toxcore/ccompat.c @@ -2,3 +2,5 @@ * Copyright © 2022 The TokTok team. */ #include "ccompat.h" + +const bool tox_is_fuzzing = TOX_IS_FUZZING; diff --git a/toxcore/ccompat.h b/toxcore/ccompat.h index 8cd2844c35f..11dd413c292 100644 --- a/toxcore/ccompat.h +++ b/toxcore/ccompat.h @@ -8,11 +8,26 @@ #ifndef C_TOXCORE_TOXCORE_CCOMPAT_H #define C_TOXCORE_TOXCORE_CCOMPAT_H +#include // bool, false, true #include // NULL, size_t #include "attributes.h" -/* No declarations here. */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#define TOX_IS_FUZZING true +#else +#define TOX_IS_FUZZING false +#endif + +extern const bool tox_is_fuzzing; + +#ifdef __cplusplus +} // extern "C" +#endif //!TOKSTYLE- diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 5b360bdc45e..b65b7607e50 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -40,12 +40,6 @@ #define ENC_SECRET_KEY_SIZE CRYPTO_SECRET_KEY_SIZE #endif -//!TOKSTYLE- -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -#include "../testing/fuzzing/fuzz_adapter.h" -#endif -//!TOKSTYLE+ - static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES, "CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES"); static_assert(CRYPTO_SECRET_KEY_SIZE == crypto_box_SECRETKEYBYTES, @@ -122,38 +116,38 @@ static void crypto_free(uint8_t *ptr, size_t bytes) void crypto_memzero(void *data, size_t length) { -#ifndef VANILLA_NACL - sodium_memzero(data, length); -#else +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) memset(data, 0, length); +#else + sodium_memzero(data, length); #endif } bool crypto_memlock(void *data, size_t length) { -#ifndef VANILLA_NACL +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) + return false; +#else if (sodium_mlock(data, length) != 0) { return false; } return true; -#else - return false; #endif } bool crypto_memunlock(void *data, size_t length) { -#ifndef VANILLA_NACL +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) + return false; +#else if (sodium_munlock(data, length) != 0) { return false; } return true; -#else - return false; #endif } @@ -169,18 +163,26 @@ bool public_key_eq(const uint8_t *pk1, const uint8_t *pk2) bool crypto_sha512_eq(const uint8_t *cksum1, const uint8_t *cksum2) { -#ifndef VANILLA_NACL - return crypto_verify_64(cksum1, cksum2) == 0; -#else +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) + // Hope that this is better for the fuzzer + return memcmp(cksum1, cksum2, CRYPTO_SHA512_SIZE) == 0; +#elif defined(VANILLA_NACL) const int lo = crypto_verify_32(cksum1, cksum2) == 0 ? 1 : 0; const int hi = crypto_verify_32(cksum1 + 8, cksum2 + 8) == 0 ? 1 : 0; return (lo & hi) == 1; +#else + return crypto_verify_64(cksum1, cksum2) == 0; #endif } bool crypto_sha256_eq(const uint8_t *cksum1, const uint8_t *cksum2) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + // Hope that this is better for the fuzzer + return memcmp(cksum1, cksum2, CRYPTO_SHA256_SIZE) == 0; +#else return crypto_verify_32(cksum1, cksum2) == 0; +#endif } uint8_t random_u08(const Random *rng) @@ -238,17 +240,19 @@ bool crypto_signature_verify(const uint8_t *signature, const uint8_t *message, u bool public_key_valid(const uint8_t *public_key) { - if (public_key[31] >= 128) { /* Last bit of key is always zero. */ - return false; - } - - return true; + /* Last bit of key is always zero. */ + return public_key[31] < 128; } int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + memcpy(shared_key, public_key, CRYPTO_SHARED_KEY_SIZE); + return 0; +#else return crypto_box_beforenm(shared_key, public_key, secret_key); +#endif } int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, @@ -450,11 +454,6 @@ void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key) crypto_scalarmult_curve25519_base(public_key, secret_key); } -void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length) -{ - crypto_hash_sha256(hash, data, length); -} - void new_hmac_key(const Random *rng, uint8_t *key) { random_bytes(rng, key, CRYPTO_HMAC_KEY_SIZE); @@ -472,31 +471,36 @@ bool crypto_hmac_verify(const uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[ return crypto_auth_verify(auth, data, length, key) == 0; } +void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length) +{ +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + memset(hash, 0, CRYPTO_SHA256_SIZE); + memcpy(hash, data, length < CRYPTO_SHA256_SIZE ? length : CRYPTO_SHA256_SIZE); +#else + crypto_hash_sha256(hash, data, length); +#endif +} + void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + memset(hash, 0, CRYPTO_SHA512_SIZE); + memcpy(hash, data, length < CRYPTO_SHA512_SIZE ? length : CRYPTO_SHA512_SIZE); +#else crypto_hash_sha512(hash, data, length); +#endif } non_null() static void sys_random_bytes(void *obj, uint8_t *bytes, size_t length) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - fuzz_random_bytes(bytes, length); -#else randombytes(bytes, length); -#endif } non_null() static uint32_t sys_random_uniform(void *obj, uint32_t upper_bound) { -#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(VANILLA_NACL) - uint32_t randnum; - sys_random_bytes(obj, (uint8_t *)&randnum, sizeof(randnum)); - return randnum % upper_bound; -#else return randombytes_uniform(upper_bound); -#endif // VANILLA_NACL } static const Random_Funcs system_random_funcs = { @@ -515,7 +519,9 @@ const Random *system_random(void) return nullptr; } #endif - + if (TOX_IS_FUZZING) { + return nullptr; + } return &system_random_obj; } diff --git a/toxcore/network.c b/toxcore/network.c index c6cb60bbc04..f73fb087863 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -97,12 +97,6 @@ #include "mono_time.h" #include "util.h" -//!TOKSTYLE- -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -#include "../testing/fuzzing/fuzz_adapter.h" -#endif -//!TOKSTYLE+ - // Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD #if !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 @@ -127,12 +121,10 @@ static bool should_ignore_recv_error(int err) return err == EWOULDBLOCK; } -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION static bool should_ignore_connect_error(int err) { return err == EWOULDBLOCK || err == EINPROGRESS; } -#endif non_null() static const char *inet_ntop4(const struct in_addr *addr, char *buf, size_t bufsize) @@ -483,54 +475,34 @@ struct Network_Addr { non_null() static int sys_close(void *obj, int sock) { -#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) - return 0; -#elif defined(OS_WIN32) +#if defined(OS_WIN32) return closesocket(sock); #else // !OS_WIN32 return close(sock); -#endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#endif } non_null() static int sys_accept(void *obj, int sock) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 2; -#else return accept(sock, nullptr, nullptr); -#endif } non_null() static int sys_bind(void *obj, int sock, const Network_Addr *addr) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else return bind(sock, (const struct sockaddr *)&addr->addr, addr->size); -#endif } non_null() static int sys_listen(void *obj, int sock, int backlog) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else return listen(sock, backlog); -#endif } non_null() static int sys_recvbuf(void *obj, int sock) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - // TODO(iphydf): Return something sensible here (from the fuzzer): number of - // bytes to be read from the socket. - return 0; -#else - #ifdef OS_WIN32 u_long count = 0; ioctlsocket(sock, FIONREAD, &count); @@ -540,100 +512,63 @@ static int sys_recvbuf(void *obj, int sock) #endif return count; -#endif } non_null() static int sys_recv(void *obj, int sock, uint8_t *buf, size_t len) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return fuzz_recv(sock, (char *)buf, len, MSG_NOSIGNAL); -#else return recv(sock, (char *)buf, len, MSG_NOSIGNAL); -#endif } non_null() static int sys_send(void *obj, int sock, const uint8_t *buf, size_t len) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return fuzz_send(sock, (const char *)buf, len, MSG_NOSIGNAL); -#else return send(sock, (const char *)buf, len, MSG_NOSIGNAL); -#endif } non_null() static int sys_sendto(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return fuzz_sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size); -#else return sendto(sock, (const char *)buf, len, 0, (const struct sockaddr *)&addr->addr, addr->size); -#endif } non_null() static int sys_recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - socklen_t size = addr->size; - const int ret = fuzz_recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size); - addr->size = size; - return ret; -#else socklen_t size = addr->size; const int ret = recvfrom(sock, (char *)buf, len, 0, (struct sockaddr *)&addr->addr, &size); addr->size = size; return ret; -#endif } non_null() static int sys_socket(void *obj, int domain, int type, int proto) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 1; -#else return (int)socket(domain, type, proto); -#endif } non_null() static int sys_socket_nonblock(void *obj, int sock, bool nonblock) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else #ifdef OS_WIN32 u_long mode = nonblock ? 1 : 0; return ioctlsocket(sock, FIONBIO, &mode); #else return fcntl(sock, F_SETFL, O_NONBLOCK, nonblock ? 1 : 0); #endif /* OS_WIN32 */ -#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ } non_null() static int sys_getsockopt(void *obj, int sock, int level, int optname, void *optval, size_t *optlen) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - memset(optval, 0, *optlen); - return 0; -#else socklen_t len = *optlen; const int ret = getsockopt(sock, level, optname, optval, &len); *optlen = len; return ret; -#endif } non_null() static int sys_setsockopt(void *obj, int sock, int level, int optname, const void *optval, size_t optlen) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else return setsockopt(sock, level, optname, optval, optlen); -#endif } static const Network_Funcs system_network_funcs = { @@ -662,6 +597,9 @@ const Network *system_network(void) return nullptr; } #endif + if (TOX_IS_FUZZING) { + return nullptr; + } return &system_network_obj; } @@ -1521,11 +1459,9 @@ bool addr_parse_ip(const char *address, IP *to) return false; } -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /** addr_resolve return values */ #define TOX_ADDR_RESOLVE_INET 1 #define TOX_ADDR_RESOLVE_INET6 2 -#endif /** * Uses getaddrinfo to resolve an address into an IP address. @@ -1547,9 +1483,9 @@ bool addr_parse_ip(const char *address, IP *to) non_null(1, 2, 3) nullable(4) static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return 0; -#else + if (TOX_IS_FUZZING) { + return 0; + } if (address == nullptr || to == nullptr) { return 0; @@ -1634,7 +1570,6 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr freeaddrinfo(server); return result; -#endif } bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra) @@ -1674,9 +1609,10 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port) return false; } -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return addrsize != 0; -#else + if (TOX_IS_FUZZING) { + return true; + } + Ip_Ntoa ip_str; LOGGER_DEBUG(log, "connecting socket %d to %s:%d", (int)sock.sock, net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port)); @@ -1696,20 +1632,20 @@ bool net_connect(const Logger *log, Socket sock, const IP_Port *ip_port) } return true; -#endif } int32_t net_getipport(const char *node, IP_Port **res, int tox_type) { -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - *res = (IP_Port *)calloc(1, sizeof(IP_Port)); - assert(*res != nullptr); - IP_Port *ip_port = *res; - ip_port->ip.ip.v4.uint32 = 0x7F000003; // 127.0.0.3 - ip_port->ip.family = *make_tox_family(AF_INET); + if (TOX_IS_FUZZING) { + *res = (IP_Port *)calloc(1, sizeof(IP_Port)); + assert(*res != nullptr); + IP_Port *ip_port = *res; + ip_port->ip.ip.v4.uint32 = 0x7F000003; // 127.0.0.3 + ip_port->ip.family = *make_tox_family(AF_INET); + + return 1; + } - return 1; -#else // Try parsing as IP address first. IP_Port parsed = {{{0}}}; @@ -1798,7 +1734,6 @@ int32_t net_getipport(const char *node, IP_Port **res, int tox_type) freeaddrinfo(infos); return count; -#endif } void net_freeipport(IP_Port *ip_ports)