#include "Ext4Crypt.h"

#include <iomanip>
#include <map>
#include <fstream>
#include <string>
#include <sstream>

#include <errno.h>
#include <dirent.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cutils/properties.h>
#include <openssl/sha.h>

#include <private/android_filesystem_config.h>

#include "unencrypted_properties.h"
#include "key_control.h"
#include "cryptfs.h"
#include "ext4_crypt_init_extensions.h"

#define LOG_TAG "Ext4Crypt"
#include "cutils/log.h"
#include <cutils/klog.h>
#include <android-base/file.h>
#include <android-base/stringprintf.h>

namespace {
    // Key length in bits
    const int key_length = 128;
    static_assert(key_length % 8 == 0,
                  "Key length must be multiple of 8 bits");

    // How long do we store passwords for?
    const int password_max_age_seconds = 60;

    // How is device encrypted
    struct keys {
        std::string master_key;
        std::string password;
        time_t expiry_time;
    };
    std::map<std::string, keys> s_key_store;

    // ext4enc:TODO get these consts from somewhere good
    const int SHA512_LENGTH = 64;
    const int EXT4_KEY_DESCRIPTOR_SIZE = 8;

    // ext4enc:TODO Include structure from somewhere sensible
    // MUST be in sync with ext4_crypto.c in kernel
    const int EXT4_MAX_KEY_SIZE = 64;
    const int EXT4_ENCRYPTION_MODE_AES_256_XTS = 1;
    struct ext4_encryption_key {
        uint32_t mode;
        char raw[EXT4_MAX_KEY_SIZE];
        uint32_t size;
    };

    namespace tag {
        const char* magic = "magic";
        const char* major_version = "major_version";
        const char* minor_version = "minor_version";
        const char* flags = "flags";
        const char* crypt_type = "crypt_type";
        const char* failed_decrypt_count = "failed_decrypt_count";
        const char* crypto_type_name = "crypto_type_name";
        const char* master_key = "master_key";
        const char* salt = "salt";
        const char* kdf_type = "kdf_type";
        const char* N_factor = "N_factor";
        const char* r_factor = "r_factor";
        const char* p_factor = "p_factor";
        const char* keymaster_blob = "keymaster_blob";
        const char* scrypted_intermediate_key = "scrypted_intermediate_key";
    }
}

static std::string e4crypt_install_key(const std::string &key);

static int put_crypt_ftr_and_key(const crypt_mnt_ftr& crypt_ftr,
                                 UnencryptedProperties& props)
{
    SLOGI("Putting crypt footer");

    bool success = props.Set<int>(tag::magic, crypt_ftr.magic)
      && props.Set<int>(tag::major_version, crypt_ftr.major_version)
      && props.Set<int>(tag::minor_version, crypt_ftr.minor_version)
      && props.Set<int>(tag::flags, crypt_ftr.flags)
      && props.Set<int>(tag::crypt_type, crypt_ftr.crypt_type)
      && props.Set<int>(tag::failed_decrypt_count,
                        crypt_ftr.failed_decrypt_count)
      && props.Set<std::string>(tag::crypto_type_name,
                                std::string(reinterpret_cast<const char*>(crypt_ftr.crypto_type_name)))
      && props.Set<std::string>(tag::master_key,
                                std::string((const char*) crypt_ftr.master_key,
                                            crypt_ftr.keysize))
      && props.Set<std::string>(tag::salt,
                                std::string((const char*) crypt_ftr.salt,
                                            SALT_LEN))
      && props.Set<int>(tag::kdf_type, crypt_ftr.kdf_type)
      && props.Set<int>(tag::N_factor, crypt_ftr.N_factor)
      && props.Set<int>(tag::r_factor, crypt_ftr.r_factor)
      && props.Set<int>(tag::p_factor, crypt_ftr.p_factor)
      && props.Set<std::string>(tag::keymaster_blob,
                                std::string((const char*) crypt_ftr.keymaster_blob,
                                            crypt_ftr.keymaster_blob_size))
      && props.Set<std::string>(tag::scrypted_intermediate_key,
                                std::string((const char*) crypt_ftr.scrypted_intermediate_key,
                                            SCRYPT_LEN));
    return success ? 0 : -1;
}

