blob: 8a5f70e9bc9aaa863574cd6722727254402b1e8c [file] [log] [blame]
Marri Devender Rao6ceec402019-02-01 03:15:19 -06001#pragma once
2
Marri Devender Raoffad1ef2019-06-03 04:54:12 -05003#include "watch.hpp"
4
Nan Zhou014be0b2021-12-28 18:00:14 -08005#include <openssl/ossl_typ.h>
Marri Devender Rao6ceec402019-02-01 03:15:19 -06006#include <openssl/x509.h>
7
Nan Zhoucf06ccd2021-12-28 16:25:45 -08008#include <functional>
9#include <memory>
Nan Zhou014be0b2021-12-28 18:00:14 -080010#include <sdbusplus/server/object.hpp>
11#include <string>
12#include <string_view>
13#include <unordered_map>
Marri Devender Raoedd11312019-02-27 08:45:10 -060014#include <xyz/openbmc_project/Certs/Certificate/server.hpp>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050015#include <xyz/openbmc_project/Certs/Replace/server.hpp>
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020016#include <xyz/openbmc_project/Object/Delete/server.hpp>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060017
Nan Zhoue1289ad2021-12-28 11:02:56 -080018namespace phosphor::certs
Marri Devender Rao6ceec402019-02-01 03:15:19 -060019{
Marri Devender Raoedd11312019-02-27 08:45:10 -060020
Nan Zhoucf06ccd2021-12-28 16:25:45 -080021// Certificate types
22enum class CertificateType
23{
Nan Zhoue3d47cd2022-09-16 03:41:53 +000024 authority,
25 server,
26 client,
27 unsupported,
Nan Zhoucf06ccd2021-12-28 16:25:45 -080028};
29
30inline constexpr const char* certificateTypeToString(CertificateType type)
31{
32 switch (type)
33 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000034 case CertificateType::authority:
Nan Zhoucf06ccd2021-12-28 16:25:45 -080035 return "authority";
Nan Zhoue3d47cd2022-09-16 03:41:53 +000036 case CertificateType::server:
Nan Zhoucf06ccd2021-12-28 16:25:45 -080037 return "server";
Nan Zhoue3d47cd2022-09-16 03:41:53 +000038 case CertificateType::client:
Nan Zhoucf06ccd2021-12-28 16:25:45 -080039 return "client";
40 default:
41 return "unsupported";
42 }
43}
44
45inline constexpr CertificateType stringToCertificateType(std::string_view type)
46{
47 if (type == "authority")
48 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000049 return CertificateType::authority;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080050 }
51 if (type == "server")
52 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000053 return CertificateType::server;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080054 }
55 if (type == "client")
56 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000057 return CertificateType::client;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080058 }
Nan Zhoue3d47cd2022-09-16 03:41:53 +000059 return CertificateType::unsupported;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080060}
61
62namespace internal
63{
64using CertificateInterface = sdbusplus::server::object_t<
65 sdbusplus::xyz::openbmc_project::Certs::server::Certificate,
66 sdbusplus::xyz::openbmc_project::Certs::server::Replace,
67 sdbusplus::xyz::openbmc_project::Object::server::Delete>;
Marri Devender Rao6ceec402019-02-01 03:15:19 -060068using InstallFunc = std::function<void(const std::string&)>;
Marri Devender Raocd30c492019-06-12 01:40:17 -050069using AppendPrivKeyFunc = std::function<void(const std::string&)>;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080070using X509Ptr = std::unique_ptr<X509, decltype(&::X509_free)>;
71} // namespace internal
Marri Devender Rao6ceec402019-02-01 03:15:19 -060072
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020073class Manager; // Forward declaration for Certificate Manager.
74
Marri Devender Rao6ceec402019-02-01 03:15:19 -060075/** @class Certificate
76 * @brief OpenBMC Certificate entry implementation.
77 * @details A concrete implementation for the
78 * xyz.openbmc_project.Certs.Certificate DBus API
Nan Zhoubf3cf752021-12-28 11:02:07 -080079 * xyz.openbmc_project.Certs.Install DBus API
Marri Devender Rao6ceec402019-02-01 03:15:19 -060080 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -080081class Certificate : public internal::CertificateInterface
Marri Devender Rao6ceec402019-02-01 03:15:19 -060082{
83 public:
84 Certificate() = delete;
85 Certificate(const Certificate&) = delete;
86 Certificate& operator=(const Certificate&) = delete;
87 Certificate(Certificate&&) = delete;
88 Certificate& operator=(Certificate&&) = delete;
89 virtual ~Certificate();
90
91 /** @brief Constructor for the Certificate Object
92 * @param[in] bus - Bus to attach to.
93 * @param[in] objPath - Object path to attach to
94 * @param[in] type - Type of the certificate
Marri Devender Rao6ceec402019-02-01 03:15:19 -060095 * @param[in] installPath - Path of the certificate to install
96 * @param[in] uploadPath - Path of the certificate file to upload
Nan Zhoucf06ccd2021-12-28 16:25:45 -080097 * @param[in] watchPtr - watch on self signed certificate
98 * @param[in] parent - the manager that owns the certificate
Willy Tu698a5742022-09-23 21:33:01 +000099 * @param[in] restore - the certificate is created in the restore path
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600100 */
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500101 Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800102 CertificateType type, const std::string& installPath,
Willy Tu698a5742022-09-23 21:33:01 +0000103 const std::string& uploadPath, Watch* watch, Manager& parent,
104 bool restore);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100105
Nan Zhou6ec13c82021-12-30 11:34:50 -0800106 /** @brief Constructor for the Certificate Object; a variant for authorities
107 * list install
108 * @param[in] bus - Bus to attach to.
109 * @param[in] objPath - Object path to attach to
110 * @param[in] type - Type of the certificate
111 * @param[in] installPath - Path of the certificate to install
112 * @param[in] x509Store - an initialized X509 store used for certificate
113 * validation; Certificate object doesn't own it
114 * @param[in] pem - Content of the certificate file to upload; it shall be
115 * a single PEM encoded x509 certificate
116 * @param[in] watchPtr - watch on self signed certificate
117 * @param[in] parent - Pointer to the manager which owns the constructed
118 * Certificate object
Willy Tu698a5742022-09-23 21:33:01 +0000119 * @param[in] restore - the certificate is created in the restore path
Nan Zhou6ec13c82021-12-30 11:34:50 -0800120 */
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500121 Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
Nan Zhou6ec13c82021-12-30 11:34:50 -0800122 const CertificateType& type, const std::string& installPath,
123 X509_STORE& x509Store, const std::string& pem, Watch* watchPtr,
Willy Tu698a5742022-09-23 21:33:01 +0000124 Manager& parent, bool restore);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800125
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100126 /** @brief Validate and Replace/Install the certificate file
127 * Install/Replace the existing certificate file with another
128 * (possibly CA signed) Certificate file.
129 * @param[in] filePath - Certificate file path.
Willy Tu698a5742022-09-23 21:33:01 +0000130 * @param[in] restore - the certificate is created in the restore path
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100131 */
Willy Tu698a5742022-09-23 21:33:01 +0000132 void install(const std::string& filePath, bool restore);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600133
Nan Zhou6ec13c82021-12-30 11:34:50 -0800134 /** @brief Validate and Replace/Install the certificate file
135 * Install/Replace the existing certificate file with another
136 * (possibly CA signed) Certificate file.
137 * @param[in] x509Store - an initialized X509 store used for certificate
138 * validation; Certificate object doesn't own it
139 * @param[in] pem - a string buffer which stores a PEM encoded certificate.
Willy Tu698a5742022-09-23 21:33:01 +0000140 * @param[in] restore - the certificate is created in the restore path
Nan Zhou6ec13c82021-12-30 11:34:50 -0800141 */
Willy Tu698a5742022-09-23 21:33:01 +0000142 void install(X509_STORE& x509Store, const std::string& pem, bool restore);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800143
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500144 /** @brief Validate certificate and replace the existing certificate
145 * @param[in] filePath - Certificate file path.
146 */
147 void replace(const std::string filePath) override;
148
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500149 /** @brief Populate certificate properties by parsing certificate file
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500150 */
151 void populateProperties();
152
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200153 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100154 * @brief Obtain certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200155 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100156 * @return Certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200157 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100158 std::string getCertId() const;
159
160 /**
Nan Zhoubf3cf752021-12-28 11:02:07 -0800161 * @brief Check if provided certificate is the same as the current one.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100162 *
163 * @param[in] certPath - File path for certificate to check.
164 *
165 * @return Checking result. Return true if certificates are the same,
166 * false if not.
167 */
168 bool isSame(const std::string& certPath);
169
170 /**
171 * @brief Update certificate storage.
172 */
173 void storageUpdate();
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200174
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200175 /**
176 * @brief Delete the certificate
177 */
178 void delete_() override;
179
Nan Zhou6ec13c82021-12-30 11:34:50 -0800180 /**
181 * @brief Generate file name which is unique in the provided directory.
182 *
183 * @param[in] directoryPath - Directory path.
184 *
185 * @return File path.
186 */
187 static std::string generateUniqueFilePath(const std::string& directoryPath);
188
189 /**
190 * @brief Copies the certificate from sourceFilePath to installFilePath
191 *
192 * @param[in] sourceFilePath - Path to the source file.
193 * @param[in] certFilePath - Path to the destination file.
194 *
195 * @return void
196 */
197 static void copyCertificate(const std::string& certSrcFilePath,
198 const std::string& certFilePath);
199
200 /**
201 * @brief Returns the associated dbus object path.
202 */
203 std::string getObjectPath();
204
205 /**
206 * @brief Returns the associated cert file path.
207 */
208 std::string getCertFilePath();
209
210 /** @brief: Set the data member |certFilePath| to |path|
211 */
212 void setCertFilePath(const std::string& path);
213
214 /** @brief: Set the data member |certInstallPath| to |path|
215 */
216 void setCertInstallPath(const std::string& path);
217
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500218 private:
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200219 /**
Nan Zhoue869bb62021-12-30 11:34:42 -0800220 * @brief Populate certificate properties by parsing given certificate
221 * object
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500222 *
Nan Zhoue869bb62021-12-30 11:34:42 -0800223 * @param[in] cert The given certificate object
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500224 *
225 * @return void
226 */
Nan Zhoue869bb62021-12-30 11:34:42 -0800227 void populateProperties(X509& cert);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600228
Marri Devender Raocd30c492019-06-12 01:40:17 -0500229 /** @brief Check and append private key to the certificate file
230 * If private key is not present in the certificate file append the
231 * certificate file with private key existing in the system.
232 * @param[in] filePath - Certificate and key full file path.
233 * @return void.
234 */
235 void checkAndAppendPrivateKey(const std::string& filePath);
236
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600237 /** @brief Public/Private key compare function.
238 * Comparing private key against certificate public key
239 * from input .pem file.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500240 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600241 * @return Return true if Key compare is successful,
242 * false if not
243 */
244 bool compareKeys(const std::string& filePath);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500245
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100246 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100247 * @brief Generate authority certificate file path corresponding with
248 * OpenSSL requirements.
249 *
Nan Zhoubf3cf752021-12-28 11:02:07 -0800250 * Prepare authority certificate file path for provided certificate.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100251 * OpenSSL puts some restrictions on the certificate file name pattern.
252 * Certificate full file name needs to consists of basic file name which
253 * is certificate subject name hash and file name extension which is an
254 * integer. More over, certificates files names extensions must be
255 * consecutive integer numbers in case many certificates with the same
256 * subject name.
257 * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html
258 * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html
259 *
260 * @param[in] certSrcFilePath - Certificate source file path.
261 * @param[in] certDstDirPath - Certificate destination directory path.
262 *
263 * @return Authority certificate file path.
264 */
265 std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath,
266 const std::string& certDstDirPath);
267
268 /**
269 * @brief Generate authority certificate file path based on provided
270 * certificate source file path.
271 *
272 * @param[in] certSrcFilePath - Certificate source file path.
273 *
274 * @return Authority certificate file path.
275 */
276 std::string generateAuthCertFilePath(const std::string& certSrcFilePath);
277
278 /**
279 * @brief Generate certificate file path based on provided certificate
280 * source file path.
281 *
282 * @param[in] certSrcFilePath - Certificate source file path.
283 *
284 * @return Certificate file path.
285 */
286 std::string generateCertFilePath(const std::string& certSrcFilePath);
287
288 /** @brief Type specific function pointer map */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800289 std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600290
291 /** @brief object path */
292 std::string objectPath;
293
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100294 /** @brief Type of the certificate */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600295 CertificateType certType;
296
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100297 /** @brief Stores certificate ID */
298 std::string certId;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600299
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100300 /** @brief Stores certificate file path */
301 std::string certFilePath;
302
303 /** @brief Certificate file installation path */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800304 std::string certInstallPath;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500305
Marri Devender Raocd30c492019-06-12 01:40:17 -0500306 /** @brief Type specific function pointer map for appending private key */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800307 std::unordered_map<CertificateType, internal::AppendPrivKeyFunc>
308 appendKeyMap;
Marri Devender Raocd30c492019-06-12 01:40:17 -0500309
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800310 /** @brief Certificate file create/update watch
311 * Note that Certificate object doesn't own the pointer
312 */
313 Watch* certWatch;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200314
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200315 /** @brief Reference to Certificate Manager */
316 Manager& manager;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600317};
318
Nan Zhoue1289ad2021-12-28 11:02:56 -0800319} // namespace phosphor::certs