diff options
Diffstat (limited to 'programs/fuzz')
31 files changed, 1452 insertions, 0 deletions
diff --git a/programs/fuzz/.gitignore b/programs/fuzz/.gitignore new file mode 100644 index 00000000000..34e3ed08827 --- /dev/null +++ b/programs/fuzz/.gitignore @@ -0,0 +1,10 @@ +fuzz_client +fuzz_dtlsclient +fuzz_dtlsserver +fuzz_pkcs7 +fuzz_privkey +fuzz_pubkey +fuzz_server +fuzz_x509crl +fuzz_x509crt +fuzz_x509csr diff --git a/programs/fuzz/CMakeLists.txt b/programs/fuzz/CMakeLists.txt new file mode 100644 index 00000000000..c389029bca9 --- /dev/null +++ b/programs/fuzz/CMakeLists.txt @@ -0,0 +1,50 @@ +set(libs + ${mbedtls_target} + ${CMAKE_THREAD_LIBS_INIT} +) + +find_library(FUZZINGENGINE_LIB FuzzingEngine) +if(FUZZINGENGINE_LIB) + project(fuzz CXX) +endif() + +set(executables_no_common_c + fuzz_pubkey + fuzz_x509crl + fuzz_x509crt + fuzz_x509csr + fuzz_pkcs7 +) + +set(executables_with_common_c + fuzz_privkey + fuzz_client + fuzz_dtlsclient + fuzz_dtlsserver + fuzz_server +) + +foreach(exe IN LISTS executables_no_common_c executables_with_common_c) + + set(exe_sources ${exe}.c $<TARGET_OBJECTS:mbedtls_test>) + if(NOT FUZZINGENGINE_LIB) + list(APPEND exe_sources onefile.c) + endif() + + # This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3 + list(FIND executables_with_common_c ${exe} exe_index) + if(${exe_index} GREATER -1) + list(APPEND exe_sources common.c) + endif() + + add_executable(${exe} ${exe_sources}) + target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include) + + if (NOT FUZZINGENGINE_LIB) + target_link_libraries(${exe} ${libs}) + else() + target_link_libraries(${exe} ${libs} FuzzingEngine) + SET_TARGET_PROPERTIES(${exe} PROPERTIES LINKER_LANGUAGE CXX) + endif() + +endforeach() diff --git a/programs/fuzz/Makefile b/programs/fuzz/Makefile new file mode 100644 index 00000000000..828e5184a67 --- /dev/null +++ b/programs/fuzz/Makefile @@ -0,0 +1,48 @@ +MBEDTLS_TEST_PATH:=../../tests + +MBEDTLS_PATH := ../.. +include ../../scripts/common.make + +DEP=${MBEDLIBS} + +ifdef FUZZINGENGINE +LOCAL_LDFLAGS += -lFuzzingEngine +endif + +# A test application is built for each suites/test_suite_*.data file. +# Application name is same as .data file's base name and can be +# constructed by stripping path 'suites/' and extension .data. +APPS = $(basename $(wildcard fuzz_*.c)) + +# Construct executable name by adding OS specific suffix $(EXEXT). +BINARIES := $(addsuffix $(EXEXT),$(APPS)) + +.SILENT: + +.PHONY: all check test clean + +all: $(BINARIES) + +C_FILES := $(addsuffix .c,$(APPS)) + +%.o: %.c + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $< -o $@ + + +ifdef FUZZINGENGINE +$(BINARIES): %$(EXEXT): %.o common.o $(DEP) + echo " $(CC) common.o $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@" + $(CXX) common.o $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +else +$(BINARIES): %$(EXEXT): %.o common.o onefile.o $(DEP) + echo " $(CC) common.o onefile.o $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@" + $(CC) common.o onefile.o $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +endif + +clean: +ifndef WINDOWS + rm -rf $(BINARIES) *.o +else + if exist *.o del /Q /F *.o + if exist *.exe del /Q /F *.exe +endif diff --git a/programs/fuzz/README.md b/programs/fuzz/README.md new file mode 100644 index 00000000000..aaef03015dc --- /dev/null +++ b/programs/fuzz/README.md @@ -0,0 +1,68 @@ +What is it? +------ + +This directory contains fuzz targets. +Fuzz targets are simple codes using the library. +They are used with a so-called fuzz driver, which will generate inputs, try to process them with the fuzz target, and alert in case of an unwanted behavior (such as a buffer overflow for instance). + +These targets were meant to be used with oss-fuzz but can be used in other contexts. + +This code was contributed by Philippe Antoine ( Catena cyber ). + +How to run? +------ + +To run the fuzz targets like oss-fuzz: +``` +git clone https://github.com/google/oss-fuzz +cd oss-fuzz +python infra/helper.py build_image mbedtls +python infra/helper.py build_fuzzers --sanitizer address mbedtls +python infra/helper.py run_fuzzer mbedtls fuzz_client +``` +You can use `undefined` sanitizer as well as `address` sanitizer. +And you can run any of the fuzz targets like `fuzz_client`. + +To run the fuzz targets without oss-fuzz, you first need to install one libFuzzingEngine (libFuzzer for instance). +Then you need to compile the code with the compiler flags of the wished sanitizer. +``` +perl scripts/config.py set MBEDTLS_PLATFORM_TIME_ALT +mkdir build +cd build +cmake .. +make +``` +Finally, you can run the targets like `./test/fuzz/fuzz_client`. + + +Corpus generation for network traffic targets +------ + +These targets use network traffic as inputs : +* client : simulates a client against (fuzzed) server traffic +* server : simulates a server against (fuzzed) client traffic +* dtls_client +* dtls_server + +They also use the last bytes as configuration options. + +To generate corpus for these targets, you can do the following, not fully automated steps : +* Build mbedtls programs ssl_server2 and ssl_client2 +* Run them one against the other with `reproducible` option turned on while capturing traffic into test.pcap +* Extract tcp payloads, for instance with tshark : `tshark -Tfields -e tcp.dstport -e tcp.payload -r test.pcap > test.txt` +* Run a dummy python script to output either client or server corpus file like `python dummy.py test.txt > test.cor` +* Finally, you can add the options by appending the last bytes to the file test.cor + +Here is an example of dummy.py for extracting payload from client to server (if we used `tcp.dstport` in tshark command) +``` +import sys +import binascii + +f = open(sys.argv[1]) +for l in f.readlines(): + portAndPl=l.split() + if len(portAndPl) == 2: + # determine client or server based on port + if portAndPl[0] == "4433": + print(binascii.unhexlify(portAndPl[1].replace(":",""))) +``` diff --git a/programs/fuzz/common.c b/programs/fuzz/common.c new file mode 100644 index 00000000000..98aa4037b36 --- /dev/null +++ b/programs/fuzz/common.c @@ -0,0 +1,105 @@ +#include "common.h" +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "mbedtls/ctr_drbg.h" + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +mbedtls_time_t dummy_constant_time(mbedtls_time_t *time) +{ + (void) time; + return 0x5af2a056; +} +#endif + +void dummy_init(void) +{ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + mbedtls_platform_set_time(dummy_constant_time); +#else + fprintf(stderr, "Warning: fuzzing without constant time\n"); +#endif +} + +int dummy_send(void *ctx, const unsigned char *buf, size_t len) +{ + //silence warning about unused parameter + (void) ctx; + (void) buf; + + //pretends we wrote everything ok + if (len > INT_MAX) { + return -1; + } + return (int) len; +} + +int fuzz_recv(void *ctx, unsigned char *buf, size_t len) +{ + //reads from the buffer from fuzzer + fuzzBufferOffset_t *biomemfuzz = (fuzzBufferOffset_t *) ctx; + + if (biomemfuzz->Offset == biomemfuzz->Size) { + //EOF + return 0; + } + if (len > INT_MAX) { + return -1; + } + if (len + biomemfuzz->Offset > biomemfuzz->Size) { + //do not overflow + len = biomemfuzz->Size - biomemfuzz->Offset; + } + memcpy(buf, biomemfuzz->Data + biomemfuzz->Offset, len); + biomemfuzz->Offset += len; + return (int) len; +} + +int dummy_random(void *p_rng, unsigned char *output, size_t output_len) +{ + int ret; + size_t i; + +#if defined(MBEDTLS_CTR_DRBG_C) + //mbedtls_ctr_drbg_random requires a valid mbedtls_ctr_drbg_context in p_rng + if (p_rng != NULL) { + //use mbedtls_ctr_drbg_random to find bugs in it + ret = mbedtls_ctr_drbg_random(p_rng, output, output_len); + } else { + //fall through to pseudo-random + ret = 0; + } +#else + (void) p_rng; + ret = 0; +#endif + for (i = 0; i < output_len; i++) { + //replace result with pseudo random + output[i] = (unsigned char) rand(); + } + return ret; +} + +int dummy_entropy(void *data, unsigned char *output, size_t len) +{ + size_t i; + (void) data; + + //use mbedtls_entropy_func to find bugs in it + //test performance impact of entropy + //ret = mbedtls_entropy_func(data, output, len); + for (i = 0; i < len; i++) { + //replace result with pseudo random + output[i] = (unsigned char) rand(); + } + return 0; +} + +int fuzz_recv_timeout(void *ctx, unsigned char *buf, size_t len, + uint32_t timeout) +{ + (void) timeout; + + return fuzz_recv(ctx, buf, len); +} diff --git a/programs/fuzz/common.h b/programs/fuzz/common.h new file mode 100644 index 00000000000..094383c7a43 --- /dev/null +++ b/programs/fuzz/common.h @@ -0,0 +1,25 @@ +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#include <stddef.h> +#include <stdint.h> + +typedef struct fuzzBufferOffset { + const uint8_t *Data; + size_t Size; + size_t Offset; +} fuzzBufferOffset_t; + +#if defined(MBEDTLS_HAVE_TIME) +mbedtls_time_t dummy_constant_time(mbedtls_time_t *time); +#endif +void dummy_init(void); + +int dummy_send(void *ctx, const unsigned char *buf, size_t len); +int fuzz_recv(void *ctx, unsigned char *buf, size_t len); +int dummy_random(void *p_rng, unsigned char *output, size_t output_len); +int dummy_entropy(void *data, unsigned char *output, size_t len); +int fuzz_recv_timeout(void *ctx, unsigned char *buf, size_t len, + uint32_t timeout); diff --git a/programs/fuzz/corpuses/client b/programs/fuzz/corpuses/client Binary files differnew file mode 100644 index 00000000000..48d0a67c8f3 --- /dev/null +++ b/programs/fuzz/corpuses/client diff --git a/programs/fuzz/corpuses/dtlsclient b/programs/fuzz/corpuses/dtlsclient Binary files differnew file mode 100644 index 00000000000..87c3ca333a3 --- /dev/null +++ b/programs/fuzz/corpuses/dtlsclient diff --git a/programs/fuzz/corpuses/dtlsserver b/programs/fuzz/corpuses/dtlsserver Binary files differnew file mode 100644 index 00000000000..7a7a1179007 --- /dev/null +++ b/programs/fuzz/corpuses/dtlsserver diff --git a/programs/fuzz/corpuses/server b/programs/fuzz/corpuses/server Binary files differnew file mode 100644 index 00000000000..fbeb019f200 --- /dev/null +++ b/programs/fuzz/corpuses/server diff --git a/programs/fuzz/fuzz_client.c b/programs/fuzz/fuzz_client.c new file mode 100644 index 00000000000..07ca96efa8e --- /dev/null +++ b/programs/fuzz/fuzz_client.c @@ -0,0 +1,193 @@ +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "test/certs.h" +#include "common.h" +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + + +#if defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) +static int initialized = 0; +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) +static mbedtls_x509_crt cacert; +#endif +const char *alpn_list[3]; + + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +const unsigned char psk[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; +const char psk_id[] = "Client_identity"; +#endif + +const char *pers = "fuzz_client"; +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */ + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#if defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) + int ret; + size_t len; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + unsigned char buf[4096]; + fuzzBufferOffset_t biomemfuzz; + uint16_t options; + + if (initialized == 0) { +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_x509_crt_init(&cacert); + if (mbedtls_x509_crt_parse(&cacert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len) != 0) { + return 1; + } +#endif + + alpn_list[0] = "HTTP"; + alpn_list[1] = "fuzzalpn"; + alpn_list[2] = NULL; + + dummy_init(); + + initialized = 1; + } + + //we take 1 byte as options input + if (Size < 2) { + return 0; + } + options = (Data[Size - 2] << 8) | Data[Size - 1]; + //Avoid warnings if compile options imply no options + (void) options; + + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (mbedtls_ctr_drbg_seed(&ctr_drbg, dummy_entropy, &entropy, + (const unsigned char *) pers, strlen(pers)) != 0) { + goto exit; + } + + if (mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT) != 0) { + goto exit; + } + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if (options & 2) { + mbedtls_ssl_conf_psk(&conf, psk, sizeof(psk), + (const unsigned char *) psk_id, sizeof(psk_id) - 1); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + if (options & 4) { + mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); + mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); + } else +#endif + { + mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); + } +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + mbedtls_ssl_conf_extended_master_secret(&conf, + (options & + 0x10) ? MBEDTLS_SSL_EXTENDED_MS_DISABLED : MBEDTLS_SSL_EXTENDED_MS_ENABLED); +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + mbedtls_ssl_conf_encrypt_then_mac(&conf, + (options & + 0x20) ? MBEDTLS_SSL_ETM_DISABLED : MBEDTLS_SSL_ETM_ENABLED); +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation(&conf, + (options & + 0x80) ? MBEDTLS_SSL_RENEGOTIATION_ENABLED : MBEDTLS_SSL_RENEGOTIATION_DISABLED); +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_session_tickets(&conf, + (options & + 0x100) ? MBEDTLS_SSL_SESSION_TICKETS_DISABLED : MBEDTLS_SSL_SESSION_TICKETS_ENABLED); +#endif +#if defined(MBEDTLS_SSL_ALPN) + if (options & 0x200) { + mbedtls_ssl_conf_alpn_protocols(&conf, alpn_list); + } +#endif + //There may be other options to add : + // mbedtls_ssl_conf_cert_profile, mbedtls_ssl_conf_sig_hashes + + srand(1); + mbedtls_ssl_conf_rng(&conf, dummy_random, &ctr_drbg); + + if (mbedtls_ssl_setup(&ssl, &conf) != 0) { + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + if ((options & 1) == 0) { + if (mbedtls_ssl_set_hostname(&ssl, "localhost") != 0) { + goto exit; + } + } +#endif + + biomemfuzz.Data = Data; + biomemfuzz.Size = Size-2; + biomemfuzz.Offset = 0; + mbedtls_ssl_set_bio(&ssl, &biomemfuzz, dummy_send, fuzz_recv, NULL); + + ret = mbedtls_ssl_handshake(&ssl); + if (ret == 0) { + //keep reading data from server until the end + do { + len = sizeof(buf) - 1; + ret = mbedtls_ssl_read(&ssl, buf, len); + + if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + continue; + } else if (ret <= 0) { + //EOF or error + break; + } + } while (1); + } + +exit: + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_ssl_config_free(&conf); + mbedtls_ssl_free(&ssl); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#else + (void) Data; + (void) Size; +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */ + + return 0; +} diff --git a/programs/fuzz/fuzz_client.options b/programs/fuzz/fuzz_client.options new file mode 100644 index 00000000000..4d7340f497a --- /dev/null +++ b/programs/fuzz/fuzz_client.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 1048575 diff --git a/programs/fuzz/fuzz_dtlsclient.c b/programs/fuzz/fuzz_dtlsclient.c new file mode 100644 index 00000000000..6581dcb1e69 --- /dev/null +++ b/programs/fuzz/fuzz_dtlsclient.c @@ -0,0 +1,136 @@ +#include <string.h> +#include <stdlib.h> +#include <stdint.h> +#include "common.h" +#include "mbedtls/ssl.h" +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/timing.h" +#include "test/certs.h" + +#if defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_TIMING_C) +static int initialized = 0; +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) +static mbedtls_x509_crt cacert; +#endif + +const char *pers = "fuzz_dtlsclient"; +#endif +#endif // MBEDTLS_SSL_PROTO_DTLS + + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_TIMING_C) + int ret; + size_t len; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + mbedtls_timing_delay_context timer; + unsigned char buf[4096]; + fuzzBufferOffset_t biomemfuzz; + + if (initialized == 0) { +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_x509_crt_init(&cacert); + if (mbedtls_x509_crt_parse(&cacert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len) != 0) { + return 1; + } +#endif + dummy_init(); + + initialized = 1; + } + + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + srand(1); + if (mbedtls_ctr_drbg_seed(&ctr_drbg, dummy_entropy, &entropy, + (const unsigned char *) pers, strlen(pers)) != 0) { + goto exit; + } + + if (mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT) != 0) { + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); +#endif + mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); + mbedtls_ssl_conf_rng(&conf, dummy_random, &ctr_drbg); + + if (mbedtls_ssl_setup(&ssl, &conf) != 0) { + goto exit; + } + + mbedtls_ssl_set_timer_cb(&ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + if (mbedtls_ssl_set_hostname(&ssl, "localhost") != 0) { + goto exit; + } +#endif + + biomemfuzz.Data = Data; + biomemfuzz.Size = Size; + biomemfuzz.Offset = 0; + mbedtls_ssl_set_bio(&ssl, &biomemfuzz, dummy_send, fuzz_recv, fuzz_recv_timeout); + + ret = mbedtls_ssl_handshake(&ssl); + if (ret == 0) { + //keep reading data from server until the end + do { + len = sizeof(buf) - 1; + ret = mbedtls_ssl_read(&ssl, buf, len); + + if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + continue; + } else if (ret <= 0) { + //EOF or error + break; + } + } while (1); + } + +exit: + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_ssl_config_free(&conf); + mbedtls_ssl_free(&ssl); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#else + (void) Data; + (void) Size; +#endif + return 0; +} diff --git a/programs/fuzz/fuzz_dtlsclient.options b/programs/fuzz/fuzz_dtlsclient.options new file mode 100644 index 00000000000..4d7340f497a --- /dev/null +++ b/programs/fuzz/fuzz_dtlsclient.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 1048575 diff --git a/programs/fuzz/fuzz_dtlsserver.c b/programs/fuzz/fuzz_dtlsserver.c new file mode 100644 index 00000000000..fd3e0aa9c78 --- /dev/null +++ b/programs/fuzz/fuzz_dtlsserver.c @@ -0,0 +1,181 @@ +#include <string.h> +#include <stdlib.h> +#include <stdint.h> +#include "common.h" +#include "mbedtls/ssl.h" +#include "test/certs.h" +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/timing.h" +#include "mbedtls/ssl_cookie.h" + +#if defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_TIMING_C) && \ + (defined(MBEDTLS_MD_CAN_SHA384) || \ + defined(MBEDTLS_MD_CAN_SHA256)) +const char *pers = "fuzz_dtlsserver"; +const unsigned char client_ip[4] = { 0x7F, 0, 0, 1 }; +static int initialized = 0; +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) +static mbedtls_x509_crt srvcert; +static mbedtls_pk_context pkey; +#endif +#endif +#endif // MBEDTLS_SSL_PROTO_DTLS + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_TIMING_C) && \ + (defined(MBEDTLS_MD_CAN_SHA384) || \ + defined(MBEDTLS_MD_CAN_SHA256)) + int ret; + size_t len; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + mbedtls_timing_delay_context timer; + mbedtls_ssl_cookie_ctx cookie_ctx; + unsigned char buf[4096]; + fuzzBufferOffset_t biomemfuzz; + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_x509_crt_init(&srvcert); + mbedtls_pk_init(&pkey); +#endif + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + mbedtls_ssl_cookie_init(&cookie_ctx); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (mbedtls_ctr_drbg_seed(&ctr_drbg, dummy_entropy, &entropy, + (const unsigned char *) pers, strlen(pers)) != 0) { + goto exit; + } + + if (initialized == 0) { +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + + if (mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_srv_crt, + mbedtls_test_srv_crt_len) != 0) { + return 1; + } + if (mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len) != 0) { + return 1; + } + if (mbedtls_pk_parse_key(&pkey, (const unsigned char *) mbedtls_test_srv_key, + mbedtls_test_srv_key_len, NULL, 0, + dummy_random, &ctr_drbg) != 0) { + return 1; + } +#endif + dummy_init(); + + initialized = 1; + } + + if (mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT) != 0) { + goto exit; + } + + + srand(1); + mbedtls_ssl_conf_rng(&conf, dummy_random, &ctr_drbg); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); + if (mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey) != 0) { + goto exit; + } +#endif + + if (mbedtls_ssl_cookie_setup(&cookie_ctx, dummy_random, &ctr_drbg) != 0) { + goto exit; + } + + mbedtls_ssl_conf_dtls_cookies(&conf, + mbedtls_ssl_cookie_write, + mbedtls_ssl_cookie_check, + &cookie_ctx); + + if (mbedtls_ssl_setup(&ssl, &conf) != 0) { + goto exit; + } + + mbedtls_ssl_set_timer_cb(&ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay); + + biomemfuzz.Data = Data; + biomemfuzz.Size = Size; + biomemfuzz.Offset = 0; + mbedtls_ssl_set_bio(&ssl, &biomemfuzz, dummy_send, fuzz_recv, fuzz_recv_timeout); + if (mbedtls_ssl_set_client_transport_id(&ssl, client_ip, sizeof(client_ip)) != 0) { + goto exit; + } + + ret = mbedtls_ssl_handshake(&ssl); + + if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { + biomemfuzz.Offset = ssl.MBEDTLS_PRIVATE(next_record_offset); + mbedtls_ssl_session_reset(&ssl); + mbedtls_ssl_set_bio(&ssl, &biomemfuzz, dummy_send, fuzz_recv, fuzz_recv_timeout); + if (mbedtls_ssl_set_client_transport_id(&ssl, client_ip, sizeof(client_ip)) != 0) { + goto exit; + } + + ret = mbedtls_ssl_handshake(&ssl); + + if (ret == 0) { + //keep reading data from server until the end + do { + len = sizeof(buf) - 1; + ret = mbedtls_ssl_read(&ssl, buf, len); + if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + continue; + } else if (ret <= 0) { + //EOF or error + break; + } + } while (1); + } + } + +exit: + mbedtls_ssl_cookie_free(&cookie_ctx); + mbedtls_entropy_free(&entropy); +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pk_free(&pkey); + mbedtls_x509_crt_free(&srvcert); +#endif + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_ssl_config_free(&conf); + mbedtls_ssl_free(&ssl); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#else + (void) Data; + (void) Size; +#endif + return 0; +} diff --git a/programs/fuzz/fuzz_dtlsserver.options b/programs/fuzz/fuzz_dtlsserver.options new file mode 100644 index 00000000000..4d7340f497a --- /dev/null +++ b/programs/fuzz/fuzz_dtlsserver.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 1048575 diff --git a/programs/fuzz/fuzz_pkcs7.c b/programs/fuzz/fuzz_pkcs7.c new file mode 100644 index 00000000000..2056913f25c --- /dev/null +++ b/programs/fuzz/fuzz_pkcs7.c @@ -0,0 +1,20 @@ +#include <stdint.h> +#include "mbedtls/pkcs7.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#ifdef MBEDTLS_PKCS7_C + mbedtls_pkcs7 pkcs7; + + mbedtls_pkcs7_init(&pkcs7); + + mbedtls_pkcs7_parse_der(&pkcs7, Data, Size); + + mbedtls_pkcs7_free(&pkcs7); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/programs/fuzz/fuzz_pkcs7.options b/programs/fuzz/fuzz_pkcs7.options new file mode 100644 index 00000000000..0824b19fab4 --- /dev/null +++ b/programs/fuzz/fuzz_pkcs7.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/programs/fuzz/fuzz_privkey.c b/programs/fuzz/fuzz_privkey.c new file mode 100644 index 00000000000..753096406d9 --- /dev/null +++ b/programs/fuzz/fuzz_privkey.c @@ -0,0 +1,104 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include "mbedtls/pk.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "common.h" + +//4 Kb should be enough for every bug ;-) +#define MAX_LEN 0x1000 + +#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_CTR_DRBG_C) && defined(MBEDTLS_ENTROPY_C) +const char *pers = "fuzz_privkey"; +#endif // MBEDTLS_PK_PARSE_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_ENTROPY_C + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_CTR_DRBG_C) && defined(MBEDTLS_ENTROPY_C) + int ret; + mbedtls_pk_context pk; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + + if (Size > MAX_LEN) { + //only work on small inputs + Size = MAX_LEN; + } + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + mbedtls_pk_init(&pk); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (mbedtls_ctr_drbg_seed(&ctr_drbg, dummy_entropy, &entropy, + (const unsigned char *) pers, strlen(pers)) != 0) { + goto exit; + } + + ret = mbedtls_pk_parse_key(&pk, Data, Size, NULL, 0, + dummy_random, &ctr_drbg); + if (ret == 0) { +#if defined(MBEDTLS_RSA_C) + if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) { + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + mbedtls_rsa_context *rsa; + + mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q); + mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP); + mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP); + + rsa = mbedtls_pk_rsa(pk); + if (mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E) != 0) { + abort(); + } + if (mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP) != 0) { + abort(); + } + + mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q); + mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP); + mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP); + } else +#endif +#if defined(MBEDTLS_ECP_C) + if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY || + mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY_DH) { + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk); + mbedtls_ecp_group_id grp_id = mbedtls_ecp_keypair_get_group_id(ecp); + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id(grp_id); + + /* If the curve is not supported, the key should not have been + * accepted. */ + if (curve_info == NULL) { + abort(); + } + } else +#endif + { + /* The key is valid but is not of a supported type. + * This should not happen. */ + abort(); + } + } +exit: + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_pk_free(&pk); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#else + (void) Data; + (void) Size; +#endif // MBEDTLS_PK_PARSE_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_ENTROPY_C + + return 0; +} diff --git a/programs/fuzz/fuzz_privkey.options b/programs/fuzz/fuzz_privkey.options new file mode 100644 index 00000000000..0824b19fab4 --- /dev/null +++ b/programs/fuzz/fuzz_privkey.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/programs/fuzz/fuzz_pubkey.c b/programs/fuzz/fuzz_pubkey.c new file mode 100644 index 00000000000..0b153b14d7d --- /dev/null +++ b/programs/fuzz/fuzz_pubkey.c @@ -0,0 +1,90 @@ +#include <stdint.h> +#include <stdlib.h> +#include "mbedtls/pk.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#ifdef MBEDTLS_PK_PARSE_C + int ret; + mbedtls_pk_context pk; + + mbedtls_pk_init(&pk); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_pk_parse_public_key(&pk, Data, Size); + if (ret == 0) { +#if defined(MBEDTLS_RSA_C) + if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_RSA) { + mbedtls_mpi N, P, Q, D, E, DP, DQ, QP; + mbedtls_rsa_context *rsa; + + mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q); + mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP); + mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP); + + rsa = mbedtls_pk_rsa(pk); + if (mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E) != 0) { + abort(); + } + if (mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E) != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { + abort(); + } + if (mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP) != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { + abort(); + } + + mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q); + mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP); + mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP); + + } else +#endif +#if defined(MBEDTLS_ECP_C) + if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY || + mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY_DH) { + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk); + mbedtls_ecp_group_id grp_id = mbedtls_ecp_keypair_get_group_id(ecp); + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id(grp_id); + + /* If the curve is not supported, the key should not have been + * accepted. */ + if (curve_info == NULL) { + abort(); + } + + /* It's a public key, so the private value should not have + * been changed from its initialization to 0. */ + mbedtls_mpi d; + mbedtls_mpi_init(&d); + if (mbedtls_ecp_export(ecp, NULL, &d, NULL) != 0) { + abort(); + } + if (mbedtls_mpi_cmp_int(&d, 0) != 0) { + abort(); + } + mbedtls_mpi_free(&d); + } else +#endif + { + /* The key is valid but is not of a supported type. + * This should not happen. */ + abort(); + } + } +#if defined(MBEDTLS_USE_PSA_CRYPTO) +exit: + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_pk_free(&pk); +#else + (void) Data; + (void) Size; +#endif //MBEDTLS_PK_PARSE_C + + return 0; +} diff --git a/programs/fuzz/fuzz_pubkey.options b/programs/fuzz/fuzz_pubkey.options new file mode 100644 index 00000000000..0824b19fab4 --- /dev/null +++ b/programs/fuzz/fuzz_pubkey.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/programs/fuzz/fuzz_server.c b/programs/fuzz/fuzz_server.c new file mode 100644 index 00000000000..64b35edb9b0 --- /dev/null +++ b/programs/fuzz/fuzz_server.c @@ -0,0 +1,216 @@ +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/ssl_ticket.h" +#include "test/certs.h" +#include "common.h" +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + + +#if defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) +const char *pers = "fuzz_server"; +static int initialized = 0; +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) +static mbedtls_x509_crt srvcert; +static mbedtls_pk_context pkey; +#endif +const char *alpn_list[3]; + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +const unsigned char psk[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; +const char psk_id[] = "Client_identity"; +#endif +#endif // MBEDTLS_SSL_SRV_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#if defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_CTR_DRBG_C) + int ret; + size_t len; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_TICKET_C) + mbedtls_ssl_ticket_context ticket_ctx; +#endif + unsigned char buf[4096]; + fuzzBufferOffset_t biomemfuzz; + uint8_t options; + + //we take 1 byte as options input + if (Size < 1) { + return 0; + } + options = Data[Size - 1]; + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_x509_crt_init(&srvcert); + mbedtls_pk_init(&pkey); +#endif + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_TICKET_C) + mbedtls_ssl_ticket_init(&ticket_ctx); +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (mbedtls_ctr_drbg_seed(&ctr_drbg, dummy_entropy, &entropy, + (const unsigned char *) pers, strlen(pers)) != 0) { + return 1; + } + + if (initialized == 0) { + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + if (mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_srv_crt, + mbedtls_test_srv_crt_len) != 0) { + return 1; + } + if (mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len) != 0) { + return 1; + } + if (mbedtls_pk_parse_key(&pkey, (const unsigned char *) mbedtls_test_srv_key, + mbedtls_test_srv_key_len, NULL, 0, + dummy_random, &ctr_drbg) != 0) { + return 1; + } +#endif + + alpn_list[0] = "HTTP"; + alpn_list[1] = "fuzzalpn"; + alpn_list[2] = NULL; + + dummy_init(); + + initialized = 1; + } + + if (mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT) != 0) { + goto exit; + } + + srand(1); + mbedtls_ssl_conf_rng(&conf, dummy_random, &ctr_drbg); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); + if (mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey) != 0) { + goto exit; + } +#endif + + mbedtls_ssl_conf_cert_req_ca_list(&conf, + (options & + 0x1) ? MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED : MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED); +#if defined(MBEDTLS_SSL_ALPN) + if (options & 0x2) { + mbedtls_ssl_conf_alpn_protocols(&conf, alpn_list); + } +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_TICKET_C) + if (options & 0x4) { + if (mbedtls_ssl_ticket_setup(&ticket_ctx, + dummy_random, &ctr_drbg, + MBEDTLS_CIPHER_AES_256_GCM, + 86400) != 0) { + goto exit; + } + + mbedtls_ssl_conf_session_tickets_cb(&conf, + mbedtls_ssl_ticket_write, + mbedtls_ssl_ticket_parse, + &ticket_ctx); + } +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + mbedtls_ssl_conf_extended_master_secret(&conf, + (options & + 0x10) ? MBEDTLS_SSL_EXTENDED_MS_DISABLED : MBEDTLS_SSL_EXTENDED_MS_ENABLED); +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + mbedtls_ssl_conf_encrypt_then_mac(&conf, + (options & + 0x20) ? MBEDTLS_SSL_ETM_ENABLED : MBEDTLS_SSL_ETM_DISABLED); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if (options & 0x40) { + mbedtls_ssl_conf_psk(&conf, psk, sizeof(psk), + (const unsigned char *) psk_id, sizeof(psk_id) - 1); + } +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation(&conf, + (options & + 0x80) ? MBEDTLS_SSL_RENEGOTIATION_ENABLED : MBEDTLS_SSL_RENEGOTIATION_DISABLED); +#endif + + if (mbedtls_ssl_setup(&ssl, &conf) != 0) { + goto exit; + } + + biomemfuzz.Data = Data; + biomemfuzz.Size = Size-1; + biomemfuzz.Offset = 0; + mbedtls_ssl_set_bio(&ssl, &biomemfuzz, dummy_send, fuzz_recv, NULL); + + mbedtls_ssl_session_reset(&ssl); + ret = mbedtls_ssl_handshake(&ssl); + if (ret == 0) { + //keep reading data from server until the end + do { + len = sizeof(buf) - 1; + ret = mbedtls_ssl_read(&ssl, buf, len); + + if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + continue; + } else if (ret <= 0) { + //EOF or error + break; + } + } while (1); + } + +exit: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_TICKET_C) + mbedtls_ssl_ticket_free(&ticket_ctx); +#endif + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_ssl_config_free(&conf); +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_PEM_PARSE_C) + mbedtls_x509_crt_free(&srvcert); + mbedtls_pk_free(&pkey); +#endif + mbedtls_ssl_free(&ssl); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_psa_crypto_free(); +#endif +#else + (void) Data; + (void) Size; +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */ + + return 0; +} diff --git a/programs/fuzz/fuzz_server.options b/programs/fuzz/fuzz_server.options new file mode 100644 index 00000000000..4d7340f497a --- /dev/null +++ b/programs/fuzz/fuzz_server.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 1048575 diff --git a/programs/fuzz/fuzz_x509crl.c b/programs/fuzz/fuzz_x509crl.c new file mode 100644 index 00000000000..151db92c890 --- /dev/null +++ b/programs/fuzz/fuzz_x509crl.c @@ -0,0 +1,39 @@ +#include <stdint.h> +#include "mbedtls/x509_crl.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#ifdef MBEDTLS_X509_CRL_PARSE_C + int ret; + mbedtls_x509_crl crl; + unsigned char buf[4096]; + + mbedtls_x509_crl_init(&crl); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_x509_crl_parse(&crl, Data, Size); +#if !defined(MBEDTLS_X509_REMOVE_INFO) + if (ret == 0) { + ret = mbedtls_x509_crl_info((char *) buf, sizeof(buf) - 1, " ", &crl); + } +#else + ((void) ret); + ((void) buf); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +exit: + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_x509_crl_free(&crl); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/programs/fuzz/fuzz_x509crl.options b/programs/fuzz/fuzz_x509crl.options new file mode 100644 index 00000000000..0824b19fab4 --- /dev/null +++ b/programs/fuzz/fuzz_x509crl.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/programs/fuzz/fuzz_x509crt.c b/programs/fuzz/fuzz_x509crt.c new file mode 100644 index 00000000000..3eee07258bc --- /dev/null +++ b/programs/fuzz/fuzz_x509crt.c @@ -0,0 +1,39 @@ +#include <stdint.h> +#include "mbedtls/x509_crt.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#ifdef MBEDTLS_X509_CRT_PARSE_C + int ret; + mbedtls_x509_crt crt; + unsigned char buf[4096]; + + mbedtls_x509_crt_init(&crt); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_x509_crt_parse(&crt, Data, Size); +#if !defined(MBEDTLS_X509_REMOVE_INFO) + if (ret == 0) { + ret = mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", &crt); + } +#else + ((void) ret); + ((void) buf); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +exit: + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_x509_crt_free(&crt); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/programs/fuzz/fuzz_x509crt.options b/programs/fuzz/fuzz_x509crt.options new file mode 100644 index 00000000000..0824b19fab4 --- /dev/null +++ b/programs/fuzz/fuzz_x509crt.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/programs/fuzz/fuzz_x509csr.c b/programs/fuzz/fuzz_x509csr.c new file mode 100644 index 00000000000..7946e57eda0 --- /dev/null +++ b/programs/fuzz/fuzz_x509csr.c @@ -0,0 +1,39 @@ +#include <stdint.h> +#include "mbedtls/x509_csr.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ +#ifdef MBEDTLS_X509_CSR_PARSE_C + int ret; + mbedtls_x509_csr csr; + unsigned char buf[4096]; + + mbedtls_x509_csr_init(&csr); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_x509_csr_parse(&csr, Data, Size); +#if !defined(MBEDTLS_X509_REMOVE_INFO) + if (ret == 0) { + ret = mbedtls_x509_csr_info((char *) buf, sizeof(buf) - 1, " ", &csr); + } +#else + ((void) ret); + ((void) buf); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +exit: + mbedtls_psa_crypto_free(); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_x509_csr_free(&csr); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/programs/fuzz/fuzz_x509csr.options b/programs/fuzz/fuzz_x509csr.options new file mode 100644 index 00000000000..0824b19fab4 --- /dev/null +++ b/programs/fuzz/fuzz_x509csr.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/programs/fuzz/onefile.c b/programs/fuzz/onefile.c new file mode 100644 index 00000000000..3b2709f8058 --- /dev/null +++ b/programs/fuzz/onefile.c @@ -0,0 +1,69 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +/* This file doesn't use any Mbed TLS function, but grab mbedtls_config.h anyway + * in case it contains platform-specific #defines related to malloc or + * stdio functions. */ +#include "mbedtls/build_info.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +int main(int argc, char **argv) +{ + FILE *fp; + uint8_t *Data; + size_t Size; + const char *argv0 = argv[0] == NULL ? "PROGRAM_NAME" : argv[0]; + + if (argc != 2) { + fprintf(stderr, "Usage: %s REPRODUCER_FILE\n", argv0); + return 1; + } + //opens the file, get its size, and reads it into a buffer + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + fprintf(stderr, "%s: Error in fopen\n", argv0); + perror(argv[1]); + return 2; + } + if (fseek(fp, 0L, SEEK_END) != 0) { + fprintf(stderr, "%s: Error in fseek(SEEK_END)\n", argv0); + perror(argv[1]); + fclose(fp); + return 2; + } + Size = ftell(fp); + if (Size == (size_t) -1) { + fprintf(stderr, "%s: Error in ftell\n", argv0); + perror(argv[1]); + fclose(fp); + return 2; + } + if (fseek(fp, 0L, SEEK_SET) != 0) { + fprintf(stderr, "%s: Error in fseek(0)\n", argv0); + perror(argv[1]); + fclose(fp); + return 2; + } + Data = malloc(Size); + if (Data == NULL) { + fprintf(stderr, "%s: Could not allocate memory\n", argv0); + perror(argv[1]); + fclose(fp); + return 2; + } + if (fread(Data, Size, 1, fp) != 1) { + fprintf(stderr, "%s: Error in fread\n", argv0); + perror(argv[1]); + free(Data); + fclose(fp); + return 2; + } + + //launch fuzzer + LLVMFuzzerTestOneInput(Data, Size); + free(Data); + fclose(fp); + return 0; +} |