static int get_crypt_ftr_and_key(crypt_mnt_ftr& crypt_ftr,
                                 const UnencryptedProperties& props)
{
    memset(&crypt_ftr, 0, sizeof(crypt_ftr));
    crypt_ftr.magic = props.Get<int>(tag::magic);
    crypt_ftr.major_version = props.Get<int>(tag::major_version);
    crypt_ftr.minor_version = props.Get<int>(tag::minor_version);
    crypt_ftr.ftr_size = sizeof(crypt_ftr);
    crypt_ftr.flags = props.Get<int>(tag::flags);
    crypt_ftr.crypt_type = props.Get<int>(tag::crypt_type);
    crypt_ftr.failed_decrypt_count = props.Get<int>(tag::failed_decrypt_count);
    std::string crypto_type_name = props.Get<std::string>(tag::crypto_type_name);
    strlcpy(reinterpret_cast<char*>(crypt_ftr.crypto_type_name),
            crypto_type_name.c_str(),
            sizeof(crypt_ftr.crypto_type_name));
    std::string master_key = props.Get<std::string>(tag::master_key);
    crypt_ftr.keysize = master_key.size();
    if (crypt_ftr.keysize > sizeof(crypt_ftr.master_key)) {
        SLOGE("Master key size too long");
        return -1;
    }
    memcpy(crypt_ftr.master_key, &master_key[0], crypt_ftr.keysize);
    std::string salt = props.Get<std::string>(tag::salt);
    if (salt.size() != SALT_LEN) {
        SLOGE("Salt wrong length");
        return -1;
    }
    memcpy(crypt_ftr.salt, &salt[0], SALT_LEN);
    crypt_ftr.kdf_type = props.Get<int>(tag::kdf_type);
    crypt_ftr.N_factor = props.Get<int>(tag::N_factor);
    crypt_ftr.r_factor = props.Get<int>(tag::r_factor);
    crypt_ftr.p_factor = props.Get<int>(tag::p_factor);
    std::string keymaster_blob = props.Get<std::string>(tag::keymaster_blob);
    crypt_ftr.keymaster_blob_size = keymaster_blob.size();
    if (crypt_ftr.keymaster_blob_size > sizeof(crypt_ftr.keymaster_blob)) {
        SLOGE("Keymaster blob too long");
        return -1;
    }
    memcpy(crypt_ftr.keymaster_blob, &keymaster_blob[0],
           crypt_ftr.keymaster_blob_size);
    std::string scrypted_intermediate_key = props.Get<std::string>(tag::scrypted_intermediate_key);
    if (scrypted_intermediate_key.size() != SCRYPT_LEN) {
        SLOGE("scrypted intermediate key wrong length");
        return -1;
    }
    memcpy(crypt_ftr.scrypted_intermediate_key, &scrypted_intermediate_key[0],
           SCRYPT_LEN);

    return 0;
}

static UnencryptedProperties GetProps(const char* path)
{
    return UnencryptedProperties(path);
}

static UnencryptedProperties GetAltProps(const char* path)
{
    return UnencryptedProperties((std::string() + path + "/tmp_mnt").c_str());
}

static UnencryptedProperties GetPropsOrAltProps(const char* path)
{
    UnencryptedProperties props = GetProps(path);
    if (props.OK()) {
        return props;
    }
    return GetAltProps(path);
}

