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