diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | fuzz/Makefile.am | 17 | ||||
-rw-r--r-- | fuzz/fuzz_gcrypt_light.cpp | 124 | ||||
-rw-r--r-- | src/lib/third_party/include/gcrypt_light.h | 8 | ||||
-rw-r--r-- | src/lib/third_party/src/gcrypt_light.c | 27 |
5 files changed, 165 insertions, 12 deletions
diff --git a/.gitignore b/.gitignore index 847a6da77..1327386cd 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,7 @@ /fuzz/fuzz_ds_ahocorasick /fuzz/fuzz_libinjection /fuzz/fuzz_tls_certificate +/fuzz/fuzz_gcrypt_light /fuzz/fuzz_ndpi_reader_alloc_fail_seed_corpus.zip /fuzz/fuzz_ndpi_reader_seed_corpus.zip /fuzz/fuzz_quic_get_crypto_data_seed_corpus.zip diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index 08def2ff3..b283e6095 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am @@ -5,6 +5,8 @@ bin_PROGRAMS += fuzz_alg_bins fuzz_alg_hll fuzz_alg_hw_rsi_outliers_da fuzz_alg_ bin_PROGRAMS += fuzz_ds_patricia fuzz_ds_ahocorasick fuzz_ds_libcache fuzz_ds_tree fuzz_ds_ptree #Third party bin_PROGRAMS += fuzz_libinjection +#Internal crypto +bin_PROGRAMS += fuzz_gcrypt_light fuzz_process_packet_SOURCES = fuzz_process_packet.c fuzz_common_code.c fuzz_process_packet_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) @@ -305,6 +307,21 @@ fuzz_tls_certificate_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \ $(fuzz_tls_certificate_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@ +fuzz_gcrypt_light_SOURCES = fuzz_gcrypt_light.cpp fuzz_common_code.c +fuzz_gcrypt_light_CXXFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -I ../src/lib/third_party/include/ +fuzz_gcrypt_light_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -I ../src/lib/third_party/include/ +fuzz_gcrypt_light_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS) +fuzz_gcrypt_light_LDFLAGS = $(LIBS) +if HAS_FUZZLDFLAGS +fuzz_gcrypt_light_CXXFLAGS += $(LIB_FUZZING_ENGINE) +fuzz_gcrypt_light_CFLAGS += $(LIB_FUZZING_ENGINE) +fuzz_gcrypt_light_LDFLAGS += $(LIB_FUZZING_ENGINE) +endif +# force usage of CXX for linker +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 $@ + # required for Google oss-fuzz # see https://github.com/google/oss-fuzz/tree/master/projects/ndpi testpcaps := $(wildcard ../tests/pcap/*.pcap*) diff --git a/fuzz/fuzz_gcrypt_light.cpp b/fuzz/fuzz_gcrypt_light.cpp new file mode 100644 index 000000000..f75d38bee --- /dev/null +++ b/fuzz/fuzz_gcrypt_light.cpp @@ -0,0 +1,124 @@ +#include "fuzz_common_code.h" + +#include <stdint.h> +#include <stdio.h> +#include <assert.h> +#include "fuzzer/FuzzedDataProvider.h" + +#ifdef HAVE_LIBGCRYPT +#include "gcrypt.h" +#define HMAC_SHA256_DIGEST_SIZE 32 +#else +#include "../src/lib/third_party/include/gcrypt_light.h" +#endif + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + FuzzedDataProvider fuzzed_data(data, size); + gcry_md_hd_t hh; + gcry_cipher_hd_t h; + gcry_error_t rc; + int algo = 0, flags = 0, mode = 0; /* Invalid values */ + int key_len, iv_len, auth_len; + u_int8_t out[HMAC_SHA256_DIGEST_SIZE]; + char buf_err[16]; + void *enc_out; + + /* To allow memory allocation failures */ + fuzz_set_alloc_callbacks_and_seed(size); + + /* MD */ + + if(fuzzed_data.ConsumeBool()) + algo = GCRY_MD_SHA256; + if(fuzzed_data.ConsumeBool()) + flags = GCRY_MD_FLAG_HMAC; + key_len = fuzzed_data.ConsumeIntegralInRange(0, 65); /* Max valid key length is 64 */ + std::vector<u_int8_t>key = fuzzed_data.ConsumeBytes<u_int8_t>(key_len); + std::vector<u_int8_t>src = fuzzed_data.ConsumeBytes<uint8_t>(300); + + gcry_md_get_algo_dlen(algo); + rc = gcry_md_open(&hh, algo, flags); + if (rc == 0) { + gcry_md_reset(hh); + rc = gcry_md_setkey(hh, key.data(), key.size()); + if (rc == 0) { + if(fuzzed_data.ConsumeBool()) { /* To trigger MBEDTLS_ERR_MD_REKEY */ + rc = gcry_md_setkey(hh, key.data(), key.size()); + } else { + rc = gcry_md_write(hh, src.data(), src.size()); + if (rc == 0) { + memcpy(out, gcry_md_read(hh, 0), gcry_md_get_algo_dlen(algo)); + gcry_md_get_algo(hh); + } + } + } + gcry_md_close(hh); + } + gpg_strerror_r(rc, buf_err, sizeof(buf_err)); + + + /* Encryption */ + + /* ECB */ + + if(fuzzed_data.ConsumeBool()) + algo = GCRY_CIPHER_AES128; + if(fuzzed_data.ConsumeBool()) + flags = 1; /* Invalid value */ + if(fuzzed_data.ConsumeBool()) + mode = GCRY_CIPHER_MODE_ECB; + key_len = fuzzed_data.ConsumeIntegralInRange(16, 17); /* Only 16 is a valid key length */ + std::vector<u_int8_t>key2 = fuzzed_data.ConsumeBytes<u_int8_t>(key_len); + enc_out = ndpi_malloc(src.size()); + if (!enc_out) + return 0; + + rc = gcry_cipher_open(&h, algo, mode, flags); + if (rc == 0) { + rc = gcry_cipher_setkey(h, key2.data(), key2.size()); + if (rc == 0) { + if(fuzzed_data.ConsumeBool()) { /* To trigger MBEDTLS_ERR_CIPHER_BAD_KEY */ + rc = gcry_cipher_setkey(h, key2.data(), key2.size()); + } else { + rc = gcry_cipher_encrypt(h, enc_out, src.size(), src.data(), src.size()); + } + } + gcry_cipher_ctl(h, 0, NULL, 0); + gcry_cipher_close(h); + } + gpg_strerror_r(rc, buf_err, sizeof(buf_err)); + + /* GCM */ + + if(fuzzed_data.ConsumeBool()) + mode = GCRY_CIPHER_MODE_GCM; + iv_len = fuzzed_data.ConsumeIntegralInRange(12, 12); /* Only 12 is a valid key length */ + std::vector<u_int8_t>iv = fuzzed_data.ConsumeBytes<u_int8_t>(iv_len); + auth_len = fuzzed_data.ConsumeIntegralInRange(0, 257); /* 257 is an invalid value */ + std::vector<u_int8_t>auth = fuzzed_data.ConsumeBytes<u_int8_t>(auth_len); + + rc = gcry_cipher_open(&h, algo, mode, flags); + if (rc == 0) { + rc = gcry_cipher_setkey(h, key2.data(), key2.size()); + if (rc == 0) { + gcry_cipher_reset(h); + rc = gcry_cipher_setiv(h, iv.data(), iv.size()); + if (rc == 0) { + if(fuzzed_data.ConsumeBool()) { /* To trigger MBEDTLS_ERR_CIPHER_BAD_KEY */ + rc = gcry_cipher_setiv(h, iv.data(), iv.size()); + } else { + rc = gcry_cipher_authenticate(h, auth.data(), auth.size()); + if (rc == 0) { + rc = gcry_cipher_decrypt(h, enc_out, src.size(), src.data(), src.size()); + } + } + } + } + gcry_cipher_close(h); + } + gpg_strerror_r(rc, buf_err, sizeof(buf_err)); + + ndpi_free(enc_out); + + return 0; +} diff --git a/src/lib/third_party/include/gcrypt_light.h b/src/lib/third_party/include/gcrypt_light.h index 6d6a115ee..bbd664155 100644 --- a/src/lib/third_party/include/gcrypt_light.h +++ b/src/lib/third_party/include/gcrypt_light.h @@ -1,4 +1,8 @@ +#ifdef __cplusplus +extern "C" { +#endif + #ifndef GCRY_LIGHT_H #define GCRY_LIGHT_H @@ -84,4 +88,8 @@ size_t gcry_cipher_get_algo_keylen (int algo); #endif /* GCRY_LIGHT_H */ +#ifdef __cplusplus +} +#endif + /* vim: set ts=4 sw=4 et foldmethod=marker foldmarker={{{{,}}}}: */ diff --git a/src/lib/third_party/src/gcrypt_light.c b/src/lib/third_party/src/gcrypt_light.c index 10cb7cd39..512f67bb5 100644 --- a/src/lib/third_party/src/gcrypt_light.c +++ b/src/lib/third_party/src/gcrypt_light.c @@ -116,7 +116,7 @@ const char *gcry_check_version(void *unused) { gcry_error_t gcry_md_open(gcry_md_hd_t *h,int algo,int flags) { gcry_md_hd_t ctx; if(!(algo == GCRY_MD_SHA256 && flags == GCRY_MD_FLAG_HMAC)) return MBEDTLS_ERR_MD_NOT_SUPPORT; - ctx = ndpi_calloc(1,sizeof(struct gcry_md_hd)); + ctx = (gcry_md_hd_t)ndpi_calloc(1,sizeof(struct gcry_md_hd)); if(!ctx) return MBEDTLS_ERR_MD_ALLOC_FAILED; *h = ctx; return GPG_ERR_NO_ERROR; @@ -133,13 +133,15 @@ void gcry_md_reset(gcry_md_hd_t h) { gcry_error_t gcry_md_setkey(gcry_md_hd_t h,const uint8_t *key,size_t key_len) { if(h->key_len) return MBEDTLS_ERR_MD_REKEY; h->key_len = key_len <= sizeof(h->key) ? key_len : sizeof(h->key); - memcpy(h->key,key,h->key_len); + if(h->key_len > 0) + memcpy(h->key,key,h->key_len); return GPG_ERR_NO_ERROR; } gcry_error_t gcry_md_write(gcry_md_hd_t h,const uint8_t *data,size_t data_len) { if(h->data_len + data_len > GCRY_MD_BUFF_SIZE) return MBEDTLS_ERR_MD_DATA_TOO_BIG; - memcpy(&h->data_buf[h->data_len],data,data_len); + if(data_len > 0) + memcpy(&h->data_buf[h->data_len],data,data_len); h->data_len += data_len; return GPG_ERR_NO_ERROR; } @@ -178,7 +180,7 @@ size_t s_len = ROUND_SIZE8(sizeof(struct gcry_cipher_hd));; switch(mode) { case GCRY_CIPHER_MODE_ECB: - r = ndpi_calloc(1,s_len + sizeof(mbedtls_aes_context)); + r = (struct gcry_cipher_hd *)ndpi_calloc(1,s_len + sizeof(mbedtls_aes_context)); if(!r) return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; r->ctx.ecb = (mbedtls_aes_context *)(r+1); mbedtls_aes_init(r->ctx.ecb); @@ -188,7 +190,7 @@ size_t s_len = ROUND_SIZE8(sizeof(struct gcry_cipher_hd));; size_t aes_ctx_size = ROUND_SIZE8(sizeof( mbedtls_aes_context )); size_t gcm_ctx_size = ROUND_SIZE8(sizeof( mbedtls_gcm_context )); - r = ndpi_calloc(1,s_len + gcm_ctx_size + aes_ctx_size); + r = (struct gcry_cipher_hd *)ndpi_calloc(1,s_len + gcm_ctx_size + aes_ctx_size); if(!r) return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; r->ctx.gcm = (mbedtls_gcm_context *)(r+1); mbedtls_gcm_init(r->ctx.gcm,(void *)(((char *)(r+1)) + gcm_ctx_size)); @@ -250,10 +252,10 @@ gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t h, const void *key, size_t key if( keylen != gcry_cipher_get_algo_keylen(h->algo)) return MBEDTLS_ERR_CIPHER_BAD_KEY; switch(h->mode) { case GCRY_CIPHER_MODE_ECB: - r = mbedtls_aes_setkey_enc( h->ctx.ecb, key, keylen*8 ); + r = mbedtls_aes_setkey_enc( h->ctx.ecb, (const unsigned char *)key, keylen*8 ); break; case GCRY_CIPHER_MODE_GCM: - r = mbedtls_gcm_setkey( h->ctx.gcm, MBEDTLS_CIPHER_ID_AES, key, keylen*8 ); + r = mbedtls_gcm_setkey( h->ctx.gcm, MBEDTLS_CIPHER_ID_AES, (const unsigned char *)key, keylen*8 ); break; } if(!r) { @@ -285,7 +287,8 @@ gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t h, const void *abuf, siz if(abuflen > sizeof(h->auth)) return MBEDTLS_ERR_CIPHER_BAD_KEY; h->s_auth = 1; h->authlen = abuflen; - memcpy(h->auth,abuf,abuflen); + if(abuflen > 0) + memcpy(h->auth,abuf,abuflen); return 0; } return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; @@ -298,7 +301,7 @@ gcry_error_t gcry_cipher_checktag (gcry_cipher_hd_t h, const void *intag, size_t if(h->s_crypt_ok && h->taglen == taglen) { size_t i; int diff; - const uint8_t *ctag = intag; + const uint8_t *ctag = (const uint8_t *)intag; for( diff = 0, i = 0; i < taglen; i++ ) diff |= ctag[i] ^ h->tag[i]; if(!diff) return 0; @@ -326,7 +329,7 @@ static gcry_error_t _gcry_cipher_crypt (gcry_cipher_hd_t h, if(check_valid_algo_mode(h)) return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; if(!inlen && !outsize) return MBEDTLS_ERR_GCM_BAD_INPUT; if(!in && !inlen) { - src = ndpi_malloc(outsize); + src = (uint8_t *)ndpi_malloc(outsize); if(!src) return MBEDTLS_ERR_GCM_ALLOC_FAILED; srclen = outsize; memcpy(src,out,outsize); @@ -338,7 +341,7 @@ static gcry_error_t _gcry_cipher_crypt (gcry_cipher_hd_t h, if(!encrypt) return MBEDTLS_ERR_GCM_NOT_SUPPORT; if(!( h->s_key && !h->s_crypt_ok)) return MBEDTLS_ERR_AES_MISSING_KEY; rv = mbedtls_aes_crypt_ecb(h->ctx.ecb, MBEDTLS_AES_ENCRYPT, - src ? src:in, out); + src ? src:(const unsigned char *)in, (unsigned char *)out); break; case GCRY_CIPHER_MODE_GCM: if(encrypt) return MBEDTLS_ERR_GCM_NOT_SUPPORT; @@ -349,7 +352,7 @@ static gcry_error_t _gcry_cipher_crypt (gcry_cipher_hd_t h, src ? srclen:outsize, h->iv,h->ivlen, h->auth,h->authlen, - src ? src:in,out, + src ? src:(const unsigned char *)in, (unsigned char *)out, h->taglen, h->tag); break; } |