blob: 722f07f01837fe17131dbc57d5f691f2f889b6b2 [file] [log] [blame]
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -05001#pragma once
Jayanth Othayothdd74bd22018-09-28 06:13:35 -05002
Marri Devender Raof4682712019-03-19 05:00:28 -05003#include "certificate.hpp"
4#include "csr.hpp"
Marri Devender Raoffad1ef2019-06-03 04:54:12 -05005#include "watch.hpp"
Marri Devender Raof4682712019-03-19 05:00:28 -05006
Nan Zhou014be0b2021-12-28 18:00:14 -08007#include <openssl/evp.h>
8#include <openssl/ossl_typ.h>
9#include <openssl/x509.h>
10
Nan Zhou014be0b2021-12-28 18:00:14 -080011#include <sdbusplus/server/object.hpp>
Marri Devender Raof4682712019-03-19 05:00:28 -050012#include <sdeventplus/source/child.hpp>
13#include <sdeventplus/source/event.hpp>
14#include <xyz/openbmc_project/Certs/CSR/Create/server.hpp>
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050015#include <xyz/openbmc_project/Certs/Install/server.hpp>
Nan Zhou6ec13c82021-12-30 11:34:50 -080016#include <xyz/openbmc_project/Certs/InstallAll/server.hpp>
17#include <xyz/openbmc_project/Certs/ReplaceAll/server.hpp>
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020018#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050019
Patrick Williams223e4602023-05-10 07:51:11 -050020#include <cstdint>
21#include <filesystem>
22#include <memory>
23#include <string>
24#include <vector>
25
Nan Zhoue1289ad2021-12-28 11:02:56 -080026namespace phosphor::certs
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050027{
Marri Devender Raof4682712019-03-19 05:00:28 -050028
Nan Zhoucf06ccd2021-12-28 16:25:45 -080029namespace internal
30{
31using ManagerInterface = sdbusplus::server::object_t<
32 sdbusplus::xyz::openbmc_project::Certs::server::Install,
33 sdbusplus::xyz::openbmc_project::Certs::CSR::server::Create,
Nan Zhou6ec13c82021-12-30 11:34:50 -080034 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll,
35 sdbusplus::xyz::openbmc_project::Certs::server::InstallAll,
36 sdbusplus::xyz::openbmc_project::Certs::server::ReplaceAll>;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080037}
Jayanth Othayothb50789c2018-10-09 07:13:54 -050038
Nan Zhoucf06ccd2021-12-28 16:25:45 -080039class Manager : public internal::ManagerInterface
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050040{
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;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080053 Manager(const Manager&) = delete;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050054 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.
Marri Devender Raof4682712019-03-19 05:00:28 -050061 * @param[in] event - sd event handler.
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050062 * @param[in] path - Path to attach at.
63 * @param[in] type - Type of the certificate.
64 * @param[in] unit - Unit consumed by this certificate.
Marri Devender Rao6ceec402019-02-01 03:15:19 -060065 * @param[in] installPath - Certificate installation path.
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050066 */
Patrick Williamsb3dbfb32022-07-22 19:26:57 -050067 Manager(sdbusplus::bus_t& bus, sdeventplus::Event& event, const char* path,
68 CertificateType type, const std::string& unit,
Nan Zhoucf06ccd2021-12-28 16:25:45 -080069 const std::string& installPath);
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050070
71 /** @brief Implementation for Install
72 * Replace the existing certificate key file with another
73 * (possibly CA signed) Certificate key file.
74 *
Marri Devender Rao6ceec402019-02-01 03:15:19 -060075 * @param[in] filePath - Certificate key file path.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010076 *
77 * @return Certificate object path.
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050078 */
Zbigniew Kurzynski06a69d72019-09-27 10:57:38 +020079 std::string install(const std::string filePath) override;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050080
Nan Zhou6ec13c82021-12-30 11:34:50 -080081 /** @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 */
Patrick Williams1eb04fc2025-02-01 08:23:07 -050089 std::vector<sdbusplus::message::object_path> installAll(
90 std::string path) override;
Nan Zhou6ec13c82021-12-30 11:34:50 -080091
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 */
Patrick Williams1eb04fc2025-02-01 08:23:07 -050099 std::vector<sdbusplus::message::object_path> replaceAll(
100 std::string filePath) override;
Nan Zhou6ec13c82021-12-30 11:34:50 -0800101
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200102 /** @brief Implementation for DeleteAll
103 * Delete all objects in the collection.
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500104 */
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200105 void deleteAll() override;
106
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100107 /** @brief Delete the certificate.
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200108 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100109 void deleteCertificate(const Certificate* const certificate);
110
111 /** @brief Replace the certificate.
112 */
113 void replaceCertificate(Certificate* const certificate,
114 const std::string& filePath);
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500115
Marri Devender Raof4682712019-03-19 05:00:28 -0500116 /** @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
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200198 /** @brief Get reference to certificates' collection
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500199 *
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200200 * @return Reference to certificates' collection
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500201 */
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200202 std::vector<std::unique_ptr<Certificate>>& getCertificates();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500203
Nan Zhou6ec13c82021-12-30 11:34:50 -0800204 /** @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
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500210 private:
Patrick Williamsa2f68d82024-08-16 15:21:36 -0400211 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);
Marri Devender Raof4682712019-03-19 05:00:28 -0500220
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500221 /** @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 */
Patrick Williams1eb04fc2025-02-01 08:23:07 -0500225 std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)> generateRSAKeyPair(
226 const int64_t keyBitLength);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500227
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 */
Patrick Williams1eb04fc2025-02-01 08:23:07 -0500232 std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)> generateECKeyPair(
233 const std::string& pKeyCurveId);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500234
Marri Devender Raof4682712019-03-19 05:00:28 -0500235 /** @brief Write private key data to file
236 *
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500237 * @param[in] pKey - pointer to private key
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500238 * @param[in] privKeyFileName - private key filename
Marri Devender Raof4682712019-03-19 05:00:28 -0500239 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800240 void writePrivateKey(
241 const std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>& pKey,
242 const std::string& privKeyFileName);
Marri Devender Raof4682712019-03-19 05:00:28 -0500243
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
Marri Devender Rao76411052019-08-07 01:25:07 -0500252 /** @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
Marri Devender Raof4682712019-03-19 05:00:28 -0500258 /** @brief Create CSR D-Bus object by reading the data in the CSR file
Nan Zhoubf3cf752021-12-28 11:02:07 -0800259 * @param[in] statis - SUCCESS/FAILURE In CSR generation.
Marri Devender Raof4682712019-03-19 05:00:28 -0500260 */
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 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800268 void writeCSR(
269 const std::string& filePath,
270 const std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>& x509Req);
Marri Devender Raof4682712019-03-19 05:00:28 -0500271
Nan Zhoubf3cf752021-12-28 11:02:07 -0800272 /** @brief Load certificate
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500273 * Load certificate and create certificate object
274 */
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200275 void createCertificates();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500276
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500277 /** @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
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100283 * Getting RSA private key from generated file
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500284 * @param[in] keyBitLength - Key bit length
285 * @return Pointer to RSA key
286 */
Patrick Williams1eb04fc2025-02-01 08:23:07 -0500287 std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)> getRSAKeyPair(
288 const int64_t keyBitLength);
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500289
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100290 /** @brief Update certificate storage (remove outdated files, recreate
291 * symbolic links, etc.).
292 */
293 void storageUpdate();
294
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100295 /** @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
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500307 /** @brief sdbusplus handler */
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500308 sdbusplus::bus_t& bus;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500309
Marri Devender Raof4682712019-03-19 05:00:28 -0500310 // sdevent Event handle
311 sdeventplus::Event& event;
312
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500313 /** @brief object path */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600314 std::string objectPath;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500315
316 /** @brief Type of the certificate **/
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600317 CertificateType certType;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500318
319 /** @brief Unit name associated to the service **/
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800320 std::string unitToRestart;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500321
322 /** @brief Certificate file installation path **/
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800323 std::string certInstallPath;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500324
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200325 /** @brief Collection of pointers to certificate */
326 std::vector<std::unique_ptr<Certificate>> installedCerts;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500327
Marri Devender Raof4682712019-03-19 05:00:28 -0500328 /** @brief pointer to CSR */
329 std::unique_ptr<CSR> csrPtr = nullptr;
330
331 /** @brief SDEventPlus child pointer added to event loop */
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500332 std::unique_ptr<sdeventplus::source::Child> childPtr = nullptr;
333
334 /** @brief Watch on self signed certificates */
335 std::unique_ptr<Watch> certWatchPtr = nullptr;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500336
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100337 /** @brief Parent path i.e certificate directory path */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800338 std::filesystem::path certParentInstallPath;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200339
340 /** @brief Certificate ID pool */
341 uint64_t certIdCounter = 1;
Marri Devender Raof4682712019-03-19 05:00:28 -0500342};
Nan Zhoue1289ad2021-12-28 11:02:56 -0800343} // namespace phosphor::certs