/*
 * Copyright (C) 2015 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 "Ext4Crypt.h"

#include "Utils.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/fs.h>
#include <cutils/log.h>
#include <cutils/klog.h>

#include <base/file.h>
#include <base/logging.h>
#include <base/stringprintf.h>

using android::base::StringPrintf;

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, userid_t user_id) {
    // ext4enc:TODO get the path properly
    auto key_dir = StringPrintf("%s/misc/vold/user_keys", mount_path);
    if (fs_prepare_dir(key_dir.c_str(), 0700, AID_ROOT, AID_ROOT)) {
        PLOG(ERROR) << "Failed to prepare " << key_dir;
        return "";
    }
    return StringPrintf("%s/%d", key_dir.c_str(), user_id);
}

// 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, userid_t user_id,
        const char *path, bool create_if_absent) {
    SLOGD("e4crypt_set_user_policy for %d", user_id);
    auto user_key = e4crypt_get_key(get_key_path(mount_path, user_id),
            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());
}

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_id = atoi(result->d_name);
        auto user_dir = std::string() + dir + "/" + result->d_name;
        // ext4enc:TODO don't hardcode /data
        if (e4crypt_set_user_policy("/data", user_id, 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_create_user_key(userid_t user_id) {
    SLOGD("e4crypt_create_user_key(%d)", user_id);
    // TODO: create second key for user_de data
    if (e4crypt_get_key(get_key_path(DATA_MNT_POINT, user_id), true).empty()) {
        return -1;
    } else {
        return 0;
    }
}

int e4crypt_destroy_user_key(userid_t user_id) {
    SLOGD("e4crypt_destroy_user_key(%d)", user_id);
    // TODO: destroy second key for user_de data
    auto key_path = get_key_path(DATA_MNT_POINT, user_id);
    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;
}

int e4crypt_unlock_user_key(userid_t user_id, const char* token) {
    if (property_get_bool("vold.emulate_fbe", false)) {
        // When in emulation mode, we just use chmod
        if (chmod(android::vold::BuildDataSystemCePath(user_id).c_str(), 0771) ||
                chmod(android::vold::BuildDataUserPath(nullptr, user_id).c_str(), 0771)) {
            PLOG(ERROR) << "Failed to unlock user " << user_id;
            return -1;
        }
    } else {
        auto user_key = e4crypt_get_key(get_key_path(DATA_MNT_POINT, user_id), false);
        if (user_key.empty()) {
            return -1;
        }
        auto raw_ref = e4crypt_install_key(user_key);
        if (raw_ref.empty()) {
            return -1;
        }
    }
    return 0;
}

int e4crypt_lock_user_key(userid_t user_id) {
    if (property_get_bool("vold.emulate_fbe", false)) {
        // When in emulation mode, we just use chmod
        if (chmod(android::vold::BuildDataSystemCePath(user_id).c_str(), 0000) ||
                chmod(android::vold::BuildDataUserPath(nullptr, user_id).c_str(), 0000)) {
            PLOG(ERROR) << "Failed to lock user " << user_id;
            return -1;
        }
    } else {
        // TODO: remove from kernel keyring
    }
    return 0;
}

int e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id) {
    std::string system_ce_path(android::vold::BuildDataSystemCePath(user_id));
    std::string user_ce_path(android::vold::BuildDataUserPath(volume_uuid, user_id));
    std::string user_de_path(android::vold::BuildDataUserDePath(volume_uuid, user_id));

    if (fs_prepare_dir(system_ce_path.c_str(), 0700, AID_SYSTEM, AID_SYSTEM)) {
        PLOG(ERROR) << "Failed to prepare " << system_ce_path;
        return -1;
    }
    if (fs_prepare_dir(user_ce_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) {
        PLOG(ERROR) << "Failed to prepare " << user_ce_path;
        return -1;
    }
    if (fs_prepare_dir(user_de_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM)) {
        PLOG(ERROR) << "Failed to prepare " << user_de_path;
        return -1;
    }

    if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
        if (e4crypt_set_user_policy(DATA_MNT_POINT, user_id, system_ce_path.c_str(), true)
                || e4crypt_set_user_policy(DATA_MNT_POINT, user_id, user_ce_path.c_str(), true)) {
            return -1;
        }
    }

    return 0;
}
