1 #pragma once 2 3 #include "watch.hpp" 4 5 #include <openssl/ossl_typ.h> 6 #include <openssl/x509.h> 7 8 #include <functional> 9 #include <memory> 10 #include <sdbusplus/server/object.hpp> 11 #include <string> 12 #include <string_view> 13 #include <unordered_map> 14 #include <xyz/openbmc_project/Certs/Certificate/server.hpp> 15 #include <xyz/openbmc_project/Certs/Replace/server.hpp> 16 #include <xyz/openbmc_project/Object/Delete/server.hpp> 17 18 namespace phosphor::certs 19 { 20 21 // Certificate types 22 enum class CertificateType 23 { 24 authority, 25 server, 26 client, 27 unsupported, 28 }; 29 30 inline constexpr const char* certificateTypeToString(CertificateType type) 31 { 32 switch (type) 33 { 34 case CertificateType::authority: 35 return "authority"; 36 case CertificateType::server: 37 return "server"; 38 case CertificateType::client: 39 return "client"; 40 default: 41 return "unsupported"; 42 } 43 } 44 45 inline constexpr CertificateType stringToCertificateType(std::string_view type) 46 { 47 if (type == "authority") 48 { 49 return CertificateType::authority; 50 } 51 if (type == "server") 52 { 53 return CertificateType::server; 54 } 55 if (type == "client") 56 { 57 return CertificateType::client; 58 } 59 return CertificateType::unsupported; 60 } 61 62 namespace internal 63 { 64 using CertificateInterface = sdbusplus::server::object_t< 65 sdbusplus::xyz::openbmc_project::Certs::server::Certificate, 66 sdbusplus::xyz::openbmc_project::Certs::server::Replace, 67 sdbusplus::xyz::openbmc_project::Object::server::Delete>; 68 using InstallFunc = std::function<void(const std::string&)>; 69 using AppendPrivKeyFunc = std::function<void(const std::string&)>; 70 using X509Ptr = std::unique_ptr<X509, decltype(&::X509_free)>; 71 } // namespace internal 72 73 class Manager; // Forward declaration for Certificate Manager. 74 75 /** @class Certificate 76 * @brief OpenBMC Certificate entry implementation. 77 * @details A concrete implementation for the 78 * xyz.openbmc_project.Certs.Certificate DBus API 79 * xyz.openbmc_project.Certs.Install DBus API 80 */ 81 class Certificate : public internal::CertificateInterface 82 { 83 public: 84 Certificate() = delete; 85 Certificate(const Certificate&) = delete; 86 Certificate& operator=(const Certificate&) = delete; 87 Certificate(Certificate&&) = delete; 88 Certificate& operator=(Certificate&&) = delete; 89 virtual ~Certificate(); 90 91 /** @brief Constructor for the Certificate Object 92 * @param[in] bus - Bus to attach to. 93 * @param[in] objPath - Object path to attach to 94 * @param[in] type - Type of the certificate 95 * @param[in] installPath - Path of the certificate to install 96 * @param[in] uploadPath - Path of the certificate file to upload 97 * @param[in] watchPtr - watch on self signed certificate 98 * @param[in] parent - the manager that owns the certificate 99 */ 100 Certificate(sdbusplus::bus_t& bus, const std::string& objPath, 101 CertificateType type, const std::string& installPath, 102 const std::string& uploadPath, Watch* watch, Manager& parent); 103 104 /** @brief Constructor for the Certificate Object; a variant for authorities 105 * list install 106 * @param[in] bus - Bus to attach to. 107 * @param[in] objPath - Object path to attach to 108 * @param[in] type - Type of the certificate 109 * @param[in] installPath - Path of the certificate to install 110 * @param[in] x509Store - an initialized X509 store used for certificate 111 * validation; Certificate object doesn't own it 112 * @param[in] pem - Content of the certificate file to upload; it shall be 113 * a single PEM encoded x509 certificate 114 * @param[in] watchPtr - watch on self signed certificate 115 * @param[in] parent - Pointer to the manager which owns the constructed 116 * Certificate object 117 */ 118 Certificate(sdbusplus::bus_t& bus, const std::string& objPath, 119 const CertificateType& type, const std::string& installPath, 120 X509_STORE& x509Store, const std::string& pem, Watch* watchPtr, 121 Manager& parent); 122 123 /** @brief Validate and Replace/Install the certificate file 124 * Install/Replace the existing certificate file with another 125 * (possibly CA signed) Certificate file. 126 * @param[in] filePath - Certificate file path. 127 */ 128 void install(const std::string& filePath); 129 130 /** @brief Validate and Replace/Install the certificate file 131 * Install/Replace the existing certificate file with another 132 * (possibly CA signed) Certificate file. 133 * @param[in] x509Store - an initialized X509 store used for certificate 134 * validation; Certificate object doesn't own it 135 * @param[in] pem - a string buffer which stores a PEM encoded certificate. 136 */ 137 void install(X509_STORE& x509Store, const std::string& pem); 138 139 /** @brief Validate certificate and replace the existing certificate 140 * @param[in] filePath - Certificate file path. 141 */ 142 void replace(const std::string filePath) override; 143 144 /** @brief Populate certificate properties by parsing certificate file 145 */ 146 void populateProperties(); 147 148 /** 149 * @brief Obtain certificate ID. 150 * 151 * @return Certificate ID. 152 */ 153 std::string getCertId() const; 154 155 /** 156 * @brief Check if provided certificate is the same as the current one. 157 * 158 * @param[in] certPath - File path for certificate to check. 159 * 160 * @return Checking result. Return true if certificates are the same, 161 * false if not. 162 */ 163 bool isSame(const std::string& certPath); 164 165 /** 166 * @brief Update certificate storage. 167 */ 168 void storageUpdate(); 169 170 /** 171 * @brief Delete the certificate 172 */ 173 void delete_() override; 174 175 /** 176 * @brief Generate file name which is unique in the provided directory. 177 * 178 * @param[in] directoryPath - Directory path. 179 * 180 * @return File path. 181 */ 182 static std::string generateUniqueFilePath(const std::string& directoryPath); 183 184 /** 185 * @brief Copies the certificate from sourceFilePath to installFilePath 186 * 187 * @param[in] sourceFilePath - Path to the source file. 188 * @param[in] certFilePath - Path to the destination file. 189 * 190 * @return void 191 */ 192 static void copyCertificate(const std::string& certSrcFilePath, 193 const std::string& certFilePath); 194 195 /** 196 * @brief Returns the associated dbus object path. 197 */ 198 std::string getObjectPath(); 199 200 /** 201 * @brief Returns the associated cert file path. 202 */ 203 std::string getCertFilePath(); 204 205 /** @brief: Set the data member |certFilePath| to |path| 206 */ 207 void setCertFilePath(const std::string& path); 208 209 /** @brief: Set the data member |certInstallPath| to |path| 210 */ 211 void setCertInstallPath(const std::string& path); 212 213 private: 214 /** 215 * @brief Populate certificate properties by parsing given certificate 216 * object 217 * 218 * @param[in] cert The given certificate object 219 * 220 * @return void 221 */ 222 void populateProperties(X509& cert); 223 224 /** @brief Check and append private key to the certificate file 225 * If private key is not present in the certificate file append the 226 * certificate file with private key existing in the system. 227 * @param[in] filePath - Certificate and key full file path. 228 * @return void. 229 */ 230 void checkAndAppendPrivateKey(const std::string& filePath); 231 232 /** @brief Public/Private key compare function. 233 * Comparing private key against certificate public key 234 * from input .pem file. 235 * @param[in] filePath - Certificate and key full file path. 236 * @return Return true if Key compare is successful, 237 * false if not 238 */ 239 bool compareKeys(const std::string& filePath); 240 241 /** 242 * @brief Generate authority certificate file path corresponding with 243 * OpenSSL requirements. 244 * 245 * Prepare authority certificate file path for provided certificate. 246 * OpenSSL puts some restrictions on the certificate file name pattern. 247 * Certificate full file name needs to consists of basic file name which 248 * is certificate subject name hash and file name extension which is an 249 * integer. More over, certificates files names extensions must be 250 * consecutive integer numbers in case many certificates with the same 251 * subject name. 252 * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html 253 * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html 254 * 255 * @param[in] certSrcFilePath - Certificate source file path. 256 * @param[in] certDstDirPath - Certificate destination directory path. 257 * 258 * @return Authority certificate file path. 259 */ 260 std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath, 261 const std::string& certDstDirPath); 262 263 /** 264 * @brief Generate authority certificate file path based on provided 265 * certificate source file path. 266 * 267 * @param[in] certSrcFilePath - Certificate source file path. 268 * 269 * @return Authority certificate file path. 270 */ 271 std::string generateAuthCertFilePath(const std::string& certSrcFilePath); 272 273 /** 274 * @brief Generate certificate file path based on provided certificate 275 * source file path. 276 * 277 * @param[in] certSrcFilePath - Certificate source file path. 278 * 279 * @return Certificate file path. 280 */ 281 std::string generateCertFilePath(const std::string& certSrcFilePath); 282 283 /** @brief Type specific function pointer map */ 284 std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap; 285 286 /** @brief object path */ 287 std::string objectPath; 288 289 /** @brief Type of the certificate */ 290 CertificateType certType; 291 292 /** @brief Stores certificate ID */ 293 std::string certId; 294 295 /** @brief Stores certificate file path */ 296 std::string certFilePath; 297 298 /** @brief Certificate file installation path */ 299 std::string certInstallPath; 300 301 /** @brief Type specific function pointer map for appending private key */ 302 std::unordered_map<CertificateType, internal::AppendPrivKeyFunc> 303 appendKeyMap; 304 305 /** @brief Certificate file create/update watch 306 * Note that Certificate object doesn't own the pointer 307 */ 308 Watch* certWatch; 309 310 /** @brief Reference to Certificate Manager */ 311 Manager& manager; 312 }; 313 314 } // namespace phosphor::certs 315