Skip to content

Commit

Permalink
fuzz: extend fuzzing coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanNardi committed Oct 7, 2023
1 parent 8ca842e commit 86115a8
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
/fuzz/fuzz_dga
/fuzz/fuzz_ds_cmsketch
/fuzz/fuzz_gcrypt_light
/fuzz/fuzz_gcrypt_aes
/fuzz/fuzz_gcrypt_gcm
/fuzz/fuzz_ndpi_reader_payload_analyzer
/fuzz/fuzz_filecfg_protocols
/fuzz/fuzz_readerutils_workflow
Expand Down
19 changes: 19 additions & 0 deletions example/ndpiReader.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <float.h> /* FLT_EPSILON */
#ifdef WIN32
#include <winsock2.h> /* winsock.h is included automatically */
#include <windows.h>
Expand Down Expand Up @@ -407,6 +408,22 @@ static void ndpiCheckIPMatch(char *testChar) {

/********************** FUNCTIONS ********************* */

static double ndpi_flow_get_byte_count_entropy(const uint32_t byte_count[256],
unsigned int num_bytes)
{
int i;
double sum = 0.0;

for(i=0; i<256; i++) {
double tmp = (double) byte_count[i] / (double) num_bytes;

if(tmp > FLT_EPSILON) {
sum -= tmp * logf(tmp);
}
}
return(sum / log(2.0));
}

/**
* @brief Set main components necessary to the detection
*/
Expand All @@ -433,6 +450,8 @@ flowGetBDMeanandVariance(struct ndpi_flow_info* flow) {
* Sum up the byte_count array for outbound and inbound flows,
* if this flow is bidirectional
*/
/* TODO: we could probably use ndpi_data_* generic functions to simplify the code and
to get rid of `ndpi_flow_get_byte_count_entropy()` */
if (!flow->bidirectional) {
array = last_entropy->src2dst_byte_count;
num_bytes = last_entropy->src2dst_l4_bytes;
Expand Down
38 changes: 10 additions & 28 deletions example/reader_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,7 @@ void ndpi_payload_analyzer(struct ndpi_flow_info *flow,
for(j=min_pattern_len; j <= max_pattern_len; j++) {
if((i+j) < payload_len) {
if(ndpi_analyze_payload(flow, src_to_dst_direction, &payload[i], j, packet_id) == -1) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Avoid too much logging while fuzzing */
LOG(NDPI_LOG_ERROR, "Error ndpi_analyze_payload (allocation failure)\n");
#endif
}
}
}
Expand Down Expand Up @@ -462,8 +459,11 @@ struct ndpi_workflow* ndpi_workflow_init(const struct ndpi_workflow_prefs * pref
static NDPI_PROTOCOL_BITMASK debug_bitmask;
static int _debug_protocols_ok = 0;

/* On some fuzzers we don't want to use these memory allocators, but some custom ones */
#ifndef DISABLE_CUSTOM_ALLOCATOR_ON_READERUTILS
set_ndpi_malloc(ndpi_malloc_wrapper), set_ndpi_free(free_wrapper);
set_ndpi_flow_malloc(NULL), set_ndpi_flow_free(NULL);
#endif

/* TODO: just needed here to init ndpi ndpi_malloc wrapper */
module = ndpi_init_detection_module(init_prefs);
Expand Down Expand Up @@ -500,8 +500,14 @@ struct ndpi_workflow* ndpi_workflow_init(const struct ndpi_workflow_prefs * pref
if(_debug_protocols_ok)
ndpi_set_debug_bitmask(module, debug_bitmask);

if(do_init_flows_root)
if(do_init_flows_root) {
workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *));
if(!workflow->ndpi_flows_root) {
ndpi_exit_detection_module(module);
ndpi_free(workflow);
return NULL;
}
}

workflow->ndpi_serialization_format = serialization_format;

Expand Down Expand Up @@ -742,24 +748,6 @@ ndpi_flow_update_byte_dist_mean_var(ndpi_flow_info_t *flow, const void *x,

/* ***************************************************** */

double ndpi_flow_get_byte_count_entropy(const uint32_t byte_count[256],
unsigned int num_bytes)
{
int i;
double sum = 0.0;

for(i=0; i<256; i++) {
double tmp = (double) byte_count[i] / (double) num_bytes;

if(tmp > FLT_EPSILON) {
sum -= tmp * logf(tmp);
}
}
return(sum / log(2.0));
}

/* ***************************************************** */

static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow,
const u_int8_t version,
u_int16_t vlan_id,
Expand Down Expand Up @@ -908,10 +896,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow
struct ndpi_flow_info *newflow = (struct ndpi_flow_info*)ndpi_malloc(sizeof(struct ndpi_flow_info));

if(newflow == NULL) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Avoid too much logging while fuzzing */
LOG(NDPI_LOG_ERROR, "[NDPI] %s(1): not enough memory\n", __FUNCTION__);
#endif
return(NULL);
} else
workflow->num_allocated_flows++;
Expand Down Expand Up @@ -952,10 +937,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow
}

if((newflow->ndpi_flow = ndpi_flow_malloc(SIZEOF_FLOW_STRUCT)) == NULL) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Avoid too much logging while fuzzing */
LOG(NDPI_LOG_ERROR, "[NDPI] %s(2): not enough memory\n", __FUNCTION__);
#endif
ndpi_flow_info_free_data(newflow);
ndpi_free(newflow);
return(NULL);
Expand Down
3 changes: 1 addition & 2 deletions example/reader_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,12 +414,11 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl
void ndpi_flow_info_free_data(struct ndpi_flow_info *flow);
void ndpi_flow_info_freer(void *node);
const char* print_cipher_id(u_int32_t cipher);
double ndpi_flow_get_byte_count_entropy(const uint32_t byte_count[256], unsigned int num_bytes);
int parse_proto_name_list(char *str, NDPI_PROTOCOL_BITMASK *bitmask, int inverted_logic);

extern int nDPI_LogLevel;

#ifdef NDPI_ENABLE_DEBUG_MESSAGES
#if defined(NDPI_ENABLE_DEBUG_MESSAGES) && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
#define LOG(log_level, args...) \
{ \
if(log_level <= nDPI_LogLevel) \
Expand Down
36 changes: 33 additions & 3 deletions fuzz/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ bin_PROGRAMS += fuzz_ds_patricia fuzz_ds_ahocorasick fuzz_ds_libcache fuzz_ds_tr
#Third party
bin_PROGRAMS += fuzz_libinjection fuzz_binaryfusefilter
#Internal crypto
bin_PROGRAMS += fuzz_gcrypt_light
bin_PROGRAMS += fuzz_gcrypt_light fuzz_gcrypt_aes fuzz_gcrypt_gcm
#Configuration files
bin_PROGRAMS += fuzz_filecfg_protocols
#Reader utils
Expand Down Expand Up @@ -427,6 +427,36 @@ fuzz_gcrypt_light_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_gcrypt_light_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

fuzz_gcrypt_aes_SOURCES = fuzz_gcrypt_aes.cpp
fuzz_gcrypt_aes_CXXFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -I ../src/lib/third_party/include/
fuzz_gcrypt_aes_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -I ../src/lib/third_party/include/
fuzz_gcrypt_aes_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
fuzz_gcrypt_aes_LDFLAGS = $(LIBS)
if HAS_FUZZLDFLAGS
fuzz_gcrypt_aes_CXXFLAGS += $(LIB_FUZZING_ENGINE)
fuzz_gcrypt_aes_CFLAGS += $(LIB_FUZZING_ENGINE)
fuzz_gcrypt_aes_LDFLAGS += $(LIB_FUZZING_ENGINE)
endif
# force usage of CXX for linker
fuzz_gcrypt_aes_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_gcrypt_aes_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

fuzz_gcrypt_gcm_SOURCES = fuzz_gcrypt_gcm.cpp
fuzz_gcrypt_gcm_CXXFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -I ../src/lib/third_party/include/
fuzz_gcrypt_gcm_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -I ../src/lib/third_party/include/
fuzz_gcrypt_gcm_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
fuzz_gcrypt_gcm_LDFLAGS = $(LIBS)
if HAS_FUZZLDFLAGS
fuzz_gcrypt_gcm_CXXFLAGS += $(LIB_FUZZING_ENGINE)
fuzz_gcrypt_gcm_CFLAGS += $(LIB_FUZZING_ENGINE)
fuzz_gcrypt_gcm_LDFLAGS += $(LIB_FUZZING_ENGINE)
endif
# force usage of CXX for linker
fuzz_gcrypt_gcm_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_gcrypt_gcm_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

fuzz_filecfg_protocols_SOURCES = fuzz_filecfg_protocols.c fuzz_common_code.c
fuzz_filecfg_protocols_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
fuzz_filecfg_protocols_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
Expand All @@ -441,8 +471,8 @@ fuzz_filecfg_protocols_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(fuzz_filecfg_protocols_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@

fuzz_readerutils_workflow_SOURCES = fuzz_readerutils_workflow.cpp fuzz_common_code.c ../example/reader_util.c
fuzz_readerutils_workflow_CXXFLAGS = -I../example/ @NDPI_CFLAGS@ $(CXXFLAGS)
fuzz_readerutils_workflow_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
fuzz_readerutils_workflow_CXXFLAGS = -I../example/ @NDPI_CFLAGS@ $(CXXFLAGS) -DDISABLE_CUSTOM_ALLOCATOR_ON_READERUTILS
fuzz_readerutils_workflow_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -DDISABLE_CUSTOM_ALLOCATOR_ON_READERUTILS
fuzz_readerutils_workflow_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS)
fuzz_readerutils_workflow_LDFLAGS = $(PCAP_LIB) $(LIBS)
if HAS_FUZZLDFLAGS
Expand Down
4 changes: 3 additions & 1 deletion fuzz/fuzz_ds_domain_classify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
}

ndpi_domain_classify_add_domains(d, NDPI_PROTOCOL_UNKNOWN, "random_list.list");
ndpi_domain_classify_add_domains(d,
fuzzed_data.ConsumeIntegralInRange(0, NDPI_LAST_IMPLEMENTED_PROTOCOL - 1),
(char *)"random_list.list");

if (fuzzed_data.ConsumeBool())
ndpi_domain_classify_finalize(d);
Expand Down
62 changes: 62 additions & 0 deletions fuzz/fuzz_gcrypt_aes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <stdlib.h>
#include <stdint.h>
#include "fuzzer/FuzzedDataProvider.h"

#define MBEDTLS_CHECK_RETURN_TYPICAL
#include "../src/lib/third_party/include/gcrypt/aes.h"

extern int force_no_aesni;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
mbedtls_aes_context *ctx;
int key_lens[] = { 128, 192, 256, 512 /* invalid */ };
unsigned char *input, *output, *key;
int i, key_len, mode, rc;

/* No real memory allocations involved */

if(fuzzed_data.remaining_bytes() < 1 + 1 + 4 + 512 / 8 + 16)
return -1;

posix_memalign((void **)&input, 8, 16);
posix_memalign((void **)&output, 8, 16);
posix_memalign((void **)&key, 8, 512 / 8);
ctx = (mbedtls_aes_context *)malloc(sizeof(mbedtls_aes_context));

force_no_aesni = 0;
if(fuzzed_data.ConsumeBool())
force_no_aesni = 1;

mode = MBEDTLS_AES_ENCRYPT;
if(fuzzed_data.ConsumeBool())
mode = MBEDTLS_AES_DECRYPT;

mbedtls_aes_init(ctx);

key_len = fuzzed_data.PickValueInArray(key_lens);
std::vector<unsigned char>k = fuzzed_data.ConsumeBytes<u_int8_t>(key_len / 8);
std::vector<u_int8_t>in = fuzzed_data.ConsumeBytes<uint8_t>(16);

for(i = 0; i < 16; i++)
input[i] = in[i];
for(i = 0; i < key_len / 8; i++)
key[i] = k[i];

if(mode == MBEDTLS_AES_ENCRYPT)
rc = mbedtls_aes_setkey_enc(ctx, key, key_len);
else
rc = mbedtls_aes_setkey_dec(ctx, key, key_len);

if(rc == 0)
mbedtls_aes_crypt_ecb(ctx, mode, input, output);

mbedtls_aes_free(ctx);

free(ctx);
free(key);
free(input);
free(output);

return 0;
}
101 changes: 101 additions & 0 deletions fuzz/fuzz_gcrypt_gcm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "fuzzer/FuzzedDataProvider.h"

#define MBEDTLS_CHECK_RETURN_TYPICAL
#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 )
#include "../src/lib/third_party/include/gcrypt/aes.h"
#include "../src/lib/third_party/include/gcrypt/cipher.h"
#include "../src/lib/third_party/include/gcrypt/gcm.h"

extern int force_no_aesni;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
mbedtls_aes_context *aes_e_ctx, *aes_d_ctx;
mbedtls_gcm_context *gcm_e_ctx, *gcm_d_ctx;
int key_lens[] = { 128, 192, 256, 512 /* invalid */ };
unsigned char *output, *decrypted;
int key_len, rc_e, rc_d;
mbedtls_cipher_id_t cipher;
unsigned char *tag;
int iv_len, tag_len, input_length;

/* No real memory allocations involved */

if(fuzzed_data.remaining_bytes() < 1 + 4 + 512 / 8 +
1 + 64 + /* iv */
1 + /* tag_len */
1 + 64 + /* input */
1 /* useless data: to be able to add the check with assert */)
return -1;

gcm_e_ctx = (mbedtls_gcm_context *)malloc(sizeof(mbedtls_gcm_context));
gcm_d_ctx = (mbedtls_gcm_context *)malloc(sizeof(mbedtls_gcm_context));
aes_e_ctx = (mbedtls_aes_context *)malloc(sizeof(mbedtls_aes_context));
aes_d_ctx = (mbedtls_aes_context *)malloc(sizeof(mbedtls_aes_context));

/* Not sure if it is really necessary... */
force_no_aesni = 0;
if(fuzzed_data.ConsumeBool())
force_no_aesni = 1;

key_len = fuzzed_data.PickValueInArray(key_lens);
std::vector<unsigned char>key = fuzzed_data.ConsumeBytes<u_int8_t>(key_len / 8);

iv_len = fuzzed_data.ConsumeIntegralInRange(0, 64);
std::vector<u_int8_t>iv = fuzzed_data.ConsumeBytes<uint8_t>(iv_len);

tag_len = fuzzed_data.ConsumeIntegralInRange(0, 17);
tag = (unsigned char *)malloc(tag_len);

input_length = fuzzed_data.ConsumeIntegralInRange(16, 64);
std::vector<unsigned char>input = fuzzed_data.ConsumeBytes<u_int8_t>(input_length);
output = (unsigned char *)malloc(input_length);
decrypted = (unsigned char *)malloc(input_length);

cipher = static_cast<mbedtls_cipher_id_t>(fuzzed_data.ConsumeIntegralInRange(0, (int)MBEDTLS_CIPHER_ID_CHACHA20));

assert(fuzzed_data.remaining_bytes() > 0);

mbedtls_gcm_init(gcm_e_ctx, aes_e_ctx);
mbedtls_gcm_init(gcm_d_ctx, aes_d_ctx);

rc_e = mbedtls_gcm_setkey(gcm_e_ctx, cipher, key.data(), key.size() * 8);
rc_d = mbedtls_gcm_setkey(gcm_d_ctx, cipher, key.data(), key.size() * 8);

if (rc_e == 0 && rc_d == 0) {
rc_e = mbedtls_gcm_crypt_and_tag(gcm_e_ctx, MBEDTLS_GCM_ENCRYPT,
input.size(),
iv.data(), iv.size(),
NULL, 0, /* TODO */
input.data(),
output,
tag_len, tag);
if(rc_e == 0) {
rc_d = mbedtls_gcm_auth_decrypt(gcm_d_ctx,
input.size(),
iv.data(), iv.size(),
NULL, 0, /* TODO */
tag, tag_len,
output,
decrypted);
if (rc_d == 0)
assert(memcmp(input.data(), decrypted, input.size()) == 0);
}
}

mbedtls_gcm_free(gcm_e_ctx);
mbedtls_gcm_free(gcm_d_ctx);

free(tag);
free(gcm_e_ctx);
free(gcm_d_ctx);
free(aes_e_ctx);
free(aes_d_ctx);
free(output);
free(decrypted);

return 0;
}
Loading

0 comments on commit 86115a8

Please sign in to comment.