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. 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") 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 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(std::ifstream::failbit | std::ifstream::badbit | 126 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