16ceec40bSMarri Devender Rao #pragma once
26ceec40bSMarri Devender Rao 
3ffad1ef1SMarri Devender Rao #include "watch.hpp"
4ffad1ef1SMarri Devender Rao 
5014be0bfSNan Zhou #include <openssl/ossl_typ.h>
66ceec40bSMarri Devender Rao #include <openssl/x509.h>
76ceec40bSMarri Devender Rao 
8014be0bfSNan Zhou #include <sdbusplus/server/object.hpp>
9edd1131cSMarri Devender Rao #include <xyz/openbmc_project/Certs/Certificate/server.hpp>
1013bf74e4SMarri Devender Rao #include <xyz/openbmc_project/Certs/Replace/server.hpp>
11a3bb38fbSZbigniew Kurzynski #include <xyz/openbmc_project/Object/Delete/server.hpp>
126ceec40bSMarri Devender Rao 
13*223e4604SPatrick Williams #include <functional>
14*223e4604SPatrick Williams #include <memory>
15*223e4604SPatrick Williams #include <string>
16*223e4604SPatrick Williams #include <string_view>
17*223e4604SPatrick Williams #include <unordered_map>
18*223e4604SPatrick Williams 
19e1289adfSNan Zhou namespace phosphor::certs
206ceec40bSMarri Devender Rao {
21edd1131cSMarri Devender Rao 
22cf06ccdcSNan Zhou // Certificate types
23cf06ccdcSNan Zhou enum class CertificateType
24cf06ccdcSNan Zhou {
25e3d47cd4SNan Zhou     authority,
26e3d47cd4SNan Zhou     server,
27e3d47cd4SNan Zhou     client,
28e3d47cd4SNan Zhou     unsupported,
29cf06ccdcSNan Zhou };
30cf06ccdcSNan Zhou 
certificateTypeToString(CertificateType type)31cf06ccdcSNan Zhou inline constexpr const char* certificateTypeToString(CertificateType type)
32cf06ccdcSNan Zhou {
33cf06ccdcSNan Zhou     switch (type)
34cf06ccdcSNan Zhou     {
35e3d47cd4SNan Zhou         case CertificateType::authority:
36cf06ccdcSNan Zhou             return "authority";
37e3d47cd4SNan Zhou         case CertificateType::server:
38cf06ccdcSNan Zhou             return "server";
39e3d47cd4SNan Zhou         case CertificateType::client:
40cf06ccdcSNan Zhou             return "client";
41cf06ccdcSNan Zhou         default:
42cf06ccdcSNan Zhou             return "unsupported";
43cf06ccdcSNan Zhou     }
44cf06ccdcSNan Zhou }
45cf06ccdcSNan Zhou 
stringToCertificateType(std::string_view type)46cf06ccdcSNan Zhou inline constexpr CertificateType stringToCertificateType(std::string_view type)
47cf06ccdcSNan Zhou {
48cf06ccdcSNan Zhou     if (type == "authority")
49cf06ccdcSNan Zhou     {
50e3d47cd4SNan Zhou         return CertificateType::authority;
51cf06ccdcSNan Zhou     }
52cf06ccdcSNan Zhou     if (type == "server")
53cf06ccdcSNan Zhou     {
54e3d47cd4SNan Zhou         return CertificateType::server;
55cf06ccdcSNan Zhou     }
56cf06ccdcSNan Zhou     if (type == "client")
57cf06ccdcSNan Zhou     {
58e3d47cd4SNan Zhou         return CertificateType::client;
59cf06ccdcSNan Zhou     }
60e3d47cd4SNan Zhou     return CertificateType::unsupported;
61cf06ccdcSNan Zhou }
62cf06ccdcSNan Zhou 
63cf06ccdcSNan Zhou namespace internal
64cf06ccdcSNan Zhou {
65cf06ccdcSNan Zhou using CertificateInterface = sdbusplus::server::object_t<
66cf06ccdcSNan Zhou     sdbusplus::xyz::openbmc_project::Certs::server::Certificate,
67cf06ccdcSNan Zhou     sdbusplus::xyz::openbmc_project::Certs::server::Replace,
68cf06ccdcSNan Zhou     sdbusplus::xyz::openbmc_project::Object::server::Delete>;
696ceec40bSMarri Devender Rao using InstallFunc = std::function<void(const std::string&)>;
70cd30c496SMarri Devender Rao using AppendPrivKeyFunc = std::function<void(const std::string&)>;
71cf06ccdcSNan Zhou using X509Ptr = std::unique_ptr<X509, decltype(&::X509_free)>;
72cf06ccdcSNan Zhou } // namespace internal
736ceec40bSMarri Devender Rao 
74a3bb38fbSZbigniew Kurzynski class Manager; // Forward declaration for Certificate Manager.
75a3bb38fbSZbigniew Kurzynski 
766ceec40bSMarri Devender Rao /** @class Certificate
776ceec40bSMarri Devender Rao  *  @brief OpenBMC Certificate entry implementation.
786ceec40bSMarri Devender Rao  *  @details A concrete implementation for the
796ceec40bSMarri Devender Rao  *  xyz.openbmc_project.Certs.Certificate DBus API
80bf3cf751SNan Zhou  *  xyz.openbmc_project.Certs.Install DBus API
816ceec40bSMarri Devender Rao  */
82cf06ccdcSNan Zhou class Certificate : public internal::CertificateInterface
836ceec40bSMarri Devender Rao {
846ceec40bSMarri Devender Rao   public:
856ceec40bSMarri Devender Rao     Certificate() = delete;
866ceec40bSMarri Devender Rao     Certificate(const Certificate&) = delete;
876ceec40bSMarri Devender Rao     Certificate& operator=(const Certificate&) = delete;
886ceec40bSMarri Devender Rao     Certificate(Certificate&&) = delete;
896ceec40bSMarri Devender Rao     Certificate& operator=(Certificate&&) = delete;
906ceec40bSMarri Devender Rao     virtual ~Certificate();
916ceec40bSMarri Devender Rao 
926ceec40bSMarri Devender Rao     /** @brief Constructor for the Certificate Object
936ceec40bSMarri Devender Rao      *  @param[in] bus - Bus to attach to.
946ceec40bSMarri Devender Rao      *  @param[in] objPath - Object path to attach to
956ceec40bSMarri Devender Rao      *  @param[in] type - Type of the certificate
966ceec40bSMarri Devender Rao      *  @param[in] installPath - Path of the certificate to install
976ceec40bSMarri Devender Rao      *  @param[in] uploadPath - Path of the certificate file to upload
98cf06ccdcSNan Zhou      *  @param[in] watchPtr - watch on self signed certificate
99cf06ccdcSNan Zhou      *  @param[in] parent - the manager that owns the certificate
100698a5743SWilly Tu      *  @param[in] restore - the certificate is created in the restore path
1016ceec40bSMarri Devender Rao      */
102b3dbfb37SPatrick Williams     Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
103cf06ccdcSNan Zhou                 CertificateType type, const std::string& installPath,
104698a5743SWilly Tu                 const std::string& uploadPath, Watch* watch, Manager& parent,
105698a5743SWilly Tu                 bool restore);
1062f3563ccSZbigniew Lukwinski 
1076ec13c8fSNan Zhou     /** @brief Constructor for the Certificate Object; a variant for authorities
1086ec13c8fSNan Zhou      * list install
1096ec13c8fSNan Zhou      *  @param[in] bus - Bus to attach to.
1106ec13c8fSNan Zhou      *  @param[in] objPath - Object path to attach to
1116ec13c8fSNan Zhou      *  @param[in] type - Type of the certificate
1126ec13c8fSNan Zhou      *  @param[in] installPath - Path of the certificate to install
1136ec13c8fSNan Zhou      *  @param[in] x509Store - an initialized X509 store used for certificate
1146ec13c8fSNan Zhou      * validation; Certificate object doesn't own it
1156ec13c8fSNan Zhou      *  @param[in] pem - Content of the certificate file to upload; it shall be
1166ec13c8fSNan Zhou      * a single PEM encoded x509 certificate
1176ec13c8fSNan Zhou      *  @param[in] watchPtr - watch on self signed certificate
1186ec13c8fSNan Zhou      *  @param[in] parent - Pointer to the manager which owns the constructed
1196ec13c8fSNan Zhou      * Certificate object
120698a5743SWilly Tu      *  @param[in] restore - the certificate is created in the restore path
1216ec13c8fSNan Zhou      */
122b3dbfb37SPatrick Williams     Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
1236ec13c8fSNan Zhou                 const CertificateType& type, const std::string& installPath,
1246ec13c8fSNan Zhou                 X509_STORE& x509Store, const std::string& pem, Watch* watchPtr,
125698a5743SWilly Tu                 Manager& parent, bool restore);
1266ec13c8fSNan Zhou 
1272f3563ccSZbigniew Lukwinski     /** @brief Validate and Replace/Install the certificate file
1282f3563ccSZbigniew Lukwinski      *  Install/Replace the existing certificate file with another
1292f3563ccSZbigniew Lukwinski      *  (possibly CA signed) Certificate file.
1302f3563ccSZbigniew Lukwinski      *  @param[in] filePath - Certificate file path.
131698a5743SWilly Tu      *  @param[in] restore - the certificate is created in the restore path
1322f3563ccSZbigniew Lukwinski      */
133698a5743SWilly Tu     void install(const std::string& filePath, bool restore);
1346ceec40bSMarri Devender Rao 
1356ec13c8fSNan Zhou     /** @brief Validate and Replace/Install the certificate file
1366ec13c8fSNan Zhou      *  Install/Replace the existing certificate file with another
1376ec13c8fSNan Zhou      *  (possibly CA signed) Certificate file.
1386ec13c8fSNan Zhou      *  @param[in] x509Store - an initialized X509 store used for certificate
1396ec13c8fSNan Zhou      * validation; Certificate object doesn't own it
1406ec13c8fSNan Zhou      *  @param[in] pem - a string buffer which stores a PEM encoded certificate.
141698a5743SWilly Tu      *  @param[in] restore - the certificate is created in the restore path
1426ec13c8fSNan Zhou      */
143698a5743SWilly Tu     void install(X509_STORE& x509Store, const std::string& pem, bool restore);
1446ec13c8fSNan Zhou 
14513bf74e4SMarri Devender Rao     /** @brief Validate certificate and replace the existing certificate
14613bf74e4SMarri Devender Rao      *  @param[in] filePath - Certificate file path.
14713bf74e4SMarri Devender Rao      */
14813bf74e4SMarri Devender Rao     void replace(const std::string filePath) override;
14913bf74e4SMarri Devender Rao 
150ffad1ef1SMarri Devender Rao     /** @brief Populate certificate properties by parsing certificate file
151ffad1ef1SMarri Devender Rao      */
152ffad1ef1SMarri Devender Rao     void populateProperties();
153ffad1ef1SMarri Devender Rao 
154db029c95SKowalski, Kamil     /**
1552f3563ccSZbigniew Lukwinski      * @brief Obtain certificate ID.
156db029c95SKowalski, Kamil      *
1572f3563ccSZbigniew Lukwinski      * @return Certificate ID.
158db029c95SKowalski, Kamil      */
1592f3563ccSZbigniew Lukwinski     std::string getCertId() const;
1602f3563ccSZbigniew Lukwinski 
1612f3563ccSZbigniew Lukwinski     /**
162bf3cf751SNan Zhou      * @brief Check if provided certificate is the same as the current one.
1632f3563ccSZbigniew Lukwinski      *
1642f3563ccSZbigniew Lukwinski      * @param[in] certPath - File path for certificate to check.
1652f3563ccSZbigniew Lukwinski      *
1662f3563ccSZbigniew Lukwinski      * @return Checking result. Return true if certificates are the same,
1672f3563ccSZbigniew Lukwinski      *         false if not.
1682f3563ccSZbigniew Lukwinski      */
1692f3563ccSZbigniew Lukwinski     bool isSame(const std::string& certPath);
1702f3563ccSZbigniew Lukwinski 
1712f3563ccSZbigniew Lukwinski     /**
1722f3563ccSZbigniew Lukwinski      * @brief Update certificate storage.
1732f3563ccSZbigniew Lukwinski      */
1742f3563ccSZbigniew Lukwinski     void storageUpdate();
175db029c95SKowalski, Kamil 
176a3bb38fbSZbigniew Kurzynski     /**
177a3bb38fbSZbigniew Kurzynski      * @brief Delete the certificate
178a3bb38fbSZbigniew Kurzynski      */
179a3bb38fbSZbigniew Kurzynski     void delete_() override;
180a3bb38fbSZbigniew Kurzynski 
1816ec13c8fSNan Zhou     /**
1826ec13c8fSNan Zhou      * @brief Generate file name which is unique in the provided directory.
1836ec13c8fSNan Zhou      *
1846ec13c8fSNan Zhou      * @param[in] directoryPath - Directory path.
1856ec13c8fSNan Zhou      *
1866ec13c8fSNan Zhou      * @return File path.
1876ec13c8fSNan Zhou      */
1886ec13c8fSNan Zhou     static std::string generateUniqueFilePath(const std::string& directoryPath);
1896ec13c8fSNan Zhou 
1906ec13c8fSNan Zhou     /**
1916ec13c8fSNan Zhou      * @brief Copies the certificate from sourceFilePath to installFilePath
1926ec13c8fSNan Zhou      *
1936ec13c8fSNan Zhou      * @param[in] sourceFilePath - Path to the source file.
1946ec13c8fSNan Zhou      * @param[in] certFilePath - Path to the destination file.
1956ec13c8fSNan Zhou      *
1966ec13c8fSNan Zhou      * @return void
1976ec13c8fSNan Zhou      */
1986ec13c8fSNan Zhou     static void copyCertificate(const std::string& certSrcFilePath,
1996ec13c8fSNan Zhou                                 const std::string& certFilePath);
2006ec13c8fSNan Zhou 
2016ec13c8fSNan Zhou     /**
2026ec13c8fSNan Zhou      * @brief Returns the associated dbus object path.
2036ec13c8fSNan Zhou      */
2046ec13c8fSNan Zhou     std::string getObjectPath();
2056ec13c8fSNan Zhou 
2066ec13c8fSNan Zhou     /**
2076ec13c8fSNan Zhou      * @brief Returns the associated cert file path.
2086ec13c8fSNan Zhou      */
2096ec13c8fSNan Zhou     std::string getCertFilePath();
2106ec13c8fSNan Zhou 
2116ec13c8fSNan Zhou     /** @brief: Set the data member |certFilePath| to |path|
2126ec13c8fSNan Zhou      */
2136ec13c8fSNan Zhou     void setCertFilePath(const std::string& path);
2146ec13c8fSNan Zhou 
2156ec13c8fSNan Zhou     /** @brief: Set the data member |certInstallPath| to |path|
2166ec13c8fSNan Zhou      */
2176ec13c8fSNan Zhou     void setCertInstallPath(const std::string& path);
2186ec13c8fSNan Zhou 
21913bf74e4SMarri Devender Rao   private:
220db029c95SKowalski, Kamil     /**
221e869bb63SNan Zhou      * @brief Populate certificate properties by parsing given certificate
222e869bb63SNan Zhou      * object
223c4522d2eSMarri Devender Rao      *
224e869bb63SNan Zhou      * @param[in] cert The given certificate object
225c4522d2eSMarri Devender Rao      *
226c4522d2eSMarri Devender Rao      * @return void
227c4522d2eSMarri Devender Rao      */
228e869bb63SNan Zhou     void populateProperties(X509& cert);
2296ceec40bSMarri Devender Rao 
230cd30c496SMarri Devender Rao     /** @brief Check and append private key to the certificate file
231cd30c496SMarri Devender Rao      *         If private key is not present in the certificate file append the
232cd30c496SMarri Devender Rao      *         certificate file with private key existing in the system.
233cd30c496SMarri Devender Rao      *  @param[in] filePath - Certificate and key full file path.
234cd30c496SMarri Devender Rao      *  @return void.
235cd30c496SMarri Devender Rao      */
236cd30c496SMarri Devender Rao     void checkAndAppendPrivateKey(const std::string& filePath);
237cd30c496SMarri Devender Rao 
2386ceec40bSMarri Devender Rao     /** @brief Public/Private key compare function.
2396ceec40bSMarri Devender Rao      *         Comparing private key against certificate public key
2406ceec40bSMarri Devender Rao      *         from input .pem file.
241cd30c496SMarri Devender Rao      *  @param[in] filePath - Certificate and key full file path.
2426ceec40bSMarri Devender Rao      *  @return Return true if Key compare is successful,
2436ceec40bSMarri Devender Rao      *          false if not
2446ceec40bSMarri Devender Rao      */
2456ceec40bSMarri Devender Rao     bool compareKeys(const std::string& filePath);
246cd30c496SMarri Devender Rao 
2472f3563ccSZbigniew Lukwinski     /**
2482f3563ccSZbigniew Lukwinski      * @brief Generate authority certificate file path corresponding with
2492f3563ccSZbigniew Lukwinski      * OpenSSL requirements.
2502f3563ccSZbigniew Lukwinski      *
251bf3cf751SNan Zhou      * Prepare authority certificate file path for provided certificate.
2522f3563ccSZbigniew Lukwinski      * OpenSSL puts some restrictions on the certificate file name pattern.
2532f3563ccSZbigniew Lukwinski      * Certificate full file name needs to consists of basic file name which
2542f3563ccSZbigniew Lukwinski      * is certificate subject name hash and file name extension which is an
2552f3563ccSZbigniew Lukwinski      * integer. More over, certificates files names extensions must be
2562f3563ccSZbigniew Lukwinski      * consecutive integer numbers in case many certificates with the same
2572f3563ccSZbigniew Lukwinski      * subject name.
2582f3563ccSZbigniew Lukwinski      * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html
2592f3563ccSZbigniew Lukwinski      * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html
2602f3563ccSZbigniew Lukwinski      *
2612f3563ccSZbigniew Lukwinski      * @param[in] certSrcFilePath - Certificate source file path.
2622f3563ccSZbigniew Lukwinski      * @param[in] certDstDirPath - Certificate destination directory path.
2632f3563ccSZbigniew Lukwinski      *
2642f3563ccSZbigniew Lukwinski      * @return Authority certificate file path.
2652f3563ccSZbigniew Lukwinski      */
2662f3563ccSZbigniew Lukwinski     std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath,
2672f3563ccSZbigniew Lukwinski                                              const std::string& certDstDirPath);
2682f3563ccSZbigniew Lukwinski 
2692f3563ccSZbigniew Lukwinski     /**
2702f3563ccSZbigniew Lukwinski      * @brief Generate authority certificate file path based on provided
2712f3563ccSZbigniew Lukwinski      * certificate source file path.
2722f3563ccSZbigniew Lukwinski      *
2732f3563ccSZbigniew Lukwinski      * @param[in] certSrcFilePath - Certificate source file path.
2742f3563ccSZbigniew Lukwinski      *
2752f3563ccSZbigniew Lukwinski      * @return Authority certificate file path.
2762f3563ccSZbigniew Lukwinski      */
2772f3563ccSZbigniew Lukwinski     std::string generateAuthCertFilePath(const std::string& certSrcFilePath);
2782f3563ccSZbigniew Lukwinski 
2792f3563ccSZbigniew Lukwinski     /**
2802f3563ccSZbigniew Lukwinski      * @brief Generate certificate file path based on provided certificate
2812f3563ccSZbigniew Lukwinski      * source file path.
2822f3563ccSZbigniew Lukwinski      *
2832f3563ccSZbigniew Lukwinski      * @param[in] certSrcFilePath - Certificate source file path.
2842f3563ccSZbigniew Lukwinski      *
2852f3563ccSZbigniew Lukwinski      * @return Certificate file path.
2862f3563ccSZbigniew Lukwinski      */
2872f3563ccSZbigniew Lukwinski     std::string generateCertFilePath(const std::string& certSrcFilePath);
2882f3563ccSZbigniew Lukwinski 
2892f3563ccSZbigniew Lukwinski     /** @brief Type specific function pointer map */
290cf06ccdcSNan Zhou     std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap;
2916ceec40bSMarri Devender Rao 
2926ceec40bSMarri Devender Rao     /** @brief object path */
2936ceec40bSMarri Devender Rao     std::string objectPath;
2946ceec40bSMarri Devender Rao 
2952f3563ccSZbigniew Lukwinski     /** @brief Type of the certificate */
2966ceec40bSMarri Devender Rao     CertificateType certType;
2976ceec40bSMarri Devender Rao 
2982f3563ccSZbigniew Lukwinski     /** @brief Stores certificate ID */
2992f3563ccSZbigniew Lukwinski     std::string certId;
3006ceec40bSMarri Devender Rao 
3012f3563ccSZbigniew Lukwinski     /** @brief Stores certificate file path */
3022f3563ccSZbigniew Lukwinski     std::string certFilePath;
3032f3563ccSZbigniew Lukwinski 
3042f3563ccSZbigniew Lukwinski     /** @brief Certificate file installation path */
305cf06ccdcSNan Zhou     std::string certInstallPath;
306ffad1ef1SMarri Devender Rao 
307cd30c496SMarri Devender Rao     /** @brief Type specific function pointer map for appending private key */
308cf06ccdcSNan Zhou     std::unordered_map<CertificateType, internal::AppendPrivKeyFunc>
309cf06ccdcSNan Zhou         appendKeyMap;
310cd30c496SMarri Devender Rao 
311cf06ccdcSNan Zhou     /** @brief Certificate file create/update watch
312cf06ccdcSNan Zhou      * Note that Certificate object doesn't own the pointer
313cf06ccdcSNan Zhou      */
314cf06ccdcSNan Zhou     Watch* certWatch;
315db029c95SKowalski, Kamil 
316a3bb38fbSZbigniew Kurzynski     /** @brief Reference to Certificate Manager */
317a3bb38fbSZbigniew Kurzynski     Manager& manager;
3186ceec40bSMarri Devender Rao };
3196ceec40bSMarri Devender Rao 
320e1289adfSNan Zhou } // namespace phosphor::certs
321