From: Kostya Serebryany Date: Fri, 30 Sep 2016 18:16:16 +0000 (+0000) Subject: [libFuzzer] add a fuzzer test that finds CVE-2015-3193 X-Git-Tag: llvmorg-4.0.0-rc1~8467 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cfa31b6307d2d2ecb0a9c9c3b81c0305531ffadd;p=platform%2Fupstream%2Fllvm.git [libFuzzer] add a fuzzer test that finds CVE-2015-3193 llvm-svn: 282892 --- diff --git a/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh b/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh new file mode 100755 index 0000000..e60818b --- /dev/null +++ b/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/build.sh @@ -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 diff --git a/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc b/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc new file mode 100644 index 0000000..9528e4e --- /dev/null +++ b/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/target.cc @@ -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 +#include +#include +#include +#include +#include + +#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(Data)+2; + b=const_cast(Data)+2+l1; + c=const_cast(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; +} diff --git a/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh b/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh new file mode 100755 index 0000000..e528b04 --- /dev/null +++ b/llvm/lib/Fuzzer/fuzzer-test-suite/openssl-1.0.2d/test.sh @@ -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