int e4crypt_enable(const char* path)
{
    // Already enabled?
    if (s_key_store.find(path) != s_key_store.end()) {
        return 0;
    }

    // Not an encryptable device?
    UnencryptedProperties key_props = GetProps(path).GetChild(properties::key);
    if (!key_props.OK()) {
        return 0;
    }

    if (key_props.Get<std::string>(tag::master_key).empty()) {
        crypt_mnt_ftr ftr;
        if (cryptfs_create_default_ftr(&ftr, key_length)) {
            SLOGE("Failed to create crypto footer");
            return -1;
        }

        // Scrub fields not used by ext4enc
        ftr.persist_data_offset[0] = 0;
        ftr.persist_data_offset[1] = 0;
        ftr.persist_data_size = 0;

        if (put_crypt_ftr_and_key(ftr, key_props)) {
            SLOGE("Failed to write crypto footer");
            return -1;
        }

        crypt_mnt_ftr ftr2;
        if (get_crypt_ftr_and_key(ftr2, key_props)) {
            SLOGE("Failed to read crypto footer back");
            return -1;
        }

        if (memcmp(&ftr, &ftr2, sizeof(ftr)) != 0) {
            SLOGE("Crypto footer not correctly written");
            return -1;
        }
    }

    if (!UnencryptedProperties(path).Remove(properties::ref)) {
        SLOGE("Failed to remove key ref");
        return -1;
    }

    return e4crypt_check_passwd(path, "");
}

int e4crypt_change_password(const char* path, int crypt_type,
                            const char* password)
{
    SLOGI("e4crypt_change_password");
    auto key_props = GetProps(path).GetChild(properties::key);

    crypt_mnt_ftr ftr;
    if (get_crypt_ftr_and_key(ftr, key_props)) {
        SLOGE("Failed to read crypto footer back");
        return -1;
    }

    auto mki = s_key_store.find(path);
    if (mki == s_key_store.end()) {
        SLOGE("No stored master key - can't change password");
        return -1;
    }

    const unsigned char* master_key_bytes
        = reinterpret_cast<const unsigned char*>(&mki->second.master_key[0]);

    if (cryptfs_set_password(&ftr, password, master_key_bytes)) {
        SLOGE("Failed to set password");
        return -1;
    }

    ftr.crypt_type = crypt_type;

    if (put_crypt_ftr_and_key(ftr, key_props)) {
        SLOGE("Failed to write crypto footer");
        return -1;
    }

    if (!UnencryptedProperties(path).Set(properties::is_default,
                            crypt_type == CRYPT_TYPE_DEFAULT)) {
        SLOGE("Failed to update default flag");
        return -1;
    }

    return 0;
}

int e4crypt_crypto_complete(const char* path)
{
    SLOGI("ext4 crypto complete called on %s", path);
    auto key_props = GetPropsOrAltProps(path).GetChild(properties::key);
    if (key_props.Get<std::string>(tag::master_key).empty()) {
        SLOGI("No master key, so not ext4enc");
        return -1;
    }

    return 0;
}

// Get raw keyref - used to make keyname and to pass to ioctl
static std::string generate_key_ref(const char* key, int length)
{
    SHA512_CTX c;

    SHA512_Init(&c);
    SHA512_Update(&c, key, length);
    unsigned char key_ref1[SHA512_LENGTH];
    SHA512_Final(key_ref1, &c);

    SHA512_Init(&c);
    SHA512_Update(&c, key_ref1, SHA512_LENGTH);
    unsigned char key_ref2[SHA512_LENGTH];
    SHA512_Final(key_ref2, &c);

    return std::string((char*)key_ref2, EXT4_KEY_DESCRIPTOR_SIZE);
}

