/*
 * 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 <string>
#include <thread>
#include <vector>

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

#include <linux/dm-ioctl.h>

#include <android-base/logging.h>
#include <cutils/properties.h>
#include <fs_mgr.h>

#include "AutoCloseFD.h"
#include "EncryptInplace.h"
#include "KeyStorage.h"
#include "KeyUtil.h"
#include "secontext.h"
#include "Utils.h"
#include "VoldUtil.h"

extern struct fstab *fstab;
#define DM_CRYPT_BUF_SIZE 4096
#define TABLE_LOAD_RETRIES 10
#define DEFAULT_KEY_TARGET_TYPE "default-key"

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

static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
    // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
    // partitions in the fsck domain.
    if (setexeccon(secontextFsck())) {
        PLOG(ERROR) << "Failed to setexeccon";
        return false;
    }
    auto mount_rc = fs_mgr_do_mount(fstab, const_cast<char*>(mount_point),
                                    const_cast<char*>(blk_device), nullptr);
    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;
}

static bool read_key(bool create_if_absent, std::string* key) {
    auto data_rec = fs_mgr_get_crypt_entry(fstab);
    if (!data_rec) {
        LOG(ERROR) << "Failed to get data_rec";
        return false;
    }
    if (!data_rec->key_dir) {
        LOG(ERROR) << "Failed to get key_dir";
        return false;
    }
    LOG(DEBUG) << "key_dir: " << data_rec->key_dir;
    if (!android::vold::pathExists(data_rec->key_dir)) {
        if (mkdir(data_rec->key_dir, 0777) != 0) {
            PLOG(ERROR) << "Unable to create: " << data_rec->key_dir;
            return false;
        }
        LOG(DEBUG) << "Created: " << data_rec->key_dir;
    }
    std::string key_dir = data_rec->key_dir;
    auto dir = key_dir + "/key";
    auto temp = key_dir + "/tmp";
    if (!android::vold::retrieveKey(create_if_absent, dir, temp, key)) return false;
    return true;
}

static std::string default_key_params(const std::string& real_blkdev, const std::string& key) {
    std::string hex_key;
    if (android::vold::StrToHex(key, hex_key) != android::OK) {
        LOG(ERROR) << "Failed to turn key to hex";
        return "";
    }
    auto res = std::string() + "AES-256-XTS " + hex_key + " " + real_blkdev + " 0";
    LOG(DEBUG) << "crypt_params: " << res;
    return res;
}

static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t *nr_sec) {
    AutoCloseFD dev_fd(real_blkdev, O_RDONLY);
    if (!dev_fd) {
        PLOG(ERROR) << "Unable to open " << real_blkdev << " to measure size";
        return false;
    }
    unsigned long res;
    // TODO: should use BLKGETSIZE64
    get_blkdev_size(dev_fd.get(), &res);
    if (res == 0) {
        PLOG(ERROR) << "Unable to measure size of " << real_blkdev;
        return false;
    }
    *nr_sec = res;
    return true;
}

static struct dm_ioctl* dm_ioctl_init(char *buffer, size_t buffer_size,
                                      const std::string& dm_name) {
    if (buffer_size < sizeof(dm_ioctl)) {
        LOG(ERROR) << "dm_ioctl buffer too small";
        return nullptr;
    }

    memset(buffer, 0, buffer_size);
    struct dm_ioctl* io = (struct dm_ioctl*) buffer;
    io->data_size = buffer_size;
    io->data_start = sizeof(struct dm_ioctl);
    io->version[0] = 4;
    io->version[1] = 0;
    io->version[2] = 0;
    io->flags = 0;
    dm_name.copy(io->name, sizeof(io->name));
    return io;
}

static bool create_crypto_blk_dev(const std::string& dm_name, uint64_t nr_sec,
                                  const std::string& target_type, const std::string& crypt_params,
                                  std::string* crypto_blkdev) {
    AutoCloseFD dm_fd("/dev/device-mapper", O_RDWR);
    if (!dm_fd) {
        PLOG(ERROR) << "Cannot open device-mapper";
        return false;
    }
    alignas(struct dm_ioctl) char buffer[DM_CRYPT_BUF_SIZE];
    auto io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
    if (!io || ioctl(dm_fd.get(), DM_DEV_CREATE, io) != 0) {
        PLOG(ERROR) << "Cannot create dm-crypt device " << dm_name;
        return false;
    }

    // Get the device status, in particular, the name of its device file
    io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
    if (ioctl(dm_fd.get(), DM_DEV_STATUS, io) != 0) {
        PLOG(ERROR) << "Cannot retrieve dm-crypt device status " << dm_name;
        return false;
    }
    *crypto_blkdev = std::string() + "/dev/block/dm-" + std::to_string(
        (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00));

    io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
    unsigned long paramix = io->data_start + sizeof(struct dm_target_spec);
    unsigned long nullix = paramix + crypt_params.size();
    unsigned long endix = (nullix + 1 + 7) & 8; // Add room for \0 and align to 8 byte boundary

    if (endix > sizeof(buffer)) {
        LOG(ERROR) << "crypt_params too big for DM_CRYPT_BUF_SIZE";
        return false;
    }

    io->target_count = 1;
    auto tgt = (struct dm_target_spec *) (buffer + io->data_start);
    tgt->status = 0;
    tgt->sector_start = 0;
    tgt->length = nr_sec;
    target_type.copy(tgt->target_type, sizeof(tgt->target_type));
    crypt_params.copy(buffer + paramix, sizeof(buffer) - paramix);
    buffer[nullix] = '\0';
    tgt->next = endix;

    for (int i = 0; ; i++) {
        if (ioctl(dm_fd.get(), DM_TABLE_LOAD, io) == 0) {
            break;
        }
        if (i+1 >= TABLE_LOAD_RETRIES) {
            PLOG(ERROR) << "DM_TABLE_LOAD ioctl failed";
            return false;
        }
        PLOG(INFO) << "DM_TABLE_LOAD ioctl failed, retrying";
        usleep(500000);
    }

    // Resume this device to activate it
    io = dm_ioctl_init(buffer, sizeof(buffer), dm_name);
    if (ioctl(dm_fd.get(), DM_DEV_SUSPEND, io)) {
        PLOG(ERROR) << "Cannot resume dm-crypt device " << dm_name;
        return false;
    }
    return true;
}

#define DATA_PREP_TIMEOUT 1000
static bool prep_data_fs(void)
{
    // NOTE: post_fs_data results in init calling back around to vold, so all
    // callers to this method must be async

    /* Do the prep of the /data filesystem */
    property_set("vold.post_fs_data_done", "0");
    property_set("vold.decrypt", "trigger_post_fs_data");
    LOG(DEBUG) << "Waiting for post_fs_data_done";

    /* Wait a max of 50 seconds, hopefully it takes much less */
    for (int i = 0; ; i++) {
        char p[PROPERTY_VALUE_MAX];

        property_get("vold.post_fs_data_done", p, "0");
        if (*p == '1') {
            LOG(INFO) << "Successful data prep";
            return true;
        }
        if (i + 1 == DATA_PREP_TIMEOUT) {
            LOG(ERROR) << "post_fs_data timed out";
            return false;
        }
        usleep(50000);
    }
}

