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