[llvm] r282892 - [libFuzzer] add a fuzzer test that finds CVE-2015-3193

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 30 11:16:16 PDT 2016


Author: kcc
Date: Fri Sep 30 13:16:16 2016
New Revision: 282892

URL: http://llvm.org/viewvc/llvm-project?rev=282892&view=rev
Log:
[libFuzzer] add a fuzzer test that finds CVE-2015-3193

Added:
    llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/
    llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh   (with props)
    llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc
    llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh   (with props)

Added: llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh?rev=282892&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh (added)
+++ llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh Fri Sep 30 13:16:16 2016
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+[ -e $(basename $0) ] && echo "PLEASE USE THIS SCRIPT FROM ANOTHER DIR" && exit 1
+SCRIPT_DIR=$(dirname $0)
+EXECUTABLE_NAME_BASE=$(basename $SCRIPT_DIR)
+LIBFUZZER_SRC=$(dirname $(dirname $SCRIPT_DIR))
+JOBS=20
+
+# FUZZ_CXXFLAGS=" -g -fsanitize=address -fsanitize-coverage=edge"
+FUZZ_CXXFLAGS=" -g -fsanitize=address -fsanitize-coverage=trace-pc-guard,trace-cmp,trace-div,trace-gep"
+
+get() {
+  [ ! -e SRC ] && git clone https://github.com/openssl/openssl.git SRC && (cd SRC && git checkout OpenSSL_1_0_2d)
+#  [ ! -e SRC ] && wget https://www.openssl.org/source/openssl-1.0.1f.tar.gz && tar xf openssl-1.0.1f.tar.gz && mv openssl-1.0.1f SRC
+}
+build_lib() {
+  rm -rf BUILD
+  cp -rf SRC BUILD
+  (cd BUILD && ./config && make clean && make CC="clang $FUZZ_CXXFLAGS"  -j $JOBS)
+}
+
+get
+build_lib
+$LIBFUZZER_SRC/build.sh
+echo clang++ -g $SCRIPT_DIR/target.cc -DCERT_PATH=\"$SCRIPT_DIR/\"  $FUZZ_CXXFLAGS BUILD/libssl.a BUILD/libcrypto.a libFuzzer.a -lgcrypt -o $EXECUTABLE_NAME_BASE

Propchange: llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh
------------------------------------------------------------------------------
    svn:executable = *

