/*
 * 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 "fscrypt/fscrypt.h"

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <asm/ioctl.h>
#include <cutils/properties.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/fscrypt.h>
#include <logwrap/logwrap.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utils/misc.h>

#include <array>
#include <string>
#include <vector>

using namespace std::string_literals;

/* modes not supported by upstream kernel, so not in <linux/fscrypt.h> */
#define FSCRYPT_MODE_AES_256_HEH 126
#define FSCRYPT_MODE_PRIVATE 127

#define HEX_LOOKUP "0123456789abcdef"

struct ModeLookupEntry {
    std::string name;
    int id;
};

static const auto contents_modes = std::vector<ModeLookupEntry>{
        {"aes-256-xts"s, FSCRYPT_MODE_AES_256_XTS},
        {"software"s, FSCRYPT_MODE_AES_256_XTS},
        {"adiantum"s, FSCRYPT_MODE_ADIANTUM},
        {"ice"s, FSCRYPT_MODE_PRIVATE},
};

static const auto filenames_modes = std::vector<ModeLookupEntry>{
        {"aes-256-cts"s, FSCRYPT_MODE_AES_256_CTS},
        {"aes-256-heh"s, FSCRYPT_MODE_AES_256_HEH},
        {"adiantum"s, FSCRYPT_MODE_ADIANTUM},
};

static bool LookupModeByName(const std::vector<struct ModeLookupEntry>& modes,
                             const std::string& name, int* result) {
    for (const auto& e : modes) {
        if (e.name == name) {
            *result = e.id;
            return true;
        }
    }
    return false;
}

static bool LookupModeById(const std::vector<struct ModeLookupEntry>& modes, int id,
                           std::string* result) {
    for (const auto& e : modes) {
        if (e.id == id) {
            *result = e.name;
            return true;
        }
    }
    return false;
}

bool fscrypt_is_native() {
    char value[PROPERTY_VALUE_MAX];
    property_get("ro.crypto.type", value, "none");
    return !strcmp(value, "file");
}

