diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ecf6f34b2..d060255bd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -77,3 +77,5 @@ if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) link_to_source(scripts) link_to_source(ssl-opt.sh) endif() + +add_subdirectory(fuzz) diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt new file mode 100644 index 000000000..1392f63ca --- /dev/null +++ b/tests/fuzz/CMakeLists.txt @@ -0,0 +1,38 @@ +set(libs + mbedtls +) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +add_executable(fuzz_x509csr fuzz_x509csr.c onefile.c) +target_link_libraries(fuzz_x509csr ${libs}) + +add_executable(fuzz_x509crl fuzz_x509crl.c onefile.c) +target_link_libraries(fuzz_x509crl ${libs}) + +add_executable(fuzz_x509crt fuzz_x509crt.c onefile.c) +target_link_libraries(fuzz_x509crt ${libs}) + +add_executable(fuzz_privkey fuzz_privkey.c onefile.c) +target_link_libraries(fuzz_privkey ${libs}) + +add_executable(fuzz_pubkey fuzz_pubkey.c onefile.c) +target_link_libraries(fuzz_pubkey ${libs}) + +add_executable(fuzz_client fuzz_client.c onefile.c) +target_link_libraries(fuzz_client ${libs}) + +add_executable(fuzz_server fuzz_server.c onefile.c) +target_link_libraries(fuzz_server ${libs}) + +add_executable(fuzz_dtlsclient fuzz_dtlsclient.c onefile.c) +target_link_libraries(fuzz_dtlsclient ${libs}) + +add_executable(fuzz_dtlsserver fuzz_dtlsserver.c onefile.c) +target_link_libraries(fuzz_dtlsserver ${libs}) diff --git a/tests/fuzz/corpuses/client b/tests/fuzz/corpuses/client new file mode 100644 index 000000000..48d0a67c8 Binary files /dev/null and b/tests/fuzz/corpuses/client differ diff --git a/tests/fuzz/corpuses/dtlsclient b/tests/fuzz/corpuses/dtlsclient new file mode 100644 index 000000000..87c3ca333 Binary files /dev/null and b/tests/fuzz/corpuses/dtlsclient differ diff --git a/tests/fuzz/corpuses/dtlsserver b/tests/fuzz/corpuses/dtlsserver new file mode 100644 index 000000000..7a7a11790 Binary files /dev/null and b/tests/fuzz/corpuses/dtlsserver differ diff --git a/tests/fuzz/corpuses/server b/tests/fuzz/corpuses/server new file mode 100644 index 000000000..fbeb019f2 Binary files /dev/null and b/tests/fuzz/corpuses/server differ diff --git a/tests/fuzz/fuzz_client.c b/tests/fuzz/fuzz_client.c new file mode 100644 index 000000000..aee9946d9 --- /dev/null +++ b/tests/fuzz/fuzz_client.c @@ -0,0 +1,227 @@ +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include +#include +#include +#include + + +static bool initialized = 0; +#if defined(MBEDTLS_X509_CRT_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"; + + +typedef struct fuzzBufferOffset +{ + const uint8_t *Data; + size_t Size; + size_t Offset; +} fuzzBufferOffset_t; + +static 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 + return( len ); +} + +static 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 + biomemfuzz->Offset > biomemfuzz->Size) { + //do not overflow + len = biomemfuzz->Size - biomemfuzz->Offset; + } + memcpy(buf, biomemfuzz->Data + biomemfuzz->Offset, len); + biomemfuzz->Offset += len; + return( len ); +} + +static int dummy_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + size_t i; + + //use mbedtls_ctr_drbg_random to find bugs in it + ret = mbedtls_ctr_drbg_random(p_rng, output, output_len); + for (i=0; i +#include +#include +#include +#include "mbedtls/ssl.h" +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/timing.h" + + +static bool initialized = 0; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static mbedtls_x509_crt cacert; +#endif + + +const char *pers = "fuzz_dtlsclient"; + + +typedef struct fuzzBufferOffset +{ + const uint8_t *Data; + size_t Size; + size_t Offset; +} fuzzBufferOffset_t; + +static 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 + return( len ); +} + +static 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 + biomemfuzz->Offset > biomemfuzz->Size) { + //do not overflow + len = biomemfuzz->Size - biomemfuzz->Offset; + } + memcpy(buf, biomemfuzz->Data + biomemfuzz->Offset, len); + biomemfuzz->Offset += len; + return( len ); +} + +static int fuzz_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ) +{ + (void) timeout; + + return fuzz_recv(ctx, buf, len); +} + +static int dummy_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + size_t i; + + //use mbedtls_ctr_drbg_random to find bugs in it + ret = mbedtls_ctr_drbg_random(p_rng, output, output_len); + for (i=0; i +#include +#include +#include +#include "mbedtls/ssl.h" +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/timing.h" +#include "mbedtls/ssl_cookie.h" + + +const char *pers = "fuzz_dtlsserver"; +const unsigned char client_ip[4] = {0x7F, 0, 0, 1}; +static bool initialized = 0; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static mbedtls_x509_crt srvcert; +static mbedtls_pk_context pkey; +#endif + +typedef struct fuzzBufferOffset +{ + const uint8_t *Data; + size_t Size; + size_t Offset; +} fuzzBufferOffset_t; + + +static 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 + return( len ); +} + +static 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 + biomemfuzz->Offset > biomemfuzz->Size) { + //do not overflow + len = biomemfuzz->Size - biomemfuzz->Offset; + } + memcpy(buf, biomemfuzz->Data + biomemfuzz->Offset, len); + biomemfuzz->Offset += len; + return( len ); +} + +static int fuzz_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ) +{ + (void) timeout; + + return fuzz_recv(ctx, buf, len); +} + +static int dummy_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + size_t i; + + //use mbedtls_ctr_drbg_random to find bugs in it + ret = mbedtls_ctr_drbg_random(p_rng, output, output_len); + for (i=0; i +#include "mbedtls/pk.h" + +//4 Kb should be enough for every bug ;-) +#define MAX_LEN 0x1000 + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { +#ifdef MBEDTLS_PK_PARSE_C + int ret; + mbedtls_pk_context pk; + + if (Size > MAX_LEN) { + //only work on small inputs + Size = MAX_LEN; + } + + mbedtls_pk_init( &pk ); + ret = mbedtls_pk_parse_key( &pk, Data, Size, NULL, 0 ); + 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 ); + mbedtls_rsa_export( rsa, &N, &P, &Q, &D, &E ); + mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ); + + 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_ecp_keypair *ecp; + + ecp = mbedtls_pk_ec( pk ); + if (ecp) { + ret = 0; + } + } + else +#endif + { + ret = 0; + } + } + mbedtls_pk_free( &pk ); +#else + (void) Data; + (void) Size; +#endif //MBEDTLS_PK_PARSE_C + + return 0; +} diff --git a/tests/fuzz/fuzz_privkey.options b/tests/fuzz/fuzz_privkey.options new file mode 100644 index 000000000..0824b19fa --- /dev/null +++ b/tests/fuzz/fuzz_privkey.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/tests/fuzz/fuzz_pubkey.c b/tests/fuzz/fuzz_pubkey.c new file mode 100644 index 000000000..df42f7d53 --- /dev/null +++ b/tests/fuzz/fuzz_pubkey.c @@ -0,0 +1,57 @@ +#include +#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 ); + 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 ); + ret = mbedtls_rsa_export( rsa, &N, &P, &Q, &D, &E ); + ret = mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ); + + 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_ecp_keypair *ecp; + + ecp = mbedtls_pk_ec( pk ); + //dummy use of value + if (ecp) { + ret = 0; + } + } + else +#endif + { + ret = 0; + } + } + mbedtls_pk_free( &pk ); +#else + (void) Data; + (void) Size; +#endif //MBEDTLS_PK_PARSE_C + + return 0; +} diff --git a/tests/fuzz/fuzz_pubkey.options b/tests/fuzz/fuzz_pubkey.options new file mode 100644 index 000000000..0824b19fa --- /dev/null +++ b/tests/fuzz/fuzz_pubkey.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/tests/fuzz/fuzz_server.c b/tests/fuzz/fuzz_server.c new file mode 100644 index 000000000..5a9510dda --- /dev/null +++ b/tests/fuzz/fuzz_server.c @@ -0,0 +1,240 @@ +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/ssl_ticket.h" +#include +#include +#include +#include + + +const char *pers = "fuzz_server"; +static bool initialized = 0; +#if defined(MBEDTLS_X509_CRT_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 + + +typedef struct fuzzBufferOffset +{ + const uint8_t *Data; + size_t Size; + size_t Offset; +} fuzzBufferOffset_t; + + +static 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 + return( len ); +} + +static 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 + biomemfuzz->Offset > biomemfuzz->Size) { + //do not overflow + len = biomemfuzz->Size - biomemfuzz->Offset; + } + memcpy(buf, biomemfuzz->Data + biomemfuzz->Offset, len); + biomemfuzz->Offset += len; + return( len ); +} + +static int dummy_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + size_t i; + + //use mbedtls_ctr_drbg_random to find bugs in it + ret = mbedtls_ctr_drbg_random(p_rng, output, output_len); + for (i=0; i +#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 ); + ret = mbedtls_x509_crl_parse( &crl, Data, Size ); + if (ret == 0) { + ret = mbedtls_x509_crl_info( (char *) buf, sizeof( buf ) - 1, " ", &crl ); + } + mbedtls_x509_crl_free( &crl ); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/tests/fuzz/fuzz_x509crl.options b/tests/fuzz/fuzz_x509crl.options new file mode 100644 index 000000000..0824b19fa --- /dev/null +++ b/tests/fuzz/fuzz_x509crl.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/tests/fuzz/fuzz_x509crt.c b/tests/fuzz/fuzz_x509crt.c new file mode 100644 index 000000000..8f593a141 --- /dev/null +++ b/tests/fuzz/fuzz_x509crt.c @@ -0,0 +1,22 @@ +#include +#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 ); + ret = mbedtls_x509_crt_parse( &crt, Data, Size ); + if (ret == 0) { + ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", &crt ); + } + mbedtls_x509_crt_free( &crt ); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/tests/fuzz/fuzz_x509crt.options b/tests/fuzz/fuzz_x509crt.options new file mode 100644 index 000000000..0824b19fa --- /dev/null +++ b/tests/fuzz/fuzz_x509crt.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/tests/fuzz/fuzz_x509csr.c b/tests/fuzz/fuzz_x509csr.c new file mode 100644 index 000000000..3cf28a6fa --- /dev/null +++ b/tests/fuzz/fuzz_x509csr.c @@ -0,0 +1,22 @@ +#include +#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 ); + ret = mbedtls_x509_csr_parse( &csr, Data, Size ); + if (ret == 0) { + ret = mbedtls_x509_csr_info( (char *) buf, sizeof( buf ) - 1, " ", &csr ); + } + mbedtls_x509_csr_free( &csr ); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/tests/fuzz/fuzz_x509csr.options b/tests/fuzz/fuzz_x509csr.options new file mode 100644 index 000000000..0824b19fa --- /dev/null +++ b/tests/fuzz/fuzz_x509csr.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/tests/fuzz/onefile.c b/tests/fuzz/onefile.c new file mode 100644 index 000000000..caf3ca565 --- /dev/null +++ b/tests/fuzz/onefile.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +int main(int argc, char** argv) +{ + FILE * fp; + uint8_t *Data; + size_t Size; + + if (argc != 2) { + return 1; + } + //opens the file, get its size, and reads it into a buffer + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + return 2; + } + if (fseek(fp, 0L, SEEK_END) != 0) { + fclose(fp); + return 2; + } + Size = ftell(fp); + if (Size == (size_t) -1) { + fclose(fp); + return 2; + } + if (fseek(fp, 0L, SEEK_SET) != 0) { + fclose(fp); + return 2; + } + Data = malloc(Size); + if (Data == NULL) { + fclose(fp); + return 2; + } + if (fread(Data, Size, 1, fp) != 1) { + fclose(fp); + return 2; + } + + //lauch fuzzer + LLVMFuzzerTestOneInput(Data, Size); + fclose(fp); + return 0; +} +