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(
212         std::vector<std::string> alternativeNames,
213         std::string challengePassword, std::string city, std::string commonName,
214         std::string contactPerson, std::string country, std::string email,
215         std::string givenName, std::string initials, int64_t keyBitLength,
216         std::string keyCurveId, std::string keyPairAlgorithm,
217         std::vector<std::string> keyUsage, std::string organization,
218         std::string organizationalUnit, std::string state, std::string surname,
219         std::string unstructuredName);
220 
221     /** @brief Generate RSA Key pair and get private key from key pair
222      *  @param[in]  keyBitLength - KeyBit length.
223      *  @return     Pointer to RSA private key
224      */
225     std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
226         generateRSAKeyPair(const int64_t keyBitLength);
227 
228     /** @brief Generate EC Key pair and get private key from key pair
229      *  @param[in]  p_KeyCurveId - Curve ID
230      *  @return     Pointer to EC private key
231      */
232     std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
233         generateECKeyPair(const std::string& pKeyCurveId);
234 
235     /** @brief Write private key data to file
236      *
237      *  @param[in] pKey     - pointer to private key
238      *  @param[in] privKeyFileName - private key filename
239      */
240     void writePrivateKey(
241         const std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>& pKey,
242         const std::string& privKeyFileName);
243 
244     /** @brief Add the specified CSR field with the data
245      *  @param[in] x509Name - Structure used in setting certificate properties
246      *  @param[in] field - field name
247      *  @param[in] bytes - field value in bytes
248      */
249     void addEntry(X509_NAME* x509Name, const char* field,
250                   const std::string& bytes);
251 
252     /** @brief Check if usage is extended key usage
253      *  @param[in] usage - key usage value
254      *  @return true if part of extended key usage
255      */
256     bool isExtendedKeyUsage(const std::string& usage);
257 
258     /** @brief Create CSR D-Bus object by reading the data in the CSR file
259      *  @param[in] statis - SUCCESS/FAILURE In CSR generation.
260      */
261     void createCSRObject(const Status& status);
262 
263     /** @brief Write generated CSR data to file
264      *
265      *  @param[in] filePath - CSR file path.
266      *  @param[in] x509Req - OpenSSL Request Pointer.
267      */
268     void writeCSR(
269         const std::string& filePath,
270         const std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>& x509Req);
271 
272     /** @brief Load certificate
273      *  Load certificate and create certificate object
274      */
275     void createCertificates();
276 
277     /** @brief Create RSA private key file
278      *  Create RSA private key file by generating rsa key if not created
279      */
280     void createRSAPrivateKeyFile();
281 
282     /** @brief Getting RSA private key
283      *  Getting RSA private key from generated file
284      *  @param[in]  keyBitLength - Key bit length
285      *  @return     Pointer to RSA key
286      */
287     std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
288         getRSAKeyPair(const int64_t keyBitLength);
289 
290     /** @brief Update certificate storage (remove outdated files, recreate
291      * symbolic links, etc.).
292      */
293     void storageUpdate();
294 
295     /** @brief Check if provided certificate is unique across all certificates
296      * on the internal list.
297      *  @param[in] certFilePath - Path to the file with certificate for
298      * uniqueness check.
299      *  @param[in] certToDrop - Pointer to the certificate from the internal
300      * list which should be not taken into account while uniqueness check.
301      *  @return     Checking result. True if certificate is unique, false if
302      * not.
303      */
304     bool isCertificateUnique(const std::string& certFilePath,
305                              const Certificate* const certToDrop = nullptr);
306 
307     /** @brief sdbusplus handler */
308     sdbusplus::bus_t& bus;
309 
310     // sdevent Event handle
311     sdeventplus::Event& event;
312 
313     /** @brief object path */
314     std::string objectPath;
315 
316     /** @brief Type of the certificate **/
317     CertificateType certType;
318 
319     /** @brief Unit name associated to the service **/
320     std::string unitToRestart;
321 
322     /** @brief Certificate file installation path **/
323     std::string certInstallPath;
324 
325     /** @brief Collection of pointers to certificate */
326     std::vector<std::unique_ptr<Certificate>> installedCerts;
327 
328     /** @brief pointer to CSR */
329     std::unique_ptr<CSR> csrPtr = nullptr;
330 
331     /** @brief SDEventPlus child pointer added to event loop */
332     std::unique_ptr<sdeventplus::source::Child> childPtr = nullptr;
333 
334     /** @brief Watch on self signed certificates */
335     std::unique_ptr<Watch> certWatchPtr = nullptr;
336 
337     /** @brief Parent path i.e certificate directory path */
338     std::filesystem::path certParentInstallPath;
339 
340     /** @brief Certificate ID pool */
341     uint64_t certIdCounter = 1;
342 };
343 } // namespace phosphor::certs
344