summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac14
-rw-r--r--devel/fuzz/README.md2
-rw-r--r--lib/handshake.c12
-rw-r--r--lib/nettle/Makefile.am4
-rw-r--r--lib/nettle/rnd-fuzzer.c142
-rw-r--r--lib/random.c11
-rw-r--r--lib/x509/common.h7
7 files changed, 189 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index bce0d9f7ab..4ae4c0bc4e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -248,6 +248,14 @@ AC_ARG_ENABLE(tests,
enable_tests=$enableval, enable_tests=$enable_tools)
AM_CONDITIONAL(ENABLE_TESTS, test "$enable_tests" != "no")
+AC_ARG_ENABLE(fuzzer-target,
+ AS_HELP_STRING([--enable-fuzzer-target], [make a library intended for testing - not production]),
+ enable_fuzzer_target=$enableval, enable_fuzzer_target=no)
+AM_CONDITIONAL(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION, test "$enable_fuzzer_target" != "no")
+if test "$enable_fuzzer_target" != "no";then
+ AC_DEFINE([FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION], 1, [Enable fuzzer target -not for production])
+fi
+
GTK_DOC_CHECK(1.1)
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.19])
@@ -1043,3 +1051,9 @@ AC_MSG_WARN([[
*** applications to link, do not enable static linking.
]])
fi
+
+if test "$enable_fuzzer_target" != "no";then
+AC_MSG_WARN([[
+*** This version of the library is for fuzzying purposes and is intentionally broken!
+]])
+fi
diff --git a/devel/fuzz/README.md b/devel/fuzz/README.md
index 575f80e091..0d94bbae15 100644
--- a/devel/fuzz/README.md
+++ b/devel/fuzz/README.md
@@ -18,7 +18,7 @@ using other projects like openssl.
Use the following commands on top dir:
```
-$ CC="afl-gcc" ./configure
+$ CC="afl-gcc" ./configure --enable-fuzzer-target
$ make -j$(nproc)
$ cd devel/fuzz
$ make gnutls_pkcs7_parser_fuzzer
diff --git a/lib/handshake.c b/lib/handshake.c
index 8dc3fa58ec..d0e3d497bd 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -186,9 +186,14 @@ static int create_tls_random(uint8_t * dst)
* system's time.
*/
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ /* When fuzzying avoid timing dependencies */
+ memset(dst, 1, 4);
+#else
tim = gnutls_time(NULL);
/* generate server random value */
_gnutls_write_uint32(tim, dst);
+#endif
ret =
gnutls_rnd(GNUTLS_RND_NONCE, &dst[3], GNUTLS_RANDOM_SIZE - 3);
@@ -793,11 +798,18 @@ static int _gnutls_recv_finished(gnutls_session_t session)
goto cleanup;
}
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ /* When fuzzying allow to proceed without verifying the handshake
+ * consistency */
+# warning This is unsafe for production builds
+
+#else
if (memcmp(vrfy, data, data_size) != 0) {
gnutls_assert();
ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
goto cleanup;
}
+#endif
ret = _gnutls_ext_sr_finished(session, data, data_size, 1);
if (ret < 0) {
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index 12d7f016ea..c7196ae307 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -53,6 +53,10 @@ libcrypto_la_SOURCES += sysrng-linux.c
endif
endif
+if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+libcrypto_la_SOURCES += rnd-fuzzer.c
+endif
+
if ENABLE_FIPS140
libcrypto_la_SOURCES += rnd-fips.c int/drbg-aes-self-test.c \
int/drbg-aes.c int/drbg-aes.h
diff --git a/lib/nettle/rnd-fuzzer.c b/lib/nettle/rnd-fuzzer.c
new file mode 100644
index 0000000000..b48601fabf
--- /dev/null
+++ b/lib/nettle/rnd-fuzzer.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ * Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
+ *
+ * This file is part of GnuTLS.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <drbg-aes.h>
+#include <fips.h>
+
+#include "gnutls_int.h"
+#include "errors.h"
+#include <stdlib.h>
+#include <rnd-common.h>
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+# error 1
+#endif
+
+struct r48_rand_data {
+ unsigned short int __x[3]; /* Current state. */
+ unsigned short int __old_x[3]; /* Old state. */
+ unsigned short int __c; /* Additive const. in congruential formula. */
+ unsigned short int __init; /* Flag for initializing. */
+ __extension__ unsigned long long int __a; /* Factor in congruential
+ formula. */
+};
+
+static int
+__r48_rand_iterate(unsigned short int xsubi[3], struct r48_rand_data *buffer)
+{
+ uint64_t X;
+ uint64_t result;
+
+ /* Initialize buffer, if not yet done. */
+ if (unlikely(!buffer->__init)) {
+ buffer->__a = 0x5deece66dull;
+ buffer->__c = 0xb;
+ buffer->__init = 1;
+ }
+
+ /* Do the real work. We choose a data type which contains at least
+ 48 bits. Because we compute the modulus it does not care how
+ many bits really are computed. */
+
+ X = (uint64_t) xsubi[2] << 32 | (uint32_t) xsubi[1] << 16 | xsubi[0];
+
+ result = X * buffer->__a + buffer->__c;
+
+ xsubi[0] = result & 0xffff;
+ xsubi[1] = (result >> 16) & 0xffff;
+ xsubi[2] = (result >> 32) & 0xffff;
+
+ return 0;
+}
+
+static int
+r48_r(unsigned short int xsubi[3], struct r48_rand_data *buffer,
+ long int *result)
+{
+ /* Compute next state. */
+ if (__r48_rand_iterate(xsubi, buffer) < 0)
+ return -1;
+
+ /* Store the result. */
+ *result = (int32_t) ((xsubi[2] << 16) | xsubi[1]);
+
+ return 0;
+}
+
+static int r48(struct r48_rand_data *buffer, long int *result)
+{
+ return r48_r(buffer->__x, buffer, result);
+}
+
+/* This is a dummy random generator intended to be reproducible
+ * for use in fuzzying targets.
+ */
+
+static int _rngfuzz_init(void **_ctx)
+{
+ *_ctx = calloc(1, sizeof(struct r48_rand_data));
+
+ return 0;
+}
+
+static int _rngfuzz_rnd(void *_ctx, int level, void *buffer, size_t length)
+{
+ struct r48_rand_data *ctx = _ctx;
+ uint8_t *p = buffer;
+ long r;
+ unsigned i;
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ for (i = 0; i < length; i++) {
+ r48(ctx, &r);
+ p[i] = r;
+ }
+ return 0;
+}
+
+static void _rngfuzz_deinit(void *_ctx)
+{
+ struct r48_rand_data *ctx = _ctx;
+
+ free(ctx);
+}
+
+static void _rngfuzz_refresh(void *_ctx)
+{
+ /* this is predictable RNG. Don't refresh */
+ return;
+}
+
+gnutls_crypto_rnd_st _gnutls_fuzz_rnd_ops = {
+ .init = _rngfuzz_init,
+ .deinit = _rngfuzz_deinit,
+ .rnd = _rngfuzz_rnd,
+ .rnd_refresh = _rngfuzz_refresh,
+ .self_test = NULL,
+};
diff --git a/lib/random.c b/lib/random.c
index 2fe82adc7d..0c05dbe187 100644
--- a/lib/random.c
+++ b/lib/random.c
@@ -37,6 +37,9 @@
# error Unsupported platform
#endif
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+extern gnutls_crypto_rnd_st _gnutls_fuzz_rnd_ops;
+#endif
/* Per thread context of random generator, and a flag to indicate initialization */
static _Thread_local void *gnutls_rnd_ctx;
@@ -100,7 +103,13 @@ int _gnutls_rnd_preinit(void)
{
int ret;
-#ifdef ENABLE_FIPS140
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+# warning Insecure PRNG is enabled
+ ret = gnutls_crypto_rnd_register(100, &_gnutls_fuzz_rnd_ops);
+ if (ret < 0)
+ return ret;
+
+#elif defined(ENABLE_FIPS140)
/* The FIPS140 random generator is only enabled when we are compiled
* with FIPS support, _and_ the system requires FIPS140.
*/
diff --git a/lib/x509/common.h b/lib/x509/common.h
index eafc7a515b..1a27666076 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -30,9 +30,14 @@
#include <fips.h>
#define MAX_STRING_LEN 512
+
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+# define MAX_ITER_COUNT 10*1024
+#else
/* Set a maximum iteration count over which we refuse to
* decode a file. That is to prevent DoS. */
-#define MAX_ITER_COUNT (10*1024*1024)
+# define MAX_ITER_COUNT (10*1024*1024)
+#endif
#define GNUTLS_XML_SHOW_ALL 1