/*
 * Copyright (C) 2009 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 "keystore"

#include <android-base/logging.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <android/security/keystore/IKeystoreService.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <keymasterV4_0/Keymaster3.h>
#include <keymasterV4_0/Keymaster4.h>
#include <utils/StrongPointer.h>

#include <keystore/keystore_hidl_support.h>
#include <keystore/keystore_return_types.h>

#include "KeyStore.h"
#include "key_store_service.h"
#include "legacy_keymaster_device_wrapper.h"
#include "permissions.h"

/* KeyStore is a secured storage for key-value pairs. In this implementation,
 * each file stores one key-value pair. Keys are encoded in file names, and
 * values are encrypted with checksums. The encryption key is protected by a
 * user-defined password. To keep things simple, buffers are always larger than
 * the maximum space we needed, so boundary checks on buffers are omitted. */

using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::keymaster::V4_0::ErrorCode;
using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
using ::android::hardware::keymaster::V4_0::SecurityLevel;
using ::android::hidl::manager::V1_2::IServiceManager;

using ::keystore::keymaster::support::Keymaster;
using ::keystore::keymaster::support::Keymaster3;
using ::keystore::keymaster::support::Keymaster4;

using keystore::KeymasterDevices;

template <typename Wrapper>
KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) {
    KeymasterDevices result;
    serviceManager->listManifestByInterface(
        Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
            auto try_get_device = [&](const auto& name, bool fail_silent) {
                auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
                if (fail_silent && !device) return;
                CHECK(device) << "Failed to get service for \""
                              << Wrapper::WrappedIKeymasterDevice::descriptor
                              << "\" with interface name \"" << name << "\"";

                sp<Keymaster> kmDevice(new Wrapper(device, name));
                auto halVersion = kmDevice->halVersion();
                SecurityLevel securityLevel = halVersion.securityLevel;
                LOG(INFO) << "found " << Wrapper::WrappedIKeymasterDevice::descriptor
                          << " with interface name " << name << " and seclevel "
                          << toString(securityLevel);
                CHECK(static_cast<uint32_t>(securityLevel) < result.size())
                    << "Security level of \"" << Wrapper::WrappedIKeymasterDevice::descriptor
                    << "\" with interface name \"" << name << "\" out of range";
                auto& deviceSlot = result[securityLevel];
                if (deviceSlot) {
                    if (!fail_silent) {
                        LOG(WARNING) << "Implementation of \""
                                     << Wrapper::WrappedIKeymasterDevice::descriptor
                                     << "\" with interface name \"" << name
                                     << "\" and security level: " << toString(securityLevel)
                                     << " Masked by other implementation of Keymaster";
                    }
                } else {
                    deviceSlot = kmDevice;
                }
            };
            bool has_default = false;
            for (auto& n : names) {
                try_get_device(n, false);
                if (n == "default") has_default = true;
            }
            // Make sure that we always check the default device. If we enumerate only what is
            // known to hwservicemanager, we miss a possible passthrough HAL.
            if (!has_default) {
                try_get_device("default", true /* fail_silent */);
            }
        });
    return result;
}

KeymasterDevices initializeKeymasters() {
    auto serviceManager = IServiceManager::getService();
    CHECK(serviceManager.get()) << "Failed to get ServiceManager";
    auto result = enumerateKeymasterDevices<Keymaster4>(serviceManager.get());
    auto softKeymaster = result[SecurityLevel::SOFTWARE];
    if (!result[SecurityLevel::TRUSTED_ENVIRONMENT]) {
        result = enumerateKeymasterDevices<Keymaster3>(serviceManager.get());
    }
    if (softKeymaster) result[SecurityLevel::SOFTWARE] = softKeymaster;
    if (result[SecurityLevel::SOFTWARE] && !result[SecurityLevel::TRUSTED_ENVIRONMENT]) {
        LOG(WARNING) << "No secure Keymaster implementation found, but device offers insecure"
                        " Keymaster HAL. Using as default.";
        result[SecurityLevel::TRUSTED_ENVIRONMENT] = result[SecurityLevel::SOFTWARE];
        result[SecurityLevel::SOFTWARE] = nullptr;
    }
    if (!result[SecurityLevel::SOFTWARE]) {
        auto fbdev = android::keystore::makeSoftwareKeymasterDevice();
        CHECK(fbdev.get()) << "Unable to create Software Keymaster Device";
        result[SecurityLevel::SOFTWARE] = new Keymaster3(fbdev, "Software");
    }
    return result;
}

int main(int argc, char* argv[]) {
    using android::hardware::hidl_string;
    CHECK(argc >= 2) << "A directory must be specified!";
    CHECK(chdir(argv[1]) != -1) << "chdir: " << argv[1] << ": " << strerror(errno);

    auto kmDevices = initializeKeymasters();

    CHECK(kmDevices[SecurityLevel::SOFTWARE]) << "Missing software Keymaster device";
    CHECK(kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT])
        << "Error no viable keymaster device found";

    CHECK(configure_selinux() != -1) << "Failed to configure SELinux.";

    auto halVersion = kmDevices[SecurityLevel::TRUSTED_ENVIRONMENT]->halVersion();

    // If the hardware is keymaster 2.0 or higher we will not allow the fallback device for import
    // or generation of keys. The fallback device is only used for legacy keys present on the
    // device.
    SecurityLevel minimalAllowedSecurityLevelForNewKeys =
        halVersion.majorVersion >= 2 ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE;

    android::sp<keystore::KeyStore> keyStore(
        new keystore::KeyStore(kmDevices, minimalAllowedSecurityLevelForNewKeys));
    keyStore->initialize();
    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
    android::sp<keystore::KeyStoreService> service = new keystore::KeyStoreService(keyStore);
    service->setRequestingSid(true);
    android::status_t ret = sm->addService(android::String16("android.security.keystore"), service);
    CHECK(ret == android::OK) << "Couldn't register binder service!";

    /*
     * This thread is just going to process Binder transactions.
     */
    android::IPCThreadState::self()->joinThreadPool();
    return 1;
}
