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

Commit 3b41a5b4 authored by Pawan Wagh's avatar Pawan Wagh Committed by Gerrit Code Review
Browse files

Merge changes from topic "fuzz_gatekeeperd"

* changes:
  Adding fuzzer for gatekeeperd
  Separating GateKeeperProxy declaration in header
parents ab4723f8 c4bd2afc
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -18,8 +18,8 @@ package {
    default_applicable_licenses: ["Android-Apache-2.0"],
}

cc_binary {
    name: "gatekeeperd",
cc_defaults {
    name: "gatekeeperd_defaults",
    cflags: [
        "-Wall",
        "-Wextra",
@@ -52,6 +52,16 @@ cc_binary {

    static_libs: ["libscrypt_static"],
    include_dirs: ["external/scrypt/lib/crypto"],
}

cc_binary {
    name: "gatekeeperd",
    defaults: [
        "gatekeeperd_defaults",
    ],
    srcs: [
        "main.cpp",
    ],
    init_rc: ["gatekeeperd.rc"],
}

@@ -88,3 +98,20 @@ cc_library_shared {
        "libbinder",
    ],
}

cc_fuzz {
    name: "gatekeeperd_service_fuzzer",
    defaults: [
        "gatekeeperd_defaults",
        "service_fuzzer_defaults"
    ],
    srcs: [
        "fuzzer/GateKeeperServiceFuzzer.cpp",
    ],
    fuzz_config: {
        cc: [
            "subrahmanyaman@google.com",
            "swillden@google.com",
        ],
    },
}
 No newline at end of file
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * 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.
 */

#include <fuzzbinder/libbinder_driver.h>

#include "gatekeeperd.h"

using android::fuzzService;
using android::GateKeeperProxy;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    auto gatekeeperService = new GateKeeperProxy();
    fuzzService(gatekeeperService, FuzzedDataProvider(data, size));
    return 0;
}
 No newline at end of file
+297 −350
Original line number Diff line number Diff line
@@ -13,11 +13,9 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "gatekeeperd"

#include <android/service/gatekeeper/BnGateKeeperService.h>
#include <gatekeeper/GateKeeperResponse.h>
#include "gatekeeperd.h"

#include <endian.h>
#include <errno.h>
@@ -39,25 +37,18 @@
#include <log/log.h>
#include <utils/String16.h>

#include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
#include <aidl/android/security/authorization/IKeystoreAuthorization.h>
#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
#include <hidl/HidlSupport.h>

using android::sp;
using android::hardware::Return;
using android::hardware::gatekeeper::V1_0::GatekeeperResponse;
using android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
using android::hardware::gatekeeper::V1_0::IGatekeeper;

using AidlGatekeeperEnrollResp = aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
using AidlGatekeeperVerifyResp = aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
using AidlIGatekeeper = aidl::android::hardware::gatekeeper::IGatekeeper;

using ::android::binder::Status;
using ::android::service::gatekeeper::BnGateKeeperService;
using GKResponse = ::android::service::gatekeeper::GateKeeperResponse;
using GKResponseCode = ::android::service::gatekeeper::ResponseCode;
using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
@@ -70,9 +61,7 @@ static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SE
static const String16 DUMP_PERMISSION("android.permission.DUMP");
constexpr const char gatekeeperServiceName[] = "android.hardware.gatekeeper.IGatekeeper/default";

class GateKeeperProxy : public BnGateKeeperService {
  public:
    GateKeeperProxy() {
GateKeeperProxy::GateKeeperProxy() {
    clear_state_if_needed_done = false;
    hw_device = IGatekeeper::getService();
    ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(gatekeeperServiceName));
@@ -84,9 +73,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    }
}

    virtual ~GateKeeperProxy() {}

    void store_sid(uint32_t userId, uint64_t sid) {
void GateKeeperProxy::store_sid(uint32_t userId, uint64_t sid) {
    char filename[21];
    snprintf(filename, sizeof(filename), "%u", userId);
    int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
@@ -98,7 +85,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    close(fd);
}

    void clear_state_if_needed() {
void GateKeeperProxy::clear_state_if_needed() {
    if (clear_state_if_needed_done) {
        return;
    }
@@ -115,7 +102,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    clear_state_if_needed_done = true;
}

    bool mark_cold_boot() {
bool GateKeeperProxy::mark_cold_boot() {
    const char* filename = ".coldboot";
    if (access(filename, F_OK) == -1) {
        int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
@@ -129,7 +116,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    return false;
}

    void maybe_store_sid(uint32_t userId, uint64_t sid) {
void GateKeeperProxy::maybe_store_sid(uint32_t userId, uint64_t sid) {
    char filename[21];
    snprintf(filename, sizeof(filename), "%u", userId);
    if (access(filename, F_OK) == -1) {
@@ -137,7 +124,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    }
}

    uint64_t read_sid(uint32_t userId) {
uint64_t GateKeeperProxy::read_sid(uint32_t userId) {
    char filename[21];
    uint64_t sid;
    snprintf(filename, sizeof(filename), "%u", userId);
@@ -148,7 +135,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    return sid;
}

    void clear_sid(uint32_t userId) {
void GateKeeperProxy::clear_sid(uint32_t userId) {
    char filename[21];
    snprintf(filename, sizeof(filename), "%u", userId);
    if (remove(filename) < 0 && errno != ENOENT) {
@@ -157,9 +144,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    }
}

    // This should only be called on userIds being passed to the GateKeeper HAL. It ensures that
    // secure storage shared across a GSI image and a host image will not overlap.
    uint32_t adjust_userId(uint32_t userId) {
uint32_t GateKeeperProxy::adjust_userId(uint32_t userId) {
    static constexpr uint32_t kGsiOffset = 1000000;
    CHECK(userId < kGsiOffset);
    CHECK((aidl_hw_device != nullptr) || (hw_device != nullptr));
@@ -171,9 +156,11 @@ class GateKeeperProxy : public BnGateKeeperService {

#define GK_ERROR *gkResponse = GKResponse::error(), Status::ok()

    Status enroll(int32_t userId, const std::optional<std::vector<uint8_t>>& currentPasswordHandle,
Status GateKeeperProxy::enroll(int32_t userId,
                               const std::optional<std::vector<uint8_t>>& currentPasswordHandle,
                               const std::optional<std::vector<uint8_t>>& currentPassword,
                  const std::vector<uint8_t>& desiredPassword, GKResponse* gkResponse) override {
                               const std::vector<uint8_t>& desiredPassword,
                               GKResponse* gkResponse) {
    IPCThreadState* ipc = IPCThreadState::self();
    const int calling_pid = ipc->getCallingPid();
    const int calling_uid = ipc->getCallingUid();
@@ -227,8 +214,7 @@ class GateKeeperProxy : public BnGateKeeperService {
        if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
            *gkResponse = GKResponse::ok({rsp.data.begin(), rsp.data.end()});
            secureUserId = static_cast<uint64_t>(rsp.secureUserId);
            } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT &&
                       rsp.timeoutMs > 0) {
        } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT && rsp.timeoutMs > 0) {
            *gkResponse = GKResponse::retry(rsp.timeoutMs);
        } else {
            *gkResponse = GKResponse::error();
@@ -280,16 +266,17 @@ class GateKeeperProxy : public BnGateKeeperService {
    return Status::ok();
}

    Status verify(int32_t userId, const ::std::vector<uint8_t>& enrolledPasswordHandle,
                  const ::std::vector<uint8_t>& providedPassword, GKResponse* gkResponse) override {
Status GateKeeperProxy::verify(int32_t userId, const ::std::vector<uint8_t>& enrolledPasswordHandle,
                               const ::std::vector<uint8_t>& providedPassword,
                               GKResponse* gkResponse) {
    return verifyChallenge(userId, 0 /* challenge */, enrolledPasswordHandle, providedPassword,
                           gkResponse);
}

    Status verifyChallenge(int32_t userId, int64_t challenge,
Status GateKeeperProxy::verifyChallenge(int32_t userId, int64_t challenge,
                                        const std::vector<uint8_t>& enrolledPasswordHandle,
                                        const std::vector<uint8_t>& providedPassword,
                           GKResponse* gkResponse) override {
                                        GKResponse* gkResponse) {
    IPCThreadState* ipc = IPCThreadState::self();
    const int calling_pid = ipc->getCallingPid();
    const int calling_uid = ipc->getCallingUid();
@@ -325,8 +312,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    if (aidl_hw_device) {
        // AIDL gatekeeper service
        AidlGatekeeperVerifyResp rsp;
            auto result =
                aidl_hw_device->verify(hw_userId, challenge, curPwdHandle, enteredPwd, &rsp);
        auto result = aidl_hw_device->verify(hw_userId, challenge, curPwdHandle, enteredPwd, &rsp);
        if (!result.isOk()) {
            LOG(ERROR) << "verify transaction failed";
            return GK_ERROR;
@@ -334,9 +320,9 @@ class GateKeeperProxy : public BnGateKeeperService {
        if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
            secureUserId = rsp.hardwareAuthToken.userId;
            // Serialize HardwareAuthToken to a vector as hw_auth_token_t.
                *gkResponse = GKResponse::ok(authToken2AidlVec(rsp.hardwareAuthToken),
                                             rsp.statusCode ==
                                                 AidlIGatekeeper::STATUS_REENROLL /* reenroll */);
            *gkResponse = GKResponse::ok(
                    authToken2AidlVec(rsp.hardwareAuthToken),
                    rsp.statusCode == AidlIGatekeeper::STATUS_REENROLL /* reenroll */);
        } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT) {
            *gkResponse = GKResponse::retry(rsp.timeoutMs);
        } else {
@@ -371,8 +357,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    if (gkResponse->response_code() == GKResponseCode::OK) {
        if (gkResponse->payload().size() != 0) {
            // try to connect to IKeystoreAuthorization AIDL service first.
                AIBinder* authzAIBinder =
                        AServiceManager_getService("android.security.authorization");
            AIBinder* authzAIBinder = AServiceManager_getService("android.security.authorization");
            ::ndk::SpAIBinder authzBinder(authzAIBinder);
            auto authzService = IKeystoreAuthorization::fromBinder(authzBinder);
            if (authzService) {
@@ -410,12 +395,12 @@ class GateKeeperProxy : public BnGateKeeperService {
    return Status::ok();
}

    Status getSecureUserId(int32_t userId, int64_t* sid) override {
Status GateKeeperProxy::getSecureUserId(int32_t userId, int64_t* sid) {
    *sid = read_sid(userId);
    return Status::ok();
}

    Status clearSecureUserId(int32_t userId) override {
Status GateKeeperProxy::clearSecureUserId(int32_t userId) {
    IPCThreadState* ipc = IPCThreadState::self();
    const int calling_pid = ipc->getCallingPid();
    const int calling_uid = ipc->getCallingUid();
@@ -434,7 +419,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    return Status::ok();
}

    Status reportDeviceSetupComplete() override {
Status GateKeeperProxy::reportDeviceSetupComplete() {
    IPCThreadState* ipc = IPCThreadState::self();
    const int calling_pid = ipc->getCallingPid();
    const int calling_uid = ipc->getCallingUid();
@@ -447,7 +432,7 @@ class GateKeeperProxy : public BnGateKeeperService {
    return Status::ok();
}

    status_t dump(int fd, const Vector<String16>&) override {
status_t GateKeeperProxy::dump(int fd, const Vector<String16>&) {
    IPCThreadState* ipc = IPCThreadState::self();
    const int pid = ipc->getCallingPid();
    const int uid = ipc->getCallingUid();
@@ -465,42 +450,4 @@ class GateKeeperProxy : public BnGateKeeperService {

    return OK;
}

  private:
    // AIDL gatekeeper service.
    std::shared_ptr<AidlIGatekeeper> aidl_hw_device;
    // HIDL gatekeeper service.
    sp<IGatekeeper> hw_device;

    bool clear_state_if_needed_done;
    bool is_running_gsi;
};
}  // namespace android

int main(int argc, char* argv[]) {
    ALOGI("Starting gatekeeperd...");
    if (argc < 2) {
        ALOGE("A directory must be specified!");
        return 1;
    }
    if (chdir(argv[1]) == -1) {
        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
        return 1;
    }

    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
    android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
    android::status_t ret =
        sm->addService(android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
    if (ret != android::OK) {
        ALOGE("Couldn't register binder service!");
        return -1;
    }

    /*
     * We're the only thread in existence, so we're just going to process
     * Binder transaction as a single-threaded program.
     */
    android::IPCThreadState::self()->joinThreadPool();
    return 0;
}
+83 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * 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.
 */

#include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
#include <android/service/gatekeeper/BnGateKeeperService.h>
#include <gatekeeper/GateKeeperResponse.h>

using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
using AidlIGatekeeper = ::aidl::android::hardware::gatekeeper::IGatekeeper;
using ::android::binder::Status;
using ::android::service::gatekeeper::BnGateKeeperService;
using GKResponse = ::android::service::gatekeeper::GateKeeperResponse;

namespace android {

class GateKeeperProxy : public BnGateKeeperService {
  public:
    GateKeeperProxy();

    virtual ~GateKeeperProxy() {}

    void store_sid(uint32_t userId, uint64_t sid);

    void clear_state_if_needed();

    bool mark_cold_boot();

    void maybe_store_sid(uint32_t userId, uint64_t sid);

    uint64_t read_sid(uint32_t userId);

    void clear_sid(uint32_t userId);

    // This should only be called on userIds being passed to the GateKeeper HAL. It ensures that
    // secure storage shared across a GSI image and a host image will not overlap.
    uint32_t adjust_userId(uint32_t userId);

#define GK_ERROR *gkResponse = GKResponse::error(), Status::ok()

    Status enroll(int32_t userId, const std::optional<std::vector<uint8_t>>& currentPasswordHandle,
                  const std::optional<std::vector<uint8_t>>& currentPassword,
                  const std::vector<uint8_t>& desiredPassword, GKResponse* gkResponse) override;

    Status verify(int32_t userId, const ::std::vector<uint8_t>& enrolledPasswordHandle,
                  const ::std::vector<uint8_t>& providedPassword, GKResponse* gkResponse) override;

    Status verifyChallenge(int32_t userId, int64_t challenge,
                           const std::vector<uint8_t>& enrolledPasswordHandle,
                           const std::vector<uint8_t>& providedPassword,
                           GKResponse* gkResponse) override;

    Status getSecureUserId(int32_t userId, int64_t* sid) override;

    Status clearSecureUserId(int32_t userId) override;

    Status reportDeviceSetupComplete() override;

    status_t dump(int fd, const Vector<String16>&) override;

  private:
    // AIDL gatekeeper service.
    std::shared_ptr<AidlIGatekeeper> aidl_hw_device;
    // HIDL gatekeeper service.
    sp<IGatekeeper> hw_device;

    bool clear_state_if_needed_done;
    bool is_running_gsi;
};
}  // namespace android

gatekeeperd/main.cpp

0 → 100644
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * 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.
 */

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>

#include <log/log.h>

#include "gatekeeperd.h"

int main(int argc, char* argv[]) {
    ALOGI("Starting gatekeeperd...");
    if (argc < 2) {
        ALOGE("A directory must be specified!");
        return 1;
    }
    if (chdir(argv[1]) == -1) {
        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
        return 1;
    }

    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
    android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
    android::status_t ret = sm->addService(
            android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
    if (ret != android::OK) {
        ALOGE("Couldn't register binder service!");
        return -1;
    }

    /*
     * We're the only thread in existence, so we're just going to process
     * Binder transaction as a single-threaded program.
     */
    android::IPCThreadState::self()->joinThreadPool();
    return 0;
}