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