namespace android {
namespace fscrypt {

static void log_ls(const char* dirname) {
    std::array<const char*, 3> argv = {"ls", "-laZ", dirname};
    int status = 0;
    auto res =
        logwrap_fork_execvp(argv.size(), argv.data(), &status, false, LOG_ALOG, false, nullptr);
    if (res != 0) {
        PLOG(ERROR) << argv[0] << " " << argv[1] << " " << argv[2] << "failed";
        return;
    }
    if (!WIFEXITED(status)) {
        LOG(ERROR) << argv[0] << " " << argv[1] << " " << argv[2]
                   << " did not exit normally, status: " << status;
        return;
    }
    if (WEXITSTATUS(status) != 0) {
        LOG(ERROR) << argv[0] << " " << argv[1] << " " << argv[2]
                   << " returned failure: " << WEXITSTATUS(status);
        return;
    }
}

void BytesToHex(const std::string& bytes, std::string* hex) {
    hex->clear();
    for (char c : bytes) {
        *hex += HEX_LOOKUP[(c & 0xF0) >> 4];
        *hex += HEX_LOOKUP[c & 0x0F];
    }
}

static bool fscrypt_is_encrypted(int fd) {
    fscrypt_policy_v1 policy;

    // success => encrypted with v1 policy
    // EINVAL => encrypted with v2 policy
    // ENODATA => not encrypted
    return ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &policy) == 0 || errno == EINVAL;
}

unsigned int GetFirstApiLevel() {
    return android::base::GetUintProperty<unsigned int>("ro.product.first_api_level", 0);
}

bool OptionsToString(const EncryptionOptions& options, std::string* options_string) {
    return OptionsToStringForApiLevel(GetFirstApiLevel(), options, options_string);
}

bool OptionsToStringForApiLevel(unsigned int first_api_level, const EncryptionOptions& options,
                                std::string* options_string) {
    std::string contents_mode, filenames_mode;
    if (!LookupModeById(contents_modes, options.contents_mode, &contents_mode)) {
        return false;
    }
    if (!LookupModeById(filenames_modes, options.filenames_mode, &filenames_mode)) {
        return false;
    }
    *options_string = contents_mode + ":" + filenames_mode + ":v" + std::to_string(options.version);
    if ((options.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64)) {
        *options_string += "+inlinecrypt_optimized";
    }
    if ((options.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
        *options_string += "+emmc_optimized";
    }
    if (options.use_hw_wrapped_key) {
        *options_string += "+wrappedkey_v0";
    }

    EncryptionOptions options_check;
    if (!ParseOptionsForApiLevel(first_api_level, *options_string, &options_check)) {
        LOG(ERROR) << "Internal error serializing options as string: " << *options_string;
        return false;
    }
    if (options != options_check) {
        LOG(ERROR) << "Internal error serializing options as string, round trip failed: "
                   << *options_string;
        return false;
    }
    return true;
}

bool ParseOptions(const std::string& options_string, EncryptionOptions* options) {
    return ParseOptionsForApiLevel(GetFirstApiLevel(), options_string, options);
}

bool ParseOptionsForApiLevel(unsigned int first_api_level, const std::string& options_string,
                             EncryptionOptions* options) {
    auto parts = android::base::Split(options_string, ":");
    if (parts.size() > 3) {
        LOG(ERROR) << "Invalid encryption options: " << options;
        return false;
    }
    options->contents_mode = FSCRYPT_MODE_AES_256_XTS;
    if (parts.size() > 0 && !parts[0].empty()) {
        if (!LookupModeByName(contents_modes, parts[0], &options->contents_mode)) {
            LOG(ERROR) << "Invalid file contents encryption mode: " << parts[0];
            return false;
        }
    }
    if (options->contents_mode == FSCRYPT_MODE_ADIANTUM) {
        options->filenames_mode = FSCRYPT_MODE_ADIANTUM;
    } else {
        options->filenames_mode = FSCRYPT_MODE_AES_256_CTS;
    }
    if (parts.size() > 1 && !parts[1].empty()){
        if (!LookupModeByName(filenames_modes, parts[1], &options->filenames_mode)) {
            LOG(ERROR) << "Invalid file names encryption mode: " << parts[1];
            return false;
        }
    }
    // Default to v2 after Q
    constexpr unsigned int pre_gki_level = 29;
    auto is_gki = first_api_level > pre_gki_level;
    options->version = is_gki ? 2 : 1;
    options->flags = 0;
    options->use_hw_wrapped_key = false;
    if (parts.size() > 2 && !parts[2].empty()) {
        auto flags = android::base::Split(parts[2], "+");
        for (const auto& flag : flags) {
            if (flag == "v1") {
                options->version = 1;
            } else if (flag == "v2") {
                options->version = 2;
            } else if (flag == "inlinecrypt_optimized") {
                options->flags |= FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64;
            } else if (flag == "emmc_optimized") {
                options->flags |= FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32;
            } else if (flag == "wrappedkey_v0") {
                options->use_hw_wrapped_key = true;
            } else {
                LOG(ERROR) << "Unknown flag: " << flag;
                return false;
            }
        }
    }

    // In the original setting of v1 policies and AES-256-CTS we used 4-byte
    // padding of filenames, so retain that on old first_api_levels.
    //
    // For everything else, use 16-byte padding.  This is more secure (it helps
    // hide the length of filenames), and it makes the inputs evenly divisible
    // into cipher blocks which is more efficient for encryption and decryption.
    if (!is_gki && options->version == 1 && options->filenames_mode == FSCRYPT_MODE_AES_256_CTS) {
        options->flags |= FSCRYPT_POLICY_FLAGS_PAD_4;
    } else {
        options->flags |= FSCRYPT_POLICY_FLAGS_PAD_16;
    }

    // Use DIRECT_KEY for Adiantum, since it's much more efficient but just as
    // secure since Android doesn't reuse the same master key for multiple
    // encryption modes.
    if (options->contents_mode == FSCRYPT_MODE_ADIANTUM) {
        if (options->filenames_mode != FSCRYPT_MODE_ADIANTUM) {
            LOG(ERROR) << "Adiantum must be both contents and filenames mode or neither, invalid options: " << options_string;
            return false;
        }
        options->flags |= FSCRYPT_POLICY_FLAG_DIRECT_KEY;
    } else if (options->filenames_mode == FSCRYPT_MODE_ADIANTUM) {
        LOG(ERROR) << "Adiantum must be both contents and filenames mode or neither, invalid options: " << options_string;
        return false;
    }

    // IV generation methods are mutually exclusive
    int iv_methods = 0;
    iv_methods += !!(options->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64);
    iv_methods += !!(options->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32);
    iv_methods += !!(options->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY);
    if (iv_methods > 1) {
        LOG(ERROR) << "At most one IV generation method can be set, invalid options: "
                   << options_string;
        return false;
    }

    return true;
}

static std::string PolicyDebugString(const EncryptionPolicy& policy) {
    std::stringstream ss;
    std::string ref_hex;
    BytesToHex(policy.key_raw_ref, &ref_hex);
    ss << ref_hex;
    ss << " v" << policy.options.version;
    ss << " modes " << policy.options.contents_mode << "/" << policy.options.filenames_mode;
    ss << std::hex << " flags 0x" << policy.options.flags;
    return ss.str();
}

bool EnsurePolicy(const EncryptionPolicy& policy, const std::string& directory) {
    union {
        fscrypt_policy_v1 v1;
        fscrypt_policy_v2 v2;
    } kern_policy;
    memset(&kern_policy, 0, sizeof(kern_policy));

    switch (policy.options.version) {
        case 1:
            if (policy.key_raw_ref.size() != FSCRYPT_KEY_DESCRIPTOR_SIZE) {
                LOG(ERROR) << "Invalid key descriptor length for v1 policy: "
                           << policy.key_raw_ref.size();
                return false;
            }
            // Careful: FSCRYPT_POLICY_V1 is actually 0 in the API, so make sure
            // to use it here instead of a literal 1.
            kern_policy.v1.version = FSCRYPT_POLICY_V1;
            kern_policy.v1.contents_encryption_mode = policy.options.contents_mode;
            kern_policy.v1.filenames_encryption_mode = policy.options.filenames_mode;
            kern_policy.v1.flags = policy.options.flags;
            policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v1.master_key_descriptor),
                                    FSCRYPT_KEY_DESCRIPTOR_SIZE);
            break;
        case 2:
            if (policy.key_raw_ref.size() != FSCRYPT_KEY_IDENTIFIER_SIZE) {
                LOG(ERROR) << "Invalid key identifier length for v2 policy: "
                           << policy.key_raw_ref.size();
                return false;
            }
            kern_policy.v2.version = FSCRYPT_POLICY_V2;
            kern_policy.v2.contents_encryption_mode = policy.options.contents_mode;
            kern_policy.v2.filenames_encryption_mode = policy.options.filenames_mode;
            kern_policy.v2.flags = policy.options.flags;
            policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v2.master_key_identifier),
                                    FSCRYPT_KEY_IDENTIFIER_SIZE);
            break;
        default:
            LOG(ERROR) << "Invalid encryption policy version: " << policy.options.version;
            return false;
    }

    android::base::unique_fd fd(open(directory.c_str(), O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
    if (fd == -1) {
        PLOG(ERROR) << "Failed to open directory " << directory;
        return false;
    }

    bool already_encrypted = fscrypt_is_encrypted(fd);

    // FS_IOC_SET_ENCRYPTION_POLICY will set the policy if the directory is
    // unencrypted; otherwise it will verify that the existing policy matches.
    // Setting the policy will fail if the directory is already nonempty.
    if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, &kern_policy) != 0) {
        std::string reason;
        switch (errno) {
            case EEXIST:
                reason = "The directory already has a different encryption policy.";
                break;
            default:
                reason = strerror(errno);
                break;
        }
        LOG(ERROR) << "Failed to set encryption policy of " << directory << " to "
                   << PolicyDebugString(policy) << ": " << reason;
        if (errno == ENOTEMPTY) {
            log_ls(directory.c_str());
        }
        return false;
    }

    if (already_encrypted) {
        LOG(INFO) << "Verified that " << directory << " has the encryption policy "
                  << PolicyDebugString(policy);
    } else {
        LOG(INFO) << "Encryption policy of " << directory << " set to "
                  << PolicyDebugString(policy);
    }
    return true;
}

}  // namespace fscrypt
}  // namespace android
