diff --git a/programs/fuzz/CMakeLists.txt b/programs/fuzz/CMakeLists.txt index bd9bf91d94..53d771cc14 100644 --- a/programs/fuzz/CMakeLists.txt +++ b/programs/fuzz/CMakeLists.txt @@ -31,19 +31,18 @@ foreach(exe IN LISTS executables_no_common_c executables_with_common_c) $ $) if(NOT FUZZINGENGINE_LIB) - list(APPEND exe_sources ${MBEDTLS_DIR}/tf-psa-crypto/programs/fuzz/onefile.c) + 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 ${MBEDTLS_DIR}/tf-psa-crypto/programs/fuzz/fuzz_common.c) + list(APPEND exe_sources fuzz_common.c) endif() add_executable(${exe} ${exe_sources}) set_base_compile_options(${exe}) target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../framework/tests/include - ${CMAKE_CURRENT_SOURCE_DIR}/../../tf-psa-crypto/programs/fuzz/ ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include) if (NOT FUZZINGENGINE_LIB) diff --git a/programs/fuzz/fuzz_common.c b/programs/fuzz/fuzz_common.c new file mode 100644 index 0000000000..de16913728 --- /dev/null +++ b/programs/fuzz/fuzz_common.c @@ -0,0 +1,107 @@ +#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS + +#include "fuzz_common.h" +#include +#include +#include +#include +#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/fuzz_common.h b/programs/fuzz/fuzz_common.h new file mode 100644 index 0000000000..88dceacf72 --- /dev/null +++ b/programs/fuzz/fuzz_common.h @@ -0,0 +1,28 @@ +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#include +#include + +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); + +/* Implemented in the fuzz_*.c sources and required by onefile.c */ +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); diff --git a/programs/fuzz/onefile.c b/programs/fuzz/onefile.c new file mode 100644 index 0000000000..483512855c --- /dev/null +++ b/programs/fuzz/onefile.c @@ -0,0 +1,70 @@ +#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS + +#include +#include +#include +#include "fuzz_common.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 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; +}