blob: 0c2434748d2bf68db32a522b4747c34557b3aff5 [file] [log] [blame]
Kuiying Wang8f706212020-12-16 18:59:24 +08001/*
2// Copyright (c) 2020 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#include "password.hpp"
17
18#include "xyz/openbmc_project/BIOSConfig/Common/error.hpp"
19#include "xyz/openbmc_project/Common/error.hpp"
20
21#include <boost/algorithm/hex.hpp>
22#include <boost/asio.hpp>
23#include <phosphor-logging/elog-errors.hpp>
24#include <sdbusplus/asio/connection.hpp>
25#include <sdbusplus/asio/object_server.hpp>
26
27#include <fstream>
28#include <iostream>
29
30namespace bios_config_pwd
31{
32using namespace sdbusplus::xyz::openbmc_project::Common::Error;
33using namespace sdbusplus::xyz::openbmc_project::BIOSConfig::Common::Error;
34
35bool Password::isMatch(const std::string expected, const std::string seed,
36 const std::string rawData, const std::string algo)
37{
38 phosphor::logging::log<phosphor::logging::level::ERR>("isMatch");
39 if (algo == "SHA384")
40 {
41 phosphor::logging::log<phosphor::logging::level::ERR>("SHA384");
42 std::vector<uint8_t> output(SHA384_DIGEST_LENGTH);
43 unsigned int mdLen = 0;
44 if (HMAC(EVP_sha384(), seed.c_str(), seed.length(),
45 reinterpret_cast<const unsigned char*>(rawData.c_str()),
46 rawData.length(), output.data(), &mdLen) == NULL)
47 {
48 phosphor::logging::log<phosphor::logging::level::ERR>(
49 "Generate HMAC_SHA384 Integrity Check Value failed");
50 output.resize(0);
51 throw InternalFailure();
52 }
53 phosphor::logging::log<phosphor::logging::level::ERR>(expected.c_str());
54 std::string strOutput;
55 boost::algorithm::hex(output.begin(), output.end(),
56 std::back_inserter(strOutput));
57 phosphor::logging::log<phosphor::logging::level::ERR>(
58 strOutput.c_str());
59 if (expected == strOutput)
60 {
61 return true;
62 }
63 else
64 {
65 return false;
66 }
67 }
68 return false;
69}
70
71void Password::verifyPassword(std::string userName, std::string currentPassword,
72 std::string newPassword)
73{
74 if (fs::exists(seedFile.c_str()))
75 {
76 std::string userPassword = "";
77 std::string adminPassword = "";
78 std::string seed = "";
79 std::string hashAlgo = "";
80 try
81 {
82 std::ifstream ifs(seedFile.c_str());
83 nlohmann::json json;
84 ifs >> json;
85 userPassword = json["UserPwdHash"];
86 adminPassword = json["AdminPwdHash"];
87 seed = json["Seed"];
88 hashAlgo = json["HashAlgo"];
89 }
90 catch (nlohmann::detail::exception& e)
91 {
92 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
93 throw InternalFailure();
94 }
95 if (userName == "Administrator")
96 {
97 if (!isMatch(adminPassword, seed, currentPassword, hashAlgo))
98 {
99 throw InvalidCurrentPassword();
100 }
101 }
102 else
103 {
104 if (!isMatch(userPassword, seed, currentPassword, hashAlgo))
105 {
106 throw InvalidCurrentPassword();
107 }
108 }
109 if (hashAlgo == "SHA384")
110 {
111 std::vector<uint8_t> output(SHA384_DIGEST_LENGTH);
112 unsigned int mdLen = 0;
113 if (HMAC(
114 EVP_sha384(), seed.c_str(), seed.length(),
115 reinterpret_cast<const unsigned char*>(newPassword.c_str()),
116 newPassword.length(), output.data(), &mdLen) == NULL)
117 {
118 phosphor::logging::log<phosphor::logging::level::ERR>(
119 "Generate HMAC_SHA384 Integrity Check Value failed");
120 output.resize(0);
121 throw InternalFailure();
122 }
123 std::string strOutput;
124 boost::algorithm::hex(output.begin(), output.end(),
125 std::back_inserter(strOutput));
126 phosphor::logging::log<phosphor::logging::level::ERR>(
127 strOutput.c_str());
128 mNewPassword = strOutput;
129 }
130
131 return;
132 }
133 throw InternalFailure();
134}
135void Password::changePassword(std::string userName, std::string currentPassword,
136 std::string newPassword)
137{
138 phosphor::logging::log<phosphor::logging::level::DEBUG>(
139 "BIOS config changePassword");
140 verifyPassword(userName, currentPassword, newPassword);
141
142 try
143 {
144 nlohmann::json json;
145 json["UserName"] = userName;
146 json["CurrentPassword"] = currentPassword;
147 json["NewPassword"] = mNewPassword;
148 if (userName == "Administrator")
149 {
150 json["IsAdminPwdChanged"] = 1;
151 json["IsUserPwdChanged"] = 0;
152 }
153 else
154 {
155 json["IsAdminPwdChanged"] = 0;
156 json["IsUserPwdChanged"] = 1;
157 }
158 std::ofstream ofs(passwordFile.c_str(), std::ios::out);
159 ofs << std::setw(4) << json << std::endl;
160 }
161 catch (nlohmann::detail::exception& e)
162 {
163 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
164 throw InternalFailure();
165 }
166}
167Password::Password(sdbusplus::asio::object_server& objectServer,
168 std::shared_ptr<sdbusplus::asio::connection>& systemBus) :
169 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Password(
170 *systemBus, objectPathPwd),
171 objServer(objectServer), systemBus(systemBus)
172{
173 phosphor::logging::log<phosphor::logging::level::DEBUG>(
174 "BIOS config password is runing");
175 try
176 {
177 fs::path biosDir(BIOS_PERSIST_PATH);
178 fs::create_directories(biosDir);
179 passwordFile = biosDir / biosPasswordFile;
180 seedFile = biosDir / biosSeedFile;
181 }
182 catch (const fs::filesystem_error& e)
183 {
184 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
185 throw InternalFailure();
186 }
187}
188
189} // namespace bios_config_pwd
190
191int main()
192{
193 boost::asio::io_service io;
194 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
195
196 systemBus->request_name(bios_config_pwd::servicePwd);
197 sdbusplus::asio::object_server objectServer(systemBus);
198 bios_config_pwd::Password password(objectServer, systemBus);
199
200 io.run();
201 return 0;
202}