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 * @param[in] restore - the certificate is created in the restore path 100 */ 101 Certificate(sdbusplus::bus_t& bus, const std::string& objPath, 102 CertificateType type, const std::string& installPath, 103 const std::string& uploadPath, Watch* watch, Manager& parent, 104 bool restore); 105 106 /** @brief Constructor for the Certificate Object; a variant for authorities 107 * list install 108 * @param[in] bus - Bus to attach to. 109 * @param[in] objPath - Object path to attach to 110 * @param[in] type - Type of the certificate 111 * @param[in] installPath - Path of the certificate to install 112 * @param[in] x509Store - an initialized X509 store used for certificate 113 * validation; Certificate object doesn't own it 114 * @param[in] pem - Content of the certificate file to upload; it shall be 115 * a single PEM encoded x509 certificate 116 * @param[in] watchPtr - watch on self signed certificate 117 * @param[in] parent - Pointer to the manager which owns the constructed 118 * Certificate object 119 * @param[in] restore - the certificate is created in the restore path 120 */ 121 Certificate(sdbusplus::bus_t& bus, const std::string& objPath, 122 const CertificateType& type, const std::string& installPath, 123 X509_STORE& x509Store, const std::string& pem, Watch* watchPtr, 124 Manager& parent, bool restore); 125 126 /** @brief Validate and Replace/Install the certificate file 127 * Install/Replace the existing certificate file with another 128 * (possibly CA signed) Certificate file. 129 * @param[in] filePath - Certificate file path. 130 * @param[in] restore - the certificate is created in the restore path 131 */ 132 void install(const std::string& filePath, bool restore); 133 134 /** @brief Validate and Replace/Install the certificate file 135 * Install/Replace the existing certificate file with another 136 * (possibly CA signed) Certificate file. 137 * @param[in] x509Store - an initialized X509 store used for certificate 138 * validation; Certificate object doesn't own it 139 * @param[in] pem - a string buffer which stores a PEM encoded certificate. 140 * @param[in] restore - the certificate is created in the restore path 141 */ 142 void install(X509_STORE& x509Store, const std::string& pem, bool restore); 143 144 /** @brief Validate certificate and replace the existing certificate 145 * @param[in] filePath - Certificate file path. 146 */ 147 void replace(const std::string filePath) override; 148 149 /** @brief Populate certificate properties by parsing certificate file 150 */ 151 void populateProperties(); 152 153 /** 154 * @brief Obtain certificate ID. 155 * 156 * @return Certificate ID. 157 */ 158 std::string getCertId() const; 159 160 /** 161 * @brief Check if provided certificate is the same as the current one. 162 * 163 * @param[in] certPath - File path for certificate to check. 164 * 165 * @return Checking result. Return true if certificates are the same, 166 * false if not. 167 */ 168 bool isSame(const std::string& certPath); 169 170 /** 171 * @brief Update certificate storage. 172 */ 173 void storageUpdate(); 174 175 /** 176 * @brief Delete the certificate 177 */ 178 void delete_() override; 179 180 /** 181 * @brief Generate file name which is unique in the provided directory. 182 * 183 * @param[in] directoryPath - Directory path. 184 * 185 * @return File path. 186 */ 187 static std::string generateUniqueFilePath(const std::string& directoryPath); 188 189 /** 190 * @brief Copies the certificate from sourceFilePath to installFilePath 191 * 192 * @param[in] sourceFilePath - Path to the source file. 193 * @param[in] certFilePath - Path to the destination file. 194 * 195 * @return void 196 */ 197 static void copyCertificate(const std::string& certSrcFilePath, 198 const std::string& certFilePath); 199 200 /** 201 * @brief Returns the associated dbus object path. 202 */ 203 std::string getObjectPath(); 204 205 /** 206 * @brief Returns the associated cert file path. 207 */ 208 std::string getCertFilePath(); 209 210 /** @brief: Set the data member |certFilePath| to |path| 211 */ 212 void setCertFilePath(const std::string& path); 213 214 /** @brief: Set the data member |certInstallPath| to |path| 215 */ 216 void setCertInstallPath(const std::string& path); 217 218 private: 219 /** 220 * @brief Populate certificate properties by parsing given certificate 221 * object 222 * 223 * @param[in] cert The given certificate object 224 * 225 * @return void 226 */ 227 void populateProperties(X509& cert); 228 229 /** @brief Check and append private key to the certificate file 230 * If private key is not present in the certificate file append the 231 * certificate file with private key existing in the system. 232 * @param[in] filePath - Certificate and key full file path. 233 * @return void. 234 */ 235 void checkAndAppendPrivateKey(const std::string& filePath); 236 237 /** @brief Public/Private key compare function. 238 * Comparing private key against certificate public key 239 * from input .pem file. 240 * @param[in] filePath - Certificate and key full file path. 241 * @return Return true if Key compare is successful, 242 * false if not 243 */ 244 bool compareKeys(const std::string& filePath); 245 246 /** 247 * @brief Generate authority certificate file path corresponding with 248 * OpenSSL requirements. 249 * 250 * Prepare authority certificate file path for provided certificate. 251 * OpenSSL puts some restrictions on the certificate file name pattern. 252 * Certificate full file name needs to consists of basic file name which 253 * is certificate subject name hash and file name extension which is an 254 * integer. More over, certificates files names extensions must be 255 * consecutive integer numbers in case many certificates with the same 256 * subject name. 257 * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html 258 * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html 259 * 260 * @param[in] certSrcFilePath - Certificate source file path. 261 * @param[in] certDstDirPath - Certificate destination directory path. 262 * 263 * @return Authority certificate file path. 264 */ 265 std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath, 266 const std::string& certDstDirPath); 267 268 /** 269 * @brief Generate authority certificate file path based on provided 270 * certificate source file path. 271 * 272 * @param[in] certSrcFilePath - Certificate source file path. 273 * 274 * @return Authority certificate file path. 275 */ 276 std::string generateAuthCertFilePath(const std::string& certSrcFilePath); 277 278 /** 279 * @brief Generate certificate file path based on provided certificate 280 * source file path. 281 * 282 * @param[in] certSrcFilePath - Certificate source file path. 283 * 284 * @return Certificate file path. 285 */ 286 std::string generateCertFilePath(const std::string& certSrcFilePath); 287 288 /** @brief Type specific function pointer map */ 289 std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap; 290 291 /** @brief object path */ 292 std::string objectPath; 293 294 /** @brief Type of the certificate */ 295 CertificateType certType; 296 297 /** @brief Stores certificate ID */ 298 std::string certId; 299 300 /** @brief Stores certificate file path */ 301 std::string certFilePath; 302 303 /** @brief Certificate file installation path */ 304 std::string certInstallPath; 305 306 /** @brief Type specific function pointer map for appending private key */ 307 std::unordered_map<CertificateType, internal::AppendPrivKeyFunc> 308 appendKeyMap; 309 310 /** @brief Certificate file create/update watch 311 * Note that Certificate object doesn't own the pointer 312 */ 313 Watch* certWatch; 314 315 /** @brief Reference to Certificate Manager */ 316 Manager& manager; 317 }; 318 319 } // namespace phosphor::certs 320