xref: /openbmc/phosphor-state-manager/secure_boot_check.cpp (revision a52ed88654e4a92369e3fc3c2ff488495cb6e4f5)
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     const std::string propertyName =
76         LoggingSettings::property_names::quiesce_on_hw_error;
77     std::variant<bool> mfgModeEnabled;
78 
79     std::string service =
80         phosphor::state::manager::utils::getService(bus, path, interface);
81 
82     auto method = bus.new_method_call(service.c_str(), path.c_str(),
83                                       PROPERTY_INTERFACE, "Get");
84 
85     method.append(interface, propertyName);
86 
87     try
88     {
89         auto reply = bus.call(method);
90         reply.read(mfgModeEnabled);
91     }
92     catch (const sdbusplus::exception_t& e)
93     {
94         error("Error in property Get, error {ERROR}, property {PROPERTY}",
95               "ERROR", e, "PROPERTY", propertyName);
96         throw;
97     }
98 
99     return std::get<bool>(mfgModeEnabled);
100 }
101 
main()102 int main()
103 {
104     // Read the secure boot gpio
105     auto secureBootGpio =
106         phosphor::state::manager::utils::getGpioValue("bmc-secure-boot");
107     if (secureBootGpio == -1)
108     {
109         debug("bmc-secure-boot gpio not present or can not be read");
110     }
111     else if (secureBootGpio == 0)
112     {
113         info("bmc-secure-boot gpio found and indicates it is NOT enabled");
114     }
115     else
116     {
117         info("bmc-secure-boot found and indicates it is enabled");
118     }
119 
120     // Now read the /sys/kernel/debug/aspeed/ files
121     std::string dbgVal;
122     std::ifstream dbgFile;
123     int secureBootVal = -1;
124     int abrImage = -1;
125 
126     dbgFile.exceptions(
127         std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit);
128 
129     if (std::filesystem::exists(SYSFS_SECURE_BOOT_PATH))
130     {
131         try
132         {
133             dbgFile.open(SYSFS_SECURE_BOOT_PATH);
134             dbgFile >> dbgVal;
135             dbgFile.close();
136             info("Read {SECURE_BOOT_VAL} from secure_boot", "SECURE_BOOT_VAL",
137                  dbgVal);
138             secureBootVal = std::stoi(dbgVal);
139         }
140         catch (std::exception& e)
141         {
142             error("Failed to read secure boot sysfs file: {ERROR}", "ERROR", e);
143             // just continue and error will be logged at end if in mfg mode
144         }
145     }
146     else
147     {
148         info("sysfs file secure_boot not present");
149     }
150 
151     if (std::filesystem::exists(SYSFS_ABR_IMAGE_PATH))
152     {
153         try
154         {
155             dbgFile.open(SYSFS_ABR_IMAGE_PATH);
156             dbgFile >> dbgVal;
157             dbgFile.close();
158             info("Read {ABR_IMAGE_VAL} from abr_image", "ABR_IMAGE_VAL",
159                  dbgVal);
160             abrImage = std::stoi(dbgVal);
161         }
162         catch (std::exception& e)
163         {
164             error("Failed to read abr image sysfs file: {ERROR}", "ERROR", e);
165             // just continue and error will be logged at end if in mfg mode
166         }
167     }
168     else
169     {
170         info("sysfs file abr_image not present");
171     }
172 
173     if (isMfgModeEnabled())
174     {
175         if ((secureBootGpio != 1) || (secureBootVal != 1) || (abrImage != 0))
176         {
177             error("The system is not secure");
178             std::map<std::string, std::string> additionalData;
179             additionalData.emplace("SECURE_BOOT_GPIO",
180                                    std::to_string(secureBootGpio));
181             additionalData.emplace("SYSFS_SECURE_BOOT_VAL",
182                                    std::to_string(secureBootVal));
183             additionalData.emplace("SYSFS_ABR_IMAGE_VAL",
184                                    std::to_string(abrImage));
185 
186             auto bus = sdbusplus::bus::new_default();
187             phosphor::state::manager::utils::createError(
188                 bus, "xyz.openbmc_project.State.Error.SecurityCheckFail",
189                 sdbusplus::server::xyz::openbmc_project::logging::Entry::Level::
190                     Warning,
191                 additionalData);
192         }
193     }
194 
195     // Check the TPM measurement if TPM is enabled
196     if (std::filesystem::exists(std::string(SYSFS_TPM_DEVICE_PATH)))
197     {
198         checkTpmMeasurement();
199     }
200 
201     return 0;
202 }
203