From e15b72d833dd5c30f4cd4aed2ba06e64011ce73d Mon Sep 17 00:00:00 2001 From: Danny Halawi Date: Tue, 4 Aug 2020 16:52:53 -0700 Subject: [PATCH] [boringssl] Structure Aware ASN.1 Fuzzing in BoringSSL (#4179) * using asn.1 structure aware fuzzer to fuzz boringssl * incorporating feedback * changing fuzzer output name * updating build script * formatted files * pulling from google/fuzzing * uncommenting build * removing certs --- projects/boringssl/Dockerfile | 11 +++++-- projects/boringssl/build.sh | 24 ++++++++++++++- projects/boringssl/fuzz_certs.cc | 46 ++++++++++++++++++++++++++++ projects/boringssl/fuzz_pkcs12.cc | 41 +++++++++++++++++++++++++ projects/boringssl/fuzz_pkcs8.cc | 51 +++++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 projects/boringssl/fuzz_certs.cc create mode 100644 projects/boringssl/fuzz_pkcs12.cc create mode 100644 projects/boringssl/fuzz_pkcs8.cc diff --git a/projects/boringssl/Dockerfile b/projects/boringssl/Dockerfile index a36c811f0..33cc1c2d1 100644 --- a/projects/boringssl/Dockerfile +++ b/projects/boringssl/Dockerfile @@ -15,7 +15,12 @@ ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder -RUN apt-get update && apt-get install -y cmake ninja-build golang - +RUN apt-get update && apt-get install -y wget \ + golang binutils cmake ninja-build liblzma-dev libz-dev \ + pkg-config autoconf libtool RUN git clone --depth 1 https://boringssl.googlesource.com/boringssl -COPY build.sh $SRC/ +# Use ASN.1 pdu protobuf and converter from the google/fuzzing repo. +RUN git clone --depth 1 https://github.com/google/fuzzing.git +RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git +RUN (mkdir LPM && cd LPM && cmake ../libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release && ninja) +COPY *.cc build.sh $SRC/ \ No newline at end of file diff --git a/projects/boringssl/build.sh b/projects/boringssl/build.sh index 26d9330fc..ca252ba54 100755 --- a/projects/boringssl/build.sh +++ b/projects/boringssl/build.sh @@ -32,7 +32,6 @@ cmake -GNinja -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX \ $CMAKE_DEFINES $SRC/boringssl/ ninja - fuzzerFiles=$(find $SRC/boringssl/fuzz/ -name "*.cc") find . -name "*.a" @@ -48,3 +47,26 @@ for F in $fuzzerFiles; do zip -j $OUT/${fuzzerName}_seed_corpus.zip $SRC/boringssl/fuzz/${fuzzerName}_corpus/* fi done + +if [[ $CFLAGS != *sanitize=memory* ]]; then + fuzzerLPMFiles=$(find $SRC/ -maxdepth 1 -name "*.cc") + + cp $SRC/fuzzing/proto/asn1-pdu/* $SRC/ + + rm -rf genfiles && mkdir genfiles && $SRC/LPM/external.protobuf/bin/protoc asn1_pdu.proto --cpp_out=genfiles --proto_path=$SRC/ + + for F in $fuzzerLPMFiles + do + fuzzerName=$(echo ${F#*_}) + fuzzerName=$(basename $fuzzerName .cc) + echo "Building fuzzer $fuzzerName" + $CXX $CXXFLAGS -I genfiles -I . -I $SRC/libprotobuf-mutator/ -I $SRC/LPM/external.protobuf/include -I include $LIB_FUZZING_ENGINE \ + -I $SRC/boringssl/include \ + $F genfiles/asn1_pdu.pb.cc $SRC/asn1_pdu_to_der.cc \ + ./ssl/libssl.a ./crypto/libcrypto.a \ + $SRC/LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a \ + $SRC/LPM/src/libprotobuf-mutator.a \ + $SRC/LPM/external.protobuf/lib/libprotobuf.a \ + -o $OUT/"${fuzzerName}_lpm" + done +fi \ No newline at end of file diff --git a/projects/boringssl/fuzz_certs.cc b/projects/boringssl/fuzz_certs.cc new file mode 100644 index 000000000..d8d2a24e4 --- /dev/null +++ b/projects/boringssl/fuzz_certs.cc @@ -0,0 +1,46 @@ +// Copyright 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +// This fuzz target fuzzes the same API as +// https://github.com/google/boringssl/blob/master/fuzz/cert.cc, but it employs +// libprotobuf-mutator for structure-aware fuzzing. + +#include +#include +#include +#include "asn1_pdu.pb.h" +#include "asn1_pdu_to_der.h" +#include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" + +DEFINE_PROTO_FUZZER(const asn1_pdu::PDU& asn1) { + asn1_pdu::ASN1PDUToDER converter; + std::vector encoded = converter.PDUToDER(asn1); + const uint8_t* buf = encoded.data(); + size_t len = encoded.size(); + + X509* x509 = d2i_X509(NULL, &buf, len); + if (x509 != NULL) { + // Extract the public key. + EVP_PKEY_free(X509_get_pubkey(x509)); + + // Reserialize the structure. + uint8_t* der = NULL; + i2d_X509(x509, &der); + OPENSSL_free(der); + } + X509_free(x509); + ERR_clear_error(); +} \ No newline at end of file diff --git a/projects/boringssl/fuzz_pkcs12.cc b/projects/boringssl/fuzz_pkcs12.cc new file mode 100644 index 000000000..11cded4d2 --- /dev/null +++ b/projects/boringssl/fuzz_pkcs12.cc @@ -0,0 +1,41 @@ +// Copyright 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +// This fuzz target fuzzes the same API as +// https://github.com/google/boringssl/blob/master/fuzz/pkcs12.cc, but it +// employs libprotobuf-mutator for structure-aware fuzzing. + +#include +#include +#include +#include +#include "asn1_pdu.pb.h" +#include "asn1_pdu_to_der.h" +#include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" + +DEFINE_PROTO_FUZZER(const asn1_pdu::PDU& asn1) { + asn1_pdu::ASN1PDUToDER converter; + std::vector encoded = converter.PDUToDER(asn1); + const uint8_t* buf = encoded.data(); + size_t len = encoded.size(); + + bssl::UniquePtr certs(sk_X509_new_null()); + EVP_PKEY* key = nullptr; + CBS cbs; + CBS_init(&cbs, buf, len); + PKCS12_get_key_and_certs(&key, certs.get(), &cbs, "foo"); + EVP_PKEY_free(key); +} \ No newline at end of file diff --git a/projects/boringssl/fuzz_pkcs8.cc b/projects/boringssl/fuzz_pkcs8.cc new file mode 100644 index 000000000..a657d8bc2 --- /dev/null +++ b/projects/boringssl/fuzz_pkcs8.cc @@ -0,0 +1,51 @@ +// Copyright 2020 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +// This fuzz target fuzzes the same API as +// https://github.com/google/boringssl/blob/master/fuzz/pkcs8.cc, but it employs +// libprotobuf-mutator for structure-aware fuzzing. + +#include +#include +#include +#include +#include "asn1_pdu.pb.h" +#include "asn1_pdu_to_der.h" +#include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" + +DEFINE_PROTO_FUZZER(const asn1_pdu::PDU& asn1) { + asn1_pdu::ASN1PDUToDER converter; + std::vector encoded = converter.PDUToDER(asn1); + const uint8_t* buf = encoded.data(); + size_t len = encoded.size(); + + CBS cbs; + CBS_init(&cbs, buf, len); + bssl::UniquePtr pkey(EVP_parse_private_key(&cbs)); + if (pkey == NULL) { + return; + } + + uint8_t* der; + size_t der_len; + bssl::ScopedCBB cbb; + if (CBB_init(cbb.get(), 0) && + EVP_marshal_private_key(cbb.get(), pkey.get()) && + CBB_finish(cbb.get(), &der, &der_len)) { + OPENSSL_free(der); + } + ERR_clear_error(); +} \ No newline at end of file