Added: llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc?rev=282892&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc (added)
+++ llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc Fri Sep 30 13:16:16 2016
@@ -0,0 +1,149 @@
+// Find CVE-2015-3193. Derived from
+// https://github.com/hannob/bignum-fuzz/blob/master/CVE-2015-3193-openssl-vs-gcrypt-modexp.c
+/* Fuzz-compare the OpenSSL function BN_mod_exp() and the libgcrypt function gcry_mpi_powm().
+ *
+ * To use this you should compile both libgcrypt and openssl with american fuzzy lop and then statically link everything together, e.g.:
+ * afl-clang-fast -o [output] [input] libgcrypt.a libcrypto.a -lgpg-error
+ *
+ * Input is a binary file, the first bytes will decide how the rest of the file will be split into three bignums.
+ *
+ * by Hanno Böck, license CC0 (public domain)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <openssl/bn.h>
+#include <gcrypt.h>
+
+#define MAXBUF 1000000
+
+
+struct big_results {
+	char *name;
+	char *a;
+	char *b;
+	char *c;
+	char *exptmod;
+};
+
+void printres(struct big_results *res) {
+	printf("\n%s:\n", res->name);
+	printf("a: %s\n", res->a);
+	printf("b: %s\n", res->b);
+	printf("c: %s\n", res->c);
+	printf("b^c mod a: %s\n", res->exptmod);
+}
+
+void freeres(struct big_results *res) {
+	free(res->a);
+	free(res->b);
+	free(res->c);
+	free(res->exptmod);
+}
+
+
+char *gcrytostring(gcry_mpi_t in) {
+	char *a, *b;
+	size_t i;
+	size_t j=0;
+	gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char**) &a, &i, in);
+	while(a[j]=='0' && j<(i-2)) j++;
+	if ((j%2)==1) j--;
+	if (strncmp(&a[j],"00",2)==0) j++;
+	b=(char*)malloc(i-j);
+	strcpy(b, &a[j]);
+	free(a);
+	return b;
+}
+
+/* test gcry functions from libgcrypt */
+void gcrytest(unsigned char* a_raw, int a_len, unsigned char* b_raw, int b_len, unsigned char* c_raw, int c_len, struct big_results *res) {
+	gcry_mpi_t a, b, c, res1, res2;
+
+	/* unknown leak here */
+	gcry_mpi_scan(&a, GCRYMPI_FMT_USG, a_raw, a_len, NULL);
+	res->a = gcrytostring(a);
+
+	gcry_mpi_scan(&b, GCRYMPI_FMT_USG, b_raw, b_len, NULL);
+	res->b = gcrytostring(b);
+
+	gcry_mpi_scan(&c, GCRYMPI_FMT_USG, c_raw, c_len, NULL);
+	res->c = gcrytostring(c);
+
+	res1=gcry_mpi_new(0);
+
+	gcry_mpi_powm(res1, b, c, a);
+	res->exptmod=gcrytostring(res1);
+
+	gcry_mpi_release(a);
+	gcry_mpi_release(b);
+	gcry_mpi_release(c);
+	gcry_mpi_release(res1);
+}
+
+/* test bn functions from openssl/libcrypto */
+void bntest(unsigned char* a_raw, int a_len, unsigned char* b_raw, int b_len, unsigned char* c_raw, int c_len, struct big_results *res) {
+	BN_CTX *bctx = BN_CTX_new();
+	BIGNUM *a = BN_new();
+	BIGNUM *b = BN_new();
+	BIGNUM *c = BN_new();
+	BIGNUM *res1 = BN_new();
+
+	BN_bin2bn(a_raw, a_len, a);
+	BN_bin2bn(b_raw, b_len, b);
+	BN_bin2bn(c_raw, c_len, c);
+
+	res->a = BN_bn2hex(a);
+	res->b = BN_bn2hex(b);
+	res->c = BN_bn2hex(c);
+
+	BN_mod_exp(res1, b, c, a, bctx);
+	res->exptmod = BN_bn2hex(res1);
+
+	BN_free(a);
+	BN_free(b);
+	BN_free(c);
+	BN_free(res1);
+	BN_CTX_free(bctx);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size) {
+	size_t len, l1, l2,l3;
+	unsigned int divi1, divi2;
+	unsigned char *a, *b, *c;
+	struct big_results openssl_results= {"openssl",0,0,0,0};
+	struct big_results gcrypt_results= {"libgcrypt",0,0,0,0};
+
+        len = Size;
+	if (len<5) return 0;
+
+	divi1=Data[0];
+	divi2=Data[1];
+	divi1++;divi2++;
+	l1 = (len-2)*divi1/256;
+	l2 = (len-2-l1)*divi2/256;
+	l3 = (len-2-l1-l2);
+	assert(l1+l2+l3==len-2);
+	//printf("div1 div2 %i %i\n", divi1, divi2);
+	//printf("len l1 l2 l3 %i %i %i %i\n", (int)len,(int)l1,(int)l2,(int)l3);
+	a=const_cast<unsigned char*>(Data)+2;
+	b=const_cast<unsigned char*>(Data)+2+l1;
+	c=const_cast<unsigned char*>(Data)+2+l1+l2;
+
+
+	bntest(a, l1, b, l2, c, l3, &openssl_results);
+	//printres(&openssl_results);
+	if ((strcmp(openssl_results.a,"0")==0) || (strcmp(openssl_results.c,"0")==0)) goto END;
+
+	gcrytest(a, l1, b, l2, c, l3, &gcrypt_results);
+	//printres(&gcrypt_results);
+
+	assert(strcmp(openssl_results.exptmod, gcrypt_results.exptmod)==0);
+
+END:
+	freeres(&openssl_results);
+	freeres(&gcrypt_results);
+	return 0;
+}

Added: llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh?rev=282892&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh (added)
+++ llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh Fri Sep 30 13:16:16 2016
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -x
+SCRIPT_DIR=$(dirname $0)
+EXECUTABLE_NAME_BASE=$(basename $SCRIPT_DIR)
+CORPUS=CORPUS-$EXECUTABLE_NAME_BASE
+JOBS=8
+rm -rf $CORPUS
+mkdir $CORPUS
+[ -e $EXECUTABLE_NAME_BASE ] && ./$EXECUTABLE_NAME_BASE -artifact_prefix=$CORPUS/ -max_len=512  -jobs=$JOBS -workers=$JOBS $CORPUS
+grep 'Assertion `strcmp(openssl_results.exptmod, gcrypt_results.exptmod)==0. failed.' fuzz-0.log

Propchange: llvm/trunk/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh
------------------------------------------------------------------------------
    svn:executable = *




More information about the llvm-commits mailing list