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

Commit c5c0c302 authored by Pawan Wagh's avatar Pawan Wagh
Browse files

Separating GateKeeperProxy declaration in header

Adding gatekeeperd.h and moving declarations for GateKeeperProxy into
header. Adding separate main.cpp for entry point.
Adding cc_default to be used by binary and fuzzer.
This is needed in order to fuzz gatekeeperd AIDL service

Test: m gatekeeperd
Bug: N/A
Change-Id: Ifb2082f68bb200e4ed83608a6def8e45032753de
parent 057cbf63
Loading
Loading
Loading
Loading
+12 −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"],
}

+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;
}