int e4crypt_check_passwd(const char* path, const char* password)
{
    SLOGI("e4crypt_check_password");
    auto props = GetPropsOrAltProps(path);
    auto key_props = props.GetChild(properties::key);

    crypt_mnt_ftr ftr;
    if (get_crypt_ftr_and_key(ftr, key_props)) {
        SLOGE("Failed to read crypto footer back");
        return -1;
    }

    unsigned char master_key_bytes[key_length / 8];
    if (cryptfs_get_master_key (&ftr, password, master_key_bytes)){
        SLOGI("Incorrect password");
        ftr.failed_decrypt_count++;
        if (put_crypt_ftr_and_key(ftr, key_props)) {
            SLOGW("Failed to update failed_decrypt_count");
        }
        return ftr.failed_decrypt_count;
    }

    if (ftr.failed_decrypt_count) {
        ftr.failed_decrypt_count = 0;
        if (put_crypt_ftr_and_key(ftr, key_props)) {
            SLOGW("Failed to reset failed_decrypt_count");
        }
    }
    std::string master_key(reinterpret_cast<char*>(master_key_bytes),
                           sizeof(master_key_bytes));

    struct timespec now;
    clock_gettime(CLOCK_BOOTTIME, &now);
    s_key_store[path] = keys{master_key, password,
                             now.tv_sec + password_max_age_seconds};
    auto raw_ref = e4crypt_install_key(master_key);
    if (raw_ref.empty()) {
        return -1;
    }

    // Save reference to key so we can set policy later
    if (!props.Set(properties::ref, raw_ref)) {
        SLOGE("Cannot save key reference");
        return -1;
    }

    return 0;
}

static ext4_encryption_key fill_key(const std::string &key)
{
    // ext4enc:TODO Currently raw key is required to be of length
    // sizeof(ext4_key.raw) == EXT4_MAX_KEY_SIZE, so zero pad to
    // this length. Change when kernel bug is fixed.
    ext4_encryption_key ext4_key = {EXT4_ENCRYPTION_MODE_AES_256_XTS,
                                    {0},
                                    sizeof(ext4_key.raw)};
    memset(ext4_key.raw, 0, sizeof(ext4_key.raw));
    static_assert(key_length / 8 <= sizeof(ext4_key.raw),
                  "Key too long!");
    memcpy(ext4_key.raw, &key[0], key.size());
    return ext4_key;
}

static std::string keyname(const std::string &raw_ref)
{
    std::ostringstream o;
    o << "ext4:";
    for (auto i = raw_ref.begin(); i != raw_ref.end(); ++i) {
        o << std::hex << std::setw(2) << std::setfill('0') << (int)*i;
    }
    return o.str();
}

// Get the keyring we store all keys in
static key_serial_t e4crypt_keyring()
{
    return keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "e4crypt", 0);
}

static int e4crypt_install_key(const ext4_encryption_key &ext4_key, const std::string &ref)
{
    key_serial_t device_keyring = e4crypt_keyring();
    SLOGI("Found device_keyring - id is %d", device_keyring);
    key_serial_t key_id = add_key("logon", ref.c_str(),
                                  (void*)&ext4_key, sizeof(ext4_key),
                                  device_keyring);
    if (key_id == -1) {
        SLOGE("Failed to insert key into keyring with error %s",
              strerror(errno));
        return -1;
    }
    SLOGI("Added key %d (%s) to keyring %d in process %d",
          key_id, ref.c_str(), device_keyring, getpid());
    return 0;
}

// Install password into global keyring
// Return raw key reference for use in policy
static std::string e4crypt_install_key(const std::string &key)
{
    auto ext4_key = fill_key(key);
    auto raw_ref = generate_key_ref(ext4_key.raw, ext4_key.size);
    auto ref = keyname(raw_ref);
    if (e4crypt_install_key(ext4_key, ref) == -1) {
        return "";
    }
    return raw_ref;
}

