/*
 Copyright (c) 2020 Intel Corporation

 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 "password.hpp"

#include "xyz/openbmc_project/BIOSConfig/Common/error.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

#include <boost/algorithm/hex.hpp>
#include <boost/asio.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>

#include <fstream>
#include <iostream>

namespace bios_config_pwd
{
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using namespace sdbusplus::xyz::openbmc_project::BIOSConfig::Common::Error;

bool Password::compareDigest(const EVP_MD* digestFunc, size_t digestLen,
                             const std::array<uint8_t, maxHashSize>& expected,
                             const std::array<uint8_t, maxSeedSize>& seed,
                             const std::string& rawData)
{
    std::vector<uint8_t> output(digestLen);
    unsigned int hashLen = digestLen;

    if (!PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(rawData.c_str()),
                           rawData.length() + 1,
                           reinterpret_cast<const unsigned char*>(seed.data()),
                           seed.size(), iterValue, digestFunc, hashLen,
                           output.data()))
    {
        lg2::error("Generate PKCS5_PBKDF2_HMAC Integrity Check Value failed");
        throw InternalFailure();
    }

    if (std::memcmp(output.data(), expected.data(),
                    output.size() * sizeof(uint8_t)) == 0)
    {
        return true;
    }

    return false;
}

bool Password::isMatch(const std::array<uint8_t, maxHashSize>& expected,
                       const std::array<uint8_t, maxSeedSize>& seed,
                       const std::string& rawData, const std::string& algo)
{
    lg2::error("isMatch");

    if (algo == "SHA256")
    {
        return compareDigest(EVP_sha256(), SHA256_DIGEST_LENGTH, expected, seed,
                             rawData);
    }

    if (algo == "SHA384")
    {
        return compareDigest(EVP_sha384(), SHA384_DIGEST_LENGTH, expected, seed,
                             rawData);
    }

    return false;
}

bool Password::getParam(std::array<uint8_t, maxHashSize>& orgUsrPwdHash,
                        std::array<uint8_t, maxHashSize>& orgAdminPwdHash,
                        std::array<uint8_t, maxSeedSize>& seed,
                        std::string& hashAlgo)
{
    try
    {
        nlohmann::json json = nullptr;
        std::ifstream ifs(seedFile.c_str());
        if (ifs.is_open())
        {
            try
            {
                json = nlohmann::json::parse(ifs, nullptr, false);
            }
            catch (const nlohmann::json::parse_error& e)
            {
                lg2::error("Failed to parse JSON file: {ERROR}", "ERROR", e);
                return false;
            }

            if (!json.is_discarded())
            {
                orgUsrPwdHash = json["UserPwdHash"];
                orgAdminPwdHash = json["AdminPwdHash"];
                seed = json["Seed"];
                hashAlgo = json["HashAlgo"];
            }
        }
    }
    catch (nlohmann::detail::exception& e)
    {
        lg2::error("Failed to parse JSON file: {ERROR}", "ERROR", e);
        return false;
    }

    return true;
}

bool Password::verifyIntegrityCheck(
    std::string& newPassword, std::array<uint8_t, maxSeedSize>& seed,
    unsigned int mdLen, const EVP_MD* digestFunc)
{
    mNewPwdHash.fill(0);

    if (!PKCS5_PBKDF2_HMAC(reinterpret_cast<const char*>(newPassword.c_str()),
                           newPassword.length() + 1,
                           reinterpret_cast<const unsigned char*>(seed.data()),
                           seed.size(), iterValue, digestFunc, mdLen,
                           mNewPwdHash.data()))
    {
        lg2::error("Verify PKCS5_PBKDF2_HMAC Integrity Check failed");
        return false;
    }

    return true;
}

void Password::verifyPassword(std::string userName, std::string currentPassword,
                              std::string newPassword)
{
    if (fs::exists(seedFile.c_str()))
    {
        std::array<uint8_t, maxHashSize> orgUsrPwdHash;
        std::array<uint8_t, maxHashSize> orgAdminPwdHash;
        std::array<uint8_t, maxSeedSize> seed;
        std::string hashAlgo = "";

        if (getParam(orgUsrPwdHash, orgAdminPwdHash, seed, hashAlgo))
        {
            if (orgUsrPwdHash.empty() || orgAdminPwdHash.empty() ||
                seed.empty() || hashAlgo.empty())
            {
                return;
            }
        }
        else
        {
            throw InternalFailure();
        }

        if (userName == "AdminPassword")
        {
            if (!isMatch(orgAdminPwdHash, seed, currentPassword, hashAlgo))
            {
                throw InvalidCurrentPassword();
            }
        }
        else
        {
            if (!isMatch(orgUsrPwdHash, seed, currentPassword, hashAlgo))
            {
                throw InvalidCurrentPassword();
            }
        }
        if (hashAlgo == "SHA256")
        {
            if (!verifyIntegrityCheck(newPassword, seed, 32, EVP_sha256()))
            {
                throw InternalFailure();
            }
        }
        if (hashAlgo == "SHA384")
        {
            if (!verifyIntegrityCheck(newPassword, seed, 48, EVP_sha384()))
            {
                throw InternalFailure();
            }
        }
        return;
    }
    throw InternalFailure();
}
void Password::changePassword(std::string userName, std::string currentPassword,
                              std::string newPassword)
{
    lg2::debug("BIOS config changePassword");
    verifyPassword(userName, currentPassword, newPassword);

    std::ifstream fs(seedFile.c_str());
    nlohmann::json json = nullptr;

    if (fs.is_open())
    {
        try
        {
            json = nlohmann::json::parse(fs, nullptr, false);
        }
        catch (const nlohmann::json::parse_error& e)
        {
            lg2::error("Failed to parse JSON file: {ERROR}", "ERROR", e);
            throw InternalFailure();
        }

        if (json.is_discarded())
        {
            throw InternalFailure();
        }
        json["AdminPwdHash"] = mNewPwdHash;
        json["IsAdminPwdChanged"] = true;

        std::ofstream ofs(seedFile.c_str(), std::ios::out);
        const auto& writeData = json.dump();
        ofs << writeData;
        ofs.close();
    }
    else
    {
        lg2::debug("Cannot open file stream");
        throw InternalFailure();
    }
}
Password::Password(sdbusplus::asio::object_server& objectServer,
                   std::shared_ptr<sdbusplus::asio::connection>& systemBus,
                   std::string persistPath) :
    sdbusplus::xyz::openbmc_project::BIOSConfig::server::Password(
        *systemBus, objectPathPwd),
    objServer(objectServer), systemBus(systemBus)
{
    lg2::debug("BIOS config password is running");
    try
    {
        fs::path biosDir(persistPath);
        fs::create_directories(biosDir);
        seedFile = biosDir / biosSeedFile;
    }
    catch (const fs::filesystem_error& e)
    {
        lg2::error("Failed to parse JSON file: {ERROR}", "ERROR", e);
        throw InternalFailure();
    }
}

} // namespace bios_config_pwd