static void async_kick_off() {
    LOG(DEBUG) << "Asynchronously restarting framework";
    sleep(2); // TODO: this mirrors cryptfs, but can it be made shorter?
    property_set("vold.decrypt", "trigger_load_persist_props");
    if (!prep_data_fs()) return;
    /* startup service classes main and late_start */
    property_set("vold.decrypt", "trigger_restart_framework");
}

bool e4crypt_mount_metadata_encrypted() {
    LOG(DEBUG) << "e4crypt_mount_default_encrypted";
    std::string key;
    if (!read_key(false, &key)) return false;
    auto data_rec = fs_mgr_get_crypt_entry(fstab);
    if (!data_rec) {
        LOG(ERROR) << "Failed to get data_rec";
        return false;
    }
    uint64_t nr_sec;
    if (!get_number_of_sectors(data_rec->blk_device, &nr_sec)) return false;
    std::string crypto_blkdev;
    if (!create_crypto_blk_dev(kDmNameUserdata, nr_sec, DEFAULT_KEY_TARGET_TYPE,
        default_key_params(data_rec->blk_device, key), &crypto_blkdev)) return false;
    // FIXME handle the corrupt case

    LOG(DEBUG) << "Restarting filesystem for metadata encryption";
    mount_via_fs_mgr(data_rec->mount_point, crypto_blkdev.c_str());
    std::thread(&async_kick_off).detach();
    return true;
}

bool e4crypt_enable_crypto() {
    LOG(DEBUG) << "e4crypt_enable_crypto";
    char encrypted_state[PROPERTY_VALUE_MAX];
    property_get("ro.crypto.state", encrypted_state, "");
    if (strcmp(encrypted_state, "")) {
        LOG(DEBUG) << "e4crypt_enable_crypto got unexpected starting state: " << encrypted_state;
        return false;
    }

    std::string key_ref;
    if (!read_key(true, &key_ref)) return false;

    auto data_rec = fs_mgr_get_crypt_entry(fstab);
    if (!data_rec) {
        LOG(ERROR) << "Failed to get data_rec";
        return false;
    }
    uint64_t nr_sec;
    if (!get_number_of_sectors(data_rec->blk_device, &nr_sec)) return false;

    std::string crypto_blkdev;
    if (!create_crypto_blk_dev(kDmNameUserdata, nr_sec, DEFAULT_KEY_TARGET_TYPE,
        default_key_params(data_rec->blk_device, key_ref), &crypto_blkdev)) return false;

    LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
    off64_t size_already_done = 0;
    auto rc = cryptfs_enable_inplace(const_cast<char *>(crypto_blkdev.c_str()),
                                     data_rec->blk_device, nr_sec, &size_already_done, nr_sec, 0);
    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";

    property_set("ro.crypto.state", "encrypted");
    property_set("ro.crypto.type", "file");

    mount_via_fs_mgr(data_rec->mount_point, crypto_blkdev.c_str());
    property_set("vold.decrypt", "trigger_reset_main");
    std::thread(&async_kick_off).detach();
    return true;
}