int e4crypt_restart(const char* path)
{
    SLOGI("e4crypt_restart");

    int rc = 0;

    SLOGI("ext4 restart called on %s", path);
    property_set("vold.decrypt", "trigger_reset_main");
    SLOGI("Just asked init to shut down class main");
    sleep(2);

    std::string tmp_path = std::string() + path + "/tmp_mnt";

    rc = wait_and_unmount(tmp_path.c_str(), true);
    if (rc) {
        SLOGE("umount %s failed with rc %d, msg %s",
              tmp_path.c_str(), rc, strerror(errno));
        return rc;
    }

    rc = wait_and_unmount(path, true);
    if (rc) {
        SLOGE("umount %s failed with rc %d, msg %s",
              path, rc, strerror(errno));
        return rc;
    }

    return 0;
}

int e4crypt_get_password_type(const char* path)
{
    SLOGI("e4crypt_get_password_type");
    return GetPropsOrAltProps(path).GetChild(properties::key)
      .Get<int>(tag::crypt_type, CRYPT_TYPE_DEFAULT);
}

const char* e4crypt_get_password(const char* path)
{
    SLOGI("e4crypt_get_password");

    auto i = s_key_store.find(path);
    if (i == s_key_store.end()) {
        return 0;
    }

    struct timespec now;
    clock_gettime(CLOCK_BOOTTIME, &now);
    if (i->second.expiry_time < now.tv_sec) {
        e4crypt_clear_password(path);
        return 0;
    }

    return i->second.password.c_str();
}

void e4crypt_clear_password(const char* path)
{
    SLOGI("e4crypt_clear_password");

    auto i = s_key_store.find(path);
    if (i == s_key_store.end()) {
        return;
    }

    memset(&i->second.password[0], 0, i->second.password.size());
    i->second.password = std::string();
}

int e4crypt_get_field(const char* path, const char* fieldname,
                      char* value, size_t len)
{
    auto v = GetPropsOrAltProps(path).GetChild(properties::props)
      .Get<std::string>(fieldname);

    if (v == "") {
        return CRYPTO_GETFIELD_ERROR_NO_FIELD;
    }

    if (v.length() >= len) {
        return CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
    }

    strlcpy(value, v.c_str(), len);
    return 0;
}

int e4crypt_set_field(const char* path, const char* fieldname,
                      const char* value)
{
    return GetPropsOrAltProps(path).GetChild(properties::props)
        .Set(fieldname, std::string(value)) ? 0 : -1;
}

static std::string get_key_path(
    const char *mount_path,
    const char *user_handle)
{
    // ext4enc:TODO get the path properly
    auto key_dir = android::base::StringPrintf("%s/misc/vold/user_keys",
        mount_path);
    if (mkdir(key_dir.c_str(), 0700) < 0 && errno != EEXIST) {
        SLOGE("Unable to create %s (%s)", key_dir.c_str(), strerror(errno));
        return "";
    }
    return key_dir + "/" + user_handle;
}

// ext4enc:TODO this can't be the only place keys are read from /dev/urandom
// we should unite those places.
static std::string e4crypt_get_key(
    const std::string &key_path,
    bool create_if_absent)
{
    std::string content;
    if (android::base::ReadFileToString(key_path, &content)) {
        if (content.size() != key_length/8) {
            SLOGE("Wrong size key %zu in  %s", content.size(), key_path.c_str());
            return "";
        }
        return content;
    }
    if (!create_if_absent) {
        SLOGE("No key found in %s", key_path.c_str());
        return "";
    }
    std::ifstream urandom("/dev/urandom");
    if (!urandom) {
        SLOGE("Unable to open /dev/urandom (%s)", strerror(errno));
        return "";
    }
    char key_bytes[key_length / 8];
    errno = 0;
    urandom.read(key_bytes, sizeof(key_bytes));
    if (!urandom) {
        SLOGE("Unable to read key from /dev/urandom (%s)", strerror(errno));
        return "";
    }
    std::string key(key_bytes, sizeof(key_bytes));
    if (!android::base::WriteStringToFile(key, key_path)) {
        SLOGE("Unable to write key to %s (%s)",
                key_path.c_str(), strerror(errno));
        return "";
    }
    return key;
}

