/*
 * Copyright (c) 2019, 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.
 */

#define LOG_TAG "credstore"

#include <atomic>

#include <android-base/logging.h>
#include <android/security/rkp/BnGetKeyCallback.h>
#include <android/security/rkp/BnGetRegistrationCallback.h>
#include <android/security/rkp/IGetKeyCallback.h>
#include <android/security/rkp/IRemoteProvisioning.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <vintf/VintfObject.h>

#include "RemotelyProvisionedKey.h"

namespace android {
namespace security {
namespace identity {
namespace {

using ::android::binder::Status;
using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
using ::android::hardware::security::keymint::RpcHardwareInfo;
using ::android::security::rkp::BnGetKeyCallback;
using ::android::security::rkp::BnGetRegistrationCallback;
using ::android::security::rkp::IGetKeyCallback;
using ::android::security::rkp::IRegistration;
using ::android::security::rkp::IRemoteProvisioning;
using ::android::security::rkp::RemotelyProvisionedKey;

constexpr const char* kRemoteProvisioningServiceName = "remote_provisioning";

std::optional<String16> findRpcNameById(std::string_view targetRpcId) {
    auto deviceManifest = vintf::VintfObject::GetDeviceHalManifest();
    auto instances = deviceManifest->getAidlInstances("android.hardware.security.keymint",
                                                      "IRemotelyProvisionedComponent");
    for (const std::string& instance : instances) {
        auto rpcName =
            IRemotelyProvisionedComponent::descriptor + String16("/") + String16(instance.c_str());
        sp<IRemotelyProvisionedComponent> rpc =
            android::waitForService<IRemotelyProvisionedComponent>(rpcName);

        auto rpcId = getRpcId(rpc);
        if (!rpcId) {
            continue;
        }
        if (*rpcId == targetRpcId) {
            return rpcName;
        }
    }

    LOG(ERROR) << "Remotely provisioned component with given unique ID: " << targetRpcId
               << " not found";
    return std::nullopt;
}

std::optional<String16> getRpcName(const sp<IRemotelyProvisionedComponent>& rpc) {
    std::optional<std::string> targetRpcId = getRpcId(rpc);
    if (!targetRpcId) {
        return std::nullopt;
    }
    return findRpcNameById(*targetRpcId);
}

class GetKeyCallback : public BnGetKeyCallback {
  public:
    GetKeyCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise)
        : keyPromise_(std::move(keyPromise)), called_() {}

    Status onSuccess(const RemotelyProvisionedKey& key) override {
        if (called_.test_and_set()) {
            return Status::ok();
        }
        keyPromise_.set_value(key);
        return Status::ok();
    }
    Status onCancel() override {
        if (called_.test_and_set()) {
            return Status::ok();
        }
        LOG(ERROR) << "GetKeyCallback cancelled";
        keyPromise_.set_value(std::nullopt);
        return Status::ok();
    }
    Status onError(IGetKeyCallback::ErrorCode error, const String16& description) override {
        if (called_.test_and_set()) {
            return Status::ok();
        }
        LOG(ERROR) << "GetKeyCallback failed: " << static_cast<int>(error) << ", " << description;
        keyPromise_.set_value(std::nullopt);
        return Status::ok();
    }

  private:
    std::promise<std::optional<RemotelyProvisionedKey>> keyPromise_;
    // This callback can only be called into once
    std::atomic_flag called_;
};

class GetRegistrationCallback : public BnGetRegistrationCallback {
  public:
    GetRegistrationCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise,
                            uint32_t keyId)
        : keyPromise_(std::move(keyPromise)), keyId_(keyId), called_() {}

    Status onSuccess(const sp<IRegistration>& registration) override {
        if (called_.test_and_set()) {
            return Status::ok();
        }
        auto cb = sp<GetKeyCallback>::make(std::move(keyPromise_));
        auto status = registration->getKey(keyId_, cb);
        if (!status.isOk()) {
            cb->onError(IGetKeyCallback::ErrorCode::ERROR_UNKNOWN,
                        String16("Failed to register GetKeyCallback"));
        }
        return Status::ok();
    }
    Status onCancel() override {
        if (called_.test_and_set()) {
            return Status::ok();
        }
        LOG(ERROR) << "GetRegistrationCallback cancelled";
        keyPromise_.set_value(std::nullopt);
        return Status::ok();
    }
    Status onError(const String16& error) override {
        if (called_.test_and_set()) {
            return Status::ok();
        }
        LOG(ERROR) << "GetRegistrationCallback failed: " << error;
        keyPromise_.set_value(std::nullopt);
        return Status::ok();
    }

  private:
    std::promise<std::optional<RemotelyProvisionedKey>> keyPromise_;
    int32_t keyId_;
    // This callback can only be called into once
    std::atomic_flag called_;
};

}  // namespace

std::optional<std::string> getRpcId(const sp<IRemotelyProvisionedComponent>& rpc) {
    RpcHardwareInfo rpcHwInfo;
    Status status = rpc->getHardwareInfo(&rpcHwInfo);
    if (!status.isOk()) {
        LOG(ERROR) << "Error getting remotely provisioned component hardware info: " << status;
        return std::nullopt;
    }

    if (!rpcHwInfo.uniqueId) {
        LOG(ERROR) << "Remotely provisioned component is missing a unique id, which is "
                   << "required for credential key remotely provisioned attestation keys. "
                   << "This is a bug in the vendor implementation.";
        return std::nullopt;
    }

    return *rpcHwInfo.uniqueId;
}

std::optional<std::future<std::optional<RemotelyProvisionedKey>>>
getRpcKeyFuture(const sp<IRemotelyProvisionedComponent>& rpc, int32_t keyId) {
    std::promise<std::optional<RemotelyProvisionedKey>> keyPromise;
    auto keyFuture = keyPromise.get_future();

    auto rpcName = getRpcName(rpc);
    if (!rpcName) {
        LOG(ERROR) << "Failed to get IRemotelyProvisionedComponent name";
        return std::nullopt;
    }

    sp<IRemoteProvisioning> remoteProvisioning =
        android::waitForService<IRemoteProvisioning>(String16(kRemoteProvisioningServiceName));
    if (!remoteProvisioning) {
        LOG(ERROR) << "Failed to get IRemoteProvisioning HAL";
        return std::nullopt;
    }

    auto cb = sp<GetRegistrationCallback>::make(std::move(keyPromise), keyId);
    Status status = remoteProvisioning->getRegistration(*rpcName, cb);
    if (!status.isOk()) {
        LOG(ERROR) << "Failed getRegistration()";
        return std::nullopt;
    }

    return keyFuture;
}

}  // namespace identity
}  // namespace security
}  // namespace android
