Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c0bed48 authored by Yifan Hong's avatar Yifan Hong Committed by Automerger Merge Worker
Browse files

Merge "binder: fuzz TLS transport." am: 7327be2f am: 17e9554a

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1835927

Change-Id: Ibc95e7532fa56888a7c707d9ce0018d3aaff6c43
parents e43b6d23 17e9554a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ std::unique_ptr<RpcTransportCtxFactory> makeFactoryTls() {
    auto cert = android::makeSelfSignedCert(pkey.get(), android::kCertValidSeconds);
    CHECK_NE(cert.get(), nullptr);

    auto verifier = std::make_shared<RpcCertificateVerifierNoOp>();
    auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(OK);
    auto auth = std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
    return RpcTransportCtxFactoryTls::make(verifier, std::move(auth));
}
+5 −1
Original line number Diff line number Diff line
@@ -80,7 +80,11 @@ private:
// A RpcCertificateVerifier that does not verify anything.
class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
public:
    status_t verify(const SSL*, uint8_t*) override { return OK; }
    RpcCertificateVerifierNoOp(status_t status) : mStatus(status) {}
    status_t verify(const SSL*, uint8_t*) override { return mStatus; }

private:
    status_t mStatus;
};

} // namespace android
+12 −1
Original line number Diff line number Diff line
@@ -19,12 +19,19 @@ cc_fuzz {
    srcs: [
        "main.cpp",
    ],
    // Not using libbinder_tls_shared_deps to use deterministic boringssl libraries.
    static_libs: [
        "libbase",
        "libcutils",
        "liblog",
        "libbinder_tls_static",
        "libbinder_tls_test_utils",
        "libssl_fuzz_unsafe",
        "libcrypto_fuzz_unsafe",
    ],
    cflags: [
        "-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE" // for RAND_reset_for_fuzzing
    ],

    target: {
        android: {
            shared_libs: [
@@ -39,4 +46,8 @@ cc_fuzz {
            ],
        },
    },
    data: [
        "server.crt",
        "server.key",
    ],
}
+15 −0
Original line number Diff line number Diff line
#!/bin/sh

# As explained in
#  https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca

openssl genrsa -des3 -passout pass:xxxx -out server.pass.key 2048
openssl rsa -passin pass:xxxx -in server.pass.key -out server.key
rm -f server.pass.key

openssl req \
    -subj "/" \
    -new -key server.key -out server.csr

openssl x509 -req -sha256 -days 99999 -in server.csr -signkey server.key -out server.crt
rm -f server.csr
+62 −2
Original line number Diff line number Diff line
@@ -13,13 +13,20 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <binder/Binder.h>
#include <binder/Parcel.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
#include <binder/RpcTlsTestUtils.h>
#include <binder/RpcTransport.h>
#include <binder/RpcTransportRaw.h>
#include <binder/RpcTransportTls.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>

#include <sys/resource.h>
#include <sys/un.h>
@@ -51,13 +58,66 @@ class SomeBinder : public BBinder {
    }
};

int passwordCallback(char* buf, int size, int /*rwflag*/, void* /*u*/) {
    constexpr const char pass[] = "xxxx"; // See create_certs.sh
    if (size <= 0) return 0;
    int numCopy = std::min<int>(size, sizeof(pass));
    (void)memcpy(buf, pass, numCopy);
    return numCopy;
}

struct ServerAuth {
    bssl::UniquePtr<EVP_PKEY> pkey;
    bssl::UniquePtr<X509> cert;
};

// Use pre-configured keys because runtime generated keys / certificates are not
// deterministic, and the algorithm is time consuming.
ServerAuth readServerKeyAndCert() {
    ServerAuth ret;

    auto keyPath = android::base::GetExecutableDirectory() + "/data/server.key";
    bssl::UniquePtr<BIO> keyBio(BIO_new_file(keyPath.c_str(), "r"));
    ret.pkey.reset(PEM_read_bio_PrivateKey(keyBio.get(), nullptr, passwordCallback, nullptr));
    CHECK_NE(ret.pkey.get(), nullptr);

    auto certPath = android::base::GetExecutableDirectory() + "/data/server.crt";
    bssl::UniquePtr<BIO> certBio(BIO_new_file(certPath.c_str(), "r"));
    ret.cert.reset(PEM_read_bio_X509(certBio.get(), nullptr, nullptr, nullptr));
    CHECK_NE(ret.cert.get(), nullptr);

    return ret;
}

std::unique_ptr<RpcAuth> createServerRpcAuth() {
    static auto sAuth = readServerKeyAndCert();

    CHECK(EVP_PKEY_up_ref(sAuth.pkey.get()));
    bssl::UniquePtr<EVP_PKEY> pkey(sAuth.pkey.get());
    CHECK(X509_up_ref(sAuth.cert.get()));
    bssl::UniquePtr<X509> cert(sAuth.cert.get());

    return std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
}

std::unique_ptr<RpcTransportCtxFactory> makeTransportCtxFactory(FuzzedDataProvider* provider) {
    bool isTls = provider->ConsumeBool();
    if (!isTls) {
        return RpcTransportCtxFactoryRaw::make();
    }
    status_t verifyStatus = provider->ConsumeIntegral<status_t>();
    auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(verifyStatus);
    return RpcTransportCtxFactoryTls::make(verifier, createServerRpcAuth());
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    if (size > 50000) return 0;
    FuzzedDataProvider provider(data, size);
    RAND_reset_for_fuzzing();

    unlink(kSock.c_str());

    sp<RpcServer> server = RpcServer::make();
    sp<RpcServer> server = RpcServer::make(makeTransportCtxFactory(&provider));
    server->setRootObject(sp<SomeBinder>::make());
    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
    CHECK_EQ(OK, server->setupUnixDomainServer(kSock.c_str()));
Loading