/*
 * Copyright (C) 2016 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 "MetadataCrypt.h"
#include "KeyBuffer.h"

#include <algorithm>
#include <string>
#include <thread>
#include <vector>

#include <fcntl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <cutils/fs.h>
#include <fs_mgr.h>
#include <libdm/dm.h>

#include "Checkpoint.h"
#include "CryptoType.h"
#include "EncryptInplace.h"
#include "KeyStorage.h"
#include "KeyUtil.h"
#include "Keymaster.h"
#include "Utils.h"
#include "VoldUtil.h"

#define TABLE_LOAD_RETRIES 10

namespace android {
namespace vold {

using android::fs_mgr::FstabEntry;
using android::fs_mgr::GetEntryForMountPoint;
using android::vold::KeyBuffer;
using namespace android::dm;

static const std::string kDmNameUserdata = "userdata";

static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";

constexpr CryptoType supported_crypto_types[] = {aes_256_xts, adiantum};

static_assert(validateSupportedCryptoTypes(64, supported_crypto_types,
                                           array_length(supported_crypto_types)),
              "We have a CryptoType which was incompletely constructed.");

constexpr CryptoType legacy_aes_256_xts =
        CryptoType().set_config_name("aes-256-xts").set_kernel_name("AES-256-XTS").set_keysize(64);

constexpr CryptoType legacy_crypto_types[] = {legacy_aes_256_xts};

static_assert(validateSupportedCryptoTypes(64, legacy_crypto_types,
                                           array_length(legacy_crypto_types)),
              "We have a CryptoType which was incompletely constructed.");

static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
    // We're about to mount data not verified by verified boot.  Tell Keymaster that early boot has
    // ended.
    //
    // TODO(paulcrowley): Make a Keymaster singleton or something, so we don't have to repeatedly
    // open and initialize the service.
    ::android::vold::Keymaster keymaster;
    keymaster.earlyBootEnded();

    // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
    // partitions in the fsck domain.
    if (setexeccon(android::vold::sFsckContext)) {
        PLOG(ERROR) << "Failed to setexeccon";
        return false;
    }
    auto mount_rc = fs_mgr_do_mount(&fstab_default, const_cast<char*>(mount_point),
                                    const_cast<char*>(blk_device), nullptr,
                                    android::vold::cp_needsCheckpoint());
    if (setexeccon(nullptr)) {
        PLOG(ERROR) << "Failed to clear setexeccon";
        return false;
    }
    if (mount_rc != 0) {
        LOG(ERROR) << "fs_mgr_do_mount failed with rc " << mount_rc;
        return false;
    }
    LOG(DEBUG) << "Mounted " << mount_point;
    return true;
}

// Note: It is possible to orphan a key if it is removed before deleting
// Update this once keymaster APIs change, and we have a proper commit.
static void commit_key(const std::string& dir) {
    while (!android::base::WaitForProperty("vold.checkpoint_committed", "1")) {
        LOG(ERROR) << "Wait for boot timed out";
    }
    Keymaster keymaster;
    auto keyPath = dir + "/" + kFn_keymaster_key_blob;
    auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
    std::string key;

    if (!android::base::ReadFileToString(keyPath, &key)) {
        LOG(ERROR) << "Failed to read old key: " << dir;
        return;
    }
    if (rename(newKeyPath.c_str(), keyPath.c_str()) != 0) {
        PLOG(ERROR) << "Unable to move upgraded key to location: " << keyPath;
        return;
    }
    if (!keymaster.deleteKey(key)) {
        LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
    }
    LOG(INFO) << "Old Key deleted: " << dir;
}

static bool read_key(const std::string& metadata_key_dir, const KeyGeneration& gen,
                     KeyBuffer* key) {
    if (metadata_key_dir.empty()) {
        LOG(ERROR) << "Failed to get metadata_key_dir";
        return false;
    }
    std::string sKey;
    auto dir = metadata_key_dir + "/key";
    LOG(DEBUG) << "metadata_key_dir/key: " << dir;
    if (fs_mkdirs(dir.c_str(), 0700)) {
        PLOG(ERROR) << "Creating directories: " << dir;
        return false;
    }
    auto temp = metadata_key_dir + "/tmp";
    auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
    /* If we have a leftover upgraded key, delete it.
     * We either failed an update and must return to the old key,
     * or we rebooted before commiting the keys in a freak accident.
     * Either way, we can re-upgrade the key if we need to.
     */
    Keymaster keymaster;
    if (pathExists(newKeyPath)) {
        if (!android::base::ReadFileToString(newKeyPath, &sKey))
            LOG(ERROR) << "Failed to read incomplete key: " << dir;
        else if (!keymaster.deleteKey(sKey))
            LOG(ERROR) << "Incomplete key deletion failed, continuing anyway: " << dir;
        else
            unlink(newKeyPath.c_str());
    }
    bool needs_cp = cp_needsCheckpoint();
    if (!retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key, needs_cp)) return false;
    if (needs_cp && pathExists(newKeyPath)) std::thread(commit_key, dir).detach();
    return true;
}

static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_sec) {
    if (android::vold::GetBlockDev512Sectors(real_blkdev, nr_sec) != android::OK) {
        PLOG(ERROR) << "Unable to measure size of " << real_blkdev;
        return false;
    }
    return true;
}