static int e4crypt_set_user_policy(const char *mount_path, const char *user_handle,
                            const char *path, bool create_if_absent)
{
    SLOGD("e4crypt_set_user_policy for %s", user_handle);
    auto user_key = e4crypt_get_key(
        get_key_path(mount_path, user_handle),
        create_if_absent);
    if (user_key.empty()) {
        return -1;
    }
    auto raw_ref = e4crypt_install_key(user_key);
    if (raw_ref.empty()) {
        return -1;
    }
    return do_policy_set(path, raw_ref.c_str(), raw_ref.size());
}

int e4crypt_create_new_user_dir(const char *user_handle, const char *path) {
    SLOGD("e4crypt_create_new_user_dir(\"%s\", \"%s\")", user_handle, path);
    if (mkdir(path, S_IRWXU | S_IRWXG | S_IXOTH) < 0) {
        return -1;
    }
    if (chmod(path, S_IRWXU | S_IRWXG | S_IXOTH) < 0) {
        return -1;
    }
    if (chown(path, AID_SYSTEM, AID_SYSTEM) < 0) {
        return -1;
    }
    if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
        // ext4enc:TODO handle errors from this.
        e4crypt_set_user_policy(DATA_MNT_POINT, user_handle, path, true);
    }
    return 0;
}

static bool is_numeric(const char *name) {
    for (const char *p = name; *p != '\0'; p++) {
        if (!isdigit(*p))
            return false;
    }
    return true;
}

int e4crypt_set_user_crypto_policies(const char *dir)
{
    if (e4crypt_crypto_complete(DATA_MNT_POINT) != 0) {
        return 0;
    }
    SLOGD("e4crypt_set_user_crypto_policies");
    std::unique_ptr<DIR, int(*)(DIR*)> dirp(opendir(dir), closedir);
    if (!dirp) {
        SLOGE("Unable to read directory %s, error %s\n",
            dir, strerror(errno));
        return -1;
    }
    for (;;) {
        struct dirent *result = readdir(dirp.get());
        if (!result) {
            // ext4enc:TODO check errno
            break;
        }
        if (result->d_type != DT_DIR || !is_numeric(result->d_name)) {
            continue; // skips user 0, which is a symlink
        }
        auto user_dir = std::string() + dir + "/" + result->d_name;
        // ext4enc:TODO don't hardcode /data
        if (e4crypt_set_user_policy("/data", result->d_name,
                user_dir.c_str(), false)) {
            // ext4enc:TODO If this function fails, stop the boot: we must
            // deliver on promised encryption.
            SLOGE("Unable to set policy on %s\n", user_dir.c_str());
        }
    }
    return 0;
}

int e4crypt_delete_user_key(const char *user_handle) {
    SLOGD("e4crypt_delete_user_key(\"%s\")", user_handle);
    auto key_path = get_key_path(DATA_MNT_POINT, user_handle);
    auto key = e4crypt_get_key(key_path, false);
    auto ext4_key = fill_key(key);
    auto ref = keyname(generate_key_ref(ext4_key.raw, ext4_key.size));
    auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0);
    if (keyctl_revoke(key_serial) == 0) {
        SLOGD("Revoked key with serial %ld ref %s\n", key_serial, ref.c_str());
    } else {
        SLOGE("Failed to revoke key with serial %ld ref %s: %s\n",
            key_serial, ref.c_str(), strerror(errno));
    }
    int pid = fork();
    if (pid < 0) {
        SLOGE("Unable to fork: %s", strerror(errno));
        return -1;
    }
    if (pid == 0) {
        SLOGD("Forked for secdiscard");
        execl("/system/bin/secdiscard",
            "/system/bin/secdiscard",
            key_path.c_str(),
            NULL);
        SLOGE("Unable to launch secdiscard on %s: %s\n", key_path.c_str(),
            strerror(errno));
        exit(-1);
    }
    // ext4enc:TODO reap the zombie
    return 0;
}
