1 #include "config.h"
2
3 #include "utils.hpp"
4
5 #include <phosphor-logging/lg2.hpp>
6 #include <xyz/openbmc_project/Logging/Settings/client.hpp>
7
8 #include <filesystem>
9 #include <fstream>
10 #include <string>
11
12 PHOSPHOR_LOG2_USING;
13
14 constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
15 using LoggingSettings =
16 sdbusplus::client::xyz::openbmc_project::logging::Settings<>;
17
18 // Check if the TPM measurement file exists and has a valid value.
19 // If the TPM measurement is invalid, it logs an error message.
checkTpmMeasurement()20 void checkTpmMeasurement()
21 {
22 bool tpmError = false;
23 std::string errorMsg;
24 if (!std::filesystem::exists(std::string(SYSFS_TPM_MEASUREMENT_PATH)))
25 {
26 tpmError = true;
27 errorMsg = "TPM measurement file does not exist: " +
28 std::string(SYSFS_TPM_MEASUREMENT_PATH);
29 }
30 else
31 {
32 std::string tpmValueStr;
33 std::ifstream tpmFile(std::string(SYSFS_TPM_MEASUREMENT_PATH));
34
35 tpmFile >> tpmValueStr;
36 if (tpmValueStr.empty())
37 {
38 tpmError = true;
39 errorMsg = "TPM measurement value is empty: " +
40 std::string(SYSFS_TPM_MEASUREMENT_PATH);
41 }
42 else if (tpmValueStr == "0")
43 {
44 tpmError = true;
45 errorMsg = "TPM measurement value is 0: " +
46 std::string(SYSFS_TPM_MEASUREMENT_PATH);
47 }
48 tpmFile.close();
49 }
50
51 if (tpmError)
52 {
53 // Doesn't have valid TPM measurement, log an error message
54 std::map<std::string, std::string> additionalData;
55 error("{ERROR}", "ERROR", errorMsg);
56 additionalData.emplace("ERROR", errorMsg);
57 auto bus = sdbusplus::bus::new_default();
58 phosphor::state::manager::utils::createError(
59 bus, "xyz.openbmc_project.State.Error.TpmMeasurementFail",
60 sdbusplus::server::xyz::openbmc_project::logging::Entry::Level::
61 Error,
62 additionalData);
63 }
64 return;
65 }
66
67 // Utilize the QuiesceOnHwError setting as an indication that the system
68 // is operating in an environment where the user should be notified of
69 // security settings (i.e. "Manufacturing")
isMfgModeEnabled()70 bool isMfgModeEnabled()
71 {
72 auto bus = sdbusplus::bus::new_default();
73 std::string path = "/xyz/openbmc_project/logging/settings";
74 std::string interface = LoggingSettings::interface;
75 std::string propertyName = "QuiesceOnHwError";
76 std::variant<bool> mfgModeEnabled;
77
78 std::string service =
79 phosphor::state::manager::utils::getService(bus, path, interface);
80
81 auto method = bus.new_method_call(service.c_str(), path.c_str(),
82 PROPERTY_INTERFACE, "Get");
83
84 method.append(interface, propertyName);
85
86 try
87 {
88 auto reply = bus.call(method);
89 reply.read(mfgModeEnabled);
90 }
91 catch (const sdbusplus::exception_t& e)
92 {
93 error("Error in property Get, error {ERROR}, property {PROPERTY}",
94 "ERROR", e, "PROPERTY", propertyName);
95 throw;
96 }
97
98 return std::get<bool>(mfgModeEnabled);
99 }
100
main()101 int main()
102 {
103 // Read the secure boot gpio
104 auto secureBootGpio =
105 phosphor::state::manager::utils::getGpioValue("bmc-secure-boot");
106 if (secureBootGpio == -1)
107 {
108 debug("bmc-secure-boot gpio not present or can not be read");
109 }
110 else if (secureBootGpio == 0)
111 {
112 info("bmc-secure-boot gpio found and indicates it is NOT enabled");
113 }
114 else
115 {
116 info("bmc-secure-boot found and indicates it is enabled");
117 }
118
119 // Now read the /sys/kernel/debug/aspeed/ files
120 std::string dbgVal;
121 std::ifstream dbgFile;
122 int secureBootVal = -1;
123 int abrImage = -1;
124
125 dbgFile.exceptions(
126 std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit);
127
128 if (std::filesystem::exists(SYSFS_SECURE_BOOT_PATH))
129 {
130 try
131 {
132 dbgFile.open(SYSFS_SECURE_BOOT_PATH);
133 dbgFile >> dbgVal;
134 dbgFile.close();
135 info("Read {SECURE_BOOT_VAL} from secure_boot", "SECURE_BOOT_VAL",
136 dbgVal);
137 secureBootVal = std::stoi(dbgVal);
138 }
139 catch (std::exception& e)
140 {
141 error("Failed to read secure boot sysfs file: {ERROR}", "ERROR", e);
142 // just continue and error will be logged at end if in mfg mode
143 }
144 }
145 else
146 {
147 info("sysfs file secure_boot not present");
148 }
149
150 if (std::filesystem::exists(SYSFS_ABR_IMAGE_PATH))
151 {
152 try
153 {
154 dbgFile.open(SYSFS_ABR_IMAGE_PATH);
155 dbgFile >> dbgVal;
156 dbgFile.close();
157 info("Read {ABR_IMAGE_VAL} from abr_image", "ABR_IMAGE_VAL",
158 dbgVal);
159 abrImage = std::stoi(dbgVal);
160 }
161 catch (std::exception& e)
162 {
163 error("Failed to read abr image sysfs file: {ERROR}", "ERROR", e);
164 // just continue and error will be logged at end if in mfg mode
165 }
166 }
167 else
168 {
169 info("sysfs file abr_image not present");
170 }
171
172 if (isMfgModeEnabled())
173 {
174 if ((secureBootGpio != 1) || (secureBootVal != 1) || (abrImage != 0))
175 {
176 error("The system is not secure");
177 std::map<std::string, std::string> additionalData;
178 additionalData.emplace("SECURE_BOOT_GPIO",
179 std::to_string(secureBootGpio));
180 additionalData.emplace("SYSFS_SECURE_BOOT_VAL",
181 std::to_string(secureBootVal));
182 additionalData.emplace("SYSFS_ABR_IMAGE_VAL",
183 std::to_string(abrImage));
184
185 auto bus = sdbusplus::bus::new_default();
186 phosphor::state::manager::utils::createError(
187 bus, "xyz.openbmc_project.State.Error.SecurityCheckFail",
188 sdbusplus::server::xyz::openbmc_project::logging::Entry::Level::
189 Warning,
190 additionalData);
191 }
192 }
193
194 // Check the TPM measurement if TPM is enabled
195 if (std::filesystem::exists(std::string(SYSFS_TPM_DEVICE_PATH)))
196 {
197 checkTpmMeasurement();
198 }
199
200 return 0;
201 }
202