1 #pragma once
2 #include "config.h"
3 
4 #include "certificate.hpp"
5 #include "csr.hpp"
6 #include "watch.hpp"
7 
8 #include <filesystem>
9 #include <sdeventplus/source/child.hpp>
10 #include <sdeventplus/source/event.hpp>
11 #include <xyz/openbmc_project/Certs/CSR/Create/server.hpp>
12 #include <xyz/openbmc_project/Certs/Install/server.hpp>
13 #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
14 
15 namespace phosphor::certs
16 {
17 
18 namespace internal
19 {
20 using ManagerInterface = sdbusplus::server::object_t<
21     sdbusplus::xyz::openbmc_project::Certs::server::Install,
22     sdbusplus::xyz::openbmc_project::Certs::CSR::server::Create,
23     sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll>;
24 }
25 
26 class Manager : public internal::ManagerInterface
27 {
28   public:
29     /* Define all of the basic class operations:
30      *     Not allowed:
31      *         - Default constructor is not possible due to member
32      *           reference
33      *         - Move operations due to 'this' being registered as the
34      *           'context' with sdbus.
35      *     Allowed:
36      *         - copy
37      *         - Destructor.
38      */
39     Manager() = delete;
40     Manager(const Manager&) = delete;
41     Manager& operator=(const Manager&) = delete;
42     Manager(Manager&&) = delete;
43     Manager& operator=(Manager&&) = delete;
44     virtual ~Manager() = default;
45 
46     /** @brief Constructor to put object onto bus at a dbus path.
47      *  @param[in] bus - Bus to attach to.
48      *  @param[in] event - sd event handler.
49      *  @param[in] path - Path to attach at.
50      *  @param[in] type - Type of the certificate.
51      *  @param[in] unit - Unit consumed by this certificate.
52      *  @param[in] installPath - Certificate installation path.
53      */
54     Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event,
55             const char* path, CertificateType type, const std::string& unit,
56             const std::string& installPath);
57 
58     /** @brief Implementation for Install
59      *  Replace the existing certificate key file with another
60      *  (possibly CA signed) Certificate key file.
61      *
62      *  @param[in] filePath - Certificate key file path.
63      *
64      *  @return Certificate object path.
65      */
66     std::string install(const std::string filePath) override;
67 
68     /** @brief Implementation for DeleteAll
69      *  Delete all objects in the collection.
70      */
71     void deleteAll() override;
72 
73     /** @brief Delete the certificate.
74      */
75     void deleteCertificate(const Certificate* const certificate);
76 
77     /** @brief Replace the certificate.
78      */
79     void replaceCertificate(Certificate* const certificate,
80                             const std::string& filePath);
81 
82     /** @brief Generate Private key and CSR file
83      *  Generates the Private key file and CSR file based on the input
84      *  parameters. Validation of the parameters is callers responsibility.
85      *  At present supports only RSA algorithm type
86      *
87      *  @param[in] alternativeNames - Additional hostnames of the component that
88      *      is being secured.
89      *  @param[in] challengePassword - The challenge password to be applied to
90      *      the certificate for revocation requests.
91      *  @param[in] city - The city or locality of the organization making the
92      *      request. For Example Austin
93      *  @param[in] commonName - The fully qualified domain name of the component
94      *      that is being secured.
95      *  @param[in] contactPerson - The name of the user making the request.
96      *  @param[in] country - The country of the organization making the request.
97      *  @param[in] email - The email address of the contact within the
98      *      organization making the request.
99      *  @param[in] givenName - The given name of the user making the request.
100      *  @param[in] initials - The initials of the user making the request.
101      *  @param[in] keyBitLength - The length of the key in bits, if needed based
102      *      on the value of the KeyPairAlgorithm parameter.
103      *  @param[in] keyCurveId - The curve ID to be used with the key, if needed
104      *      based on the value of the KeyPairAlgorithm parameter.
105      *  @param[in] keyPairAlgorithm - The type of key pair for use with signing
106      *      algorithms. Valid built-in algorithm names for private key
107      *      generation are: RSA, DSA, DH and EC.
108      *  @param[in] keyUsage - Key usage extensions define the purpose of the
109      *      public key contained in a certificate. Valid Key usage extensions
110      *      and its usage description.
111      *      - ClientAuthentication: The public key is used for TLS WWW client
112      *      authentication.
113      *      - CodeSigning: The public key is used for the signing of executable
114      *          code
115      *      - CRLSigning: The public key is used for verifying signatures on
116      *          certificate revocation lists (CLRs).
117      *      - DataEncipherment: The public key is used for directly enciphering
118      *          raw user data without the use of an intermediate symmetric
119      *          cipher.
120      *      - DecipherOnly: The public key could be used for deciphering data
121      *          while performing key agreement.
122      *      - DigitalSignature: The public key is used for verifying digital
123      *          signatures, other than signatures on certificatesand CRLs.
124      *      - EmailProtection: The public key is used for email protection.
125      *      - EncipherOnly: Thepublic key could be used for enciphering data
126      *          while performing key agreement.
127      *      - KeyCertSign: The public key is used for verifying signatures on
128      *          public key certificates.
129      *      - KeyEncipherment: The public key is used for enciphering private or
130      *          secret keys.
131      *      - NonRepudiation: The public key is used to verify digital
132      *          signatures, other than signatures on certificates and CRLs, and
133      *          used to provide a non-repudiation service that protects against
134      *          the signing entity falsely denying some action.
135      *      - OCSPSigning: The public key is used for signing OCSP responses.
136      *      - ServerAuthentication: The public key is used for TLS WWW server
137      *          authentication.
138      *      - Timestamping: The public key is used for binding the hash of an
139      *          object to a time.
140      *  @param[in] organization - The legal name of the organization. This
141      *      should not be abbreviated and should include suffixes such as Inc,
142      *      Corp, or LLC.For example, IBM Corp.
143      *  @param[in] organizationalUnit - The name of the unit or division of the
144      *      organization making the request.
145      *  @param[in] state - The state or province where the organization is
146      *      located. This should not be abbreviated. For example, Texas.
147      *  @param[in] surname - The surname of the user making the request.
148      *  @param[in] unstructuredName - The unstructured name of the subject.
149      *
150      *  @return path[std::string] - The object path of the D-Bus object
151      *      representing CSR string. Note: For new CSR request will overwrite
152      * the existing CSR in the system.
153      */
154     std::string generateCSR(
155         std::vector<std::string> alternativeNames,
156         std::string challengePassword, std::string city, std::string commonName,
157         std::string contactPerson, std::string country, std::string email,
158         std::string givenName, std::string initials, int64_t keyBitLength,
159         std::string keyCurveId, std::string keyPairAlgorithm,
160         std::vector<std::string> keyUsage, std::string organization,
161         std::string organizationalUnit, std::string state, std::string surname,
162         std::string unstructuredName) override;
163 
164     /** @brief Get reference to certificates' collection
165      *
166      *  @return Reference to certificates' collection
167      */
168     std::vector<std::unique_ptr<Certificate>>& getCertificates();
169 
170   private:
171     void generateCSRHelper(std::vector<std::string> alternativeNames,
172                            std::string challengePassword, std::string city,
173                            std::string commonName, std::string contactPerson,
174                            std::string country, std::string email,
175                            std::string givenName, std::string initials,
176                            int64_t keyBitLength, std::string keyCurveId,
177                            std::string keyPairAlgorithm,
178                            std::vector<std::string> keyUsage,
179                            std::string organization,
180                            std::string organizationalUnit, std::string state,
181                            std::string surname, std::string unstructuredName);
182 
183     /** @brief Generate RSA Key pair and get private key from key pair
184      *  @param[in]  keyBitLength - KeyBit length.
185      *  @return     Pointer to RSA private key
186      */
187     std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
188         generateRSAKeyPair(const int64_t keyBitLength);
189 
190     /** @brief Generate EC Key pair and get private key from key pair
191      *  @param[in]  p_KeyCurveId - Curve ID
192      *  @return     Pointer to EC private key
193      */
194     std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
195         generateECKeyPair(const std::string& p_KeyCurveId);
196 
197     /** @brief Write private key data to file
198      *
199      *  @param[in] pKey     - pointer to private key
200      *  @param[in] privKeyFileName - private key filename
201      */
202     void writePrivateKey(
203         const std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>& pKey,
204         const std::string& privKeyFileName);
205 
206     /** @brief Add the specified CSR field with the data
207      *  @param[in] x509Name - Structure used in setting certificate properties
208      *  @param[in] field - field name
209      *  @param[in] bytes - field value in bytes
210      */
211     void addEntry(X509_NAME* x509Name, const char* field,
212                   const std::string& bytes);
213 
214     /** @brief Check if usage is extended key usage
215      *  @param[in] usage - key usage value
216      *  @return true if part of extended key usage
217      */
218     bool isExtendedKeyUsage(const std::string& usage);
219 
220     /** @brief Create CSR D-Bus object by reading the data in the CSR file
221      *  @param[in] statis - SUCCESS/FAILURE In CSR generation.
222      */
223     void createCSRObject(const Status& status);
224 
225     /** @brief Write generated CSR data to file
226      *
227      *  @param[in] filePath - CSR file path.
228      *  @param[in] x509Req - OpenSSL Request Pointer.
229      */
230     void writeCSR(
231         const std::string& filePath,
232         const std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>& x509Req);
233 
234     /** @brief Load certificate
235      *  Load certificate and create certificate object
236      */
237     void createCertificates();
238 
239     /** @brief Create RSA private key file
240      *  Create RSA private key file by generating rsa key if not created
241      */
242     void createRSAPrivateKeyFile();
243 
244     /** @brief Getting RSA private key
245      *  Getting RSA private key from generated file
246      *  @param[in]  keyBitLength - Key bit length
247      *  @return     Pointer to RSA key
248      */
249     std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
250         getRSAKeyPair(const int64_t keyBitLength);
251 
252     /** @brief Update certificate storage (remove outdated files, recreate
253      * symbolic links, etc.).
254      */
255     void storageUpdate();
256 
257     /** @brief Systemd unit reload or reset helper function
258      *  Reload if the unit supports it and use a restart otherwise.
259      *  @param[in] unit - service need to reload.
260      */
261     void reloadOrReset(const std::string& unit);
262 
263     /** @brief Check if provided certificate is unique across all certificates
264      * on the internal list.
265      *  @param[in] certFilePath - Path to the file with certificate for
266      * uniqueness check.
267      *  @param[in] certToDrop - Pointer to the certificate from the internal
268      * list which should be not taken into account while uniqueness check.
269      *  @return     Checking result. True if certificate is unique, false if
270      * not.
271      */
272     bool isCertificateUnique(const std::string& certFilePath,
273                              const Certificate* const certToDrop = nullptr);
274 
275     /** @brief sdbusplus handler */
276     sdbusplus::bus::bus& bus;
277 
278     // sdevent Event handle
279     sdeventplus::Event& event;
280 
281     /** @brief object path */
282     std::string objectPath;
283 
284     /** @brief Type of the certificate **/
285     CertificateType certType;
286 
287     /** @brief Unit name associated to the service **/
288     std::string unitToRestart;
289 
290     /** @brief Certificate file installation path **/
291     std::string certInstallPath;
292 
293     /** @brief Collection of pointers to certificate */
294     std::vector<std::unique_ptr<Certificate>> installedCerts;
295 
296     /** @brief pointer to CSR */
297     std::unique_ptr<CSR> csrPtr = nullptr;
298 
299     /** @brief SDEventPlus child pointer added to event loop */
300     std::unique_ptr<sdeventplus::source::Child> childPtr = nullptr;
301 
302     /** @brief Watch on self signed certificates */
303     std::unique_ptr<Watch> certWatchPtr = nullptr;
304 
305     /** @brief Parent path i.e certificate directory path */
306     std::filesystem::path certParentInstallPath;
307 
308     /** @brief Certificate ID pool */
309     uint64_t certIdCounter = 1;
310 };
311 } // namespace phosphor::certs
312