aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--fuzz/Makefile.am17
-rw-r--r--fuzz/fuzz_gcrypt_light.cpp124
-rw-r--r--src/lib/third_party/include/gcrypt_light.h8
-rw-r--r--src/lib/third_party/src/gcrypt_light.c27
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;
}