/*
// 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) :
    sdbusplus::xyz::openbmc_project::BIOSConfig::server::Password(
        *systemBus, objectPathPwd),
    objServer(objectServer), systemBus(systemBus)
{
    lg2::debug("BIOS config password is running");
    try
    {
        fs::path biosDir(BIOS_PERSIST_PATH);
        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