static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& blk_device,
                                  bool is_legacy, const std::string& cipher, bool set_dun,
                                  const KeyBuffer& key, std::string* crypto_blkdev) {
    uint64_t nr_sec;
    if (!get_number_of_sectors(blk_device, &nr_sec)) return false;

    KeyBuffer hex_key_buffer;
    if (android::vold::StrToHex(key, hex_key_buffer) != android::OK) {
        LOG(ERROR) << "Failed to turn key to hex";
        return false;
    }
    std::string hex_key(hex_key_buffer.data(), hex_key_buffer.size());

    DmTable table;
    table.Emplace<DmTargetDefaultKey>(0, nr_sec, cipher, hex_key, blk_device, 0, is_legacy,
                                      set_dun);

    auto& dm = DeviceMapper::Instance();
    for (int i = 0;; i++) {
        if (dm.CreateDevice(dm_name, table)) {
            break;
        }
        if (i + 1 >= TABLE_LOAD_RETRIES) {
            PLOG(ERROR) << "Could not create default-key device " << dm_name;
            return false;
        }
        PLOG(INFO) << "Could not create default-key device, retrying";
        usleep(500000);
    }

    if (!dm.GetDmDevicePathByName(dm_name, crypto_blkdev)) {
        LOG(ERROR) << "Cannot retrieve default-key device status " << dm_name;
        return false;
    }
    return true;
}

static const CryptoType& lookup_cipher_in_table(const CryptoType table[], int table_len,
                                                const std::string& cipher_name) {
    if (cipher_name.empty()) return table[0];
    for (int i = 0; i < table_len; i++) {
        if (cipher_name == table[i].get_config_name()) {
            return table[i];
        }
    }
    return invalid_crypto_type;
}

static const CryptoType& lookup_cipher(const std::string& cipher_name, bool is_legacy) {
    if (is_legacy) {
        return lookup_cipher_in_table(legacy_crypto_types, array_length(legacy_crypto_types),
                                      cipher_name);
    } else {
        return lookup_cipher_in_table(supported_crypto_types, array_length(supported_crypto_types),
                                      cipher_name);
    }
}

bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::string& mount_point,
                                      bool needs_encrypt) {
    LOG(DEBUG) << "fscrypt_mount_metadata_encrypted: " << mount_point << " " << needs_encrypt;
    auto encrypted_state = android::base::GetProperty("ro.crypto.state", "");
    if (encrypted_state != "" && encrypted_state != "encrypted") {
        LOG(DEBUG) << "fscrypt_enable_crypto got unexpected starting state: " << encrypted_state;
        return false;
    }

    auto data_rec = GetEntryForMountPoint(&fstab_default, mount_point);
    if (!data_rec) {
        LOG(ERROR) << "Failed to get data_rec for " << mount_point;
        return false;
    }
    if (blk_device != data_rec->blk_device) {
        LOG(ERROR) << "blk_device " << blk_device << " does not match fstab entry "
                   << data_rec->blk_device << " for " << mount_point;
        return false;
    }

    bool is_legacy;
    if (!DmTargetDefaultKey::IsLegacy(&is_legacy)) return false;

    // Non-legacy driver always sets DUN
    bool set_dun = !is_legacy || android::base::GetBoolProperty("ro.crypto.set_dun", false);
    if (!set_dun && data_rec->fs_mgr_flags.checkpoint_blk) {
        LOG(ERROR) << "Block checkpoints and metadata encryption require ro.crypto.set_dun option";
        return false;
    }

    auto cipher = lookup_cipher(data_rec->metadata_cipher, is_legacy);
    if (cipher.get_kernel_name() == nullptr) {
        LOG(ERROR) << "No metadata cipher named " << data_rec->metadata_cipher
                   << " found, is_legacy=" << is_legacy;
        return false;
    }

    auto gen = needs_encrypt ? makeGen(cipher) : neverGen();
    KeyBuffer key;
    if (!read_key(data_rec->metadata_key_dir, gen, &key)) return false;

    std::string crypto_blkdev;
    if (!create_crypto_blk_dev(kDmNameUserdata, data_rec->blk_device, is_legacy,
                               cipher.get_kernel_name(), set_dun, key, &crypto_blkdev))
        return false;

    // FIXME handle the corrupt case
    if (needs_encrypt) {
        uint64_t nr_sec;
        if (!get_number_of_sectors(data_rec->blk_device, &nr_sec)) return false;
        LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
        off64_t size_already_done = 0;
        auto rc = cryptfs_enable_inplace(crypto_blkdev.data(), blk_device.data(), nr_sec,
                                         &size_already_done, nr_sec, 0, false);
        if (rc != 0) {
            LOG(ERROR) << "Inplace crypto failed with code: " << rc;
            return false;
        }
        if (static_cast<uint64_t>(size_already_done) != nr_sec) {
            LOG(ERROR) << "Inplace crypto only got up to sector: " << size_already_done;
            return false;
        }
        LOG(INFO) << "Inplace encryption complete";
    }

    LOG(DEBUG) << "Mounting metadata-encrypted filesystem:" << mount_point;
    mount_via_fs_mgr(data_rec->mount_point.c_str(), crypto_blkdev.c_str());
    return true;
}

}  // namespace vold
}  // namespace android
