blob: e2864ebb9fada0e96e65510e24cefcd3ee7ca87c [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 Zhou014be0b2021-12-28 18:00:14 -08008#include <sdbusplus/server/object.hpp>
Marri Devender Raoedd11312019-02-27 08:45:10 -06009#include <xyz/openbmc_project/Certs/Certificate/server.hpp>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050010#include <xyz/openbmc_project/Certs/Replace/server.hpp>
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020011#include <xyz/openbmc_project/Object/Delete/server.hpp>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060012
Patrick Williams223e4602023-05-10 07:51:11 -050013#include <functional>
14#include <memory>
15#include <string>
16#include <string_view>
17#include <unordered_map>
18
Nan Zhoue1289ad2021-12-28 11:02:56 -080019namespace phosphor::certs
Marri Devender Rao6ceec402019-02-01 03:15:19 -060020{
Marri Devender Raoedd11312019-02-27 08:45:10 -060021
Nan Zhoucf06ccd2021-12-28 16:25:45 -080022// Certificate types
23enum class CertificateType
24{
Nan Zhoue3d47cd2022-09-16 03:41:53 +000025 authority,
26 server,
27 client,
28 unsupported,
Nan Zhoucf06ccd2021-12-28 16:25:45 -080029};
30
31inline constexpr const char* certificateTypeToString(CertificateType type)
32{
33 switch (type)
34 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000035 case CertificateType::authority:
Nan Zhoucf06ccd2021-12-28 16:25:45 -080036 return "authority";
Nan Zhoue3d47cd2022-09-16 03:41:53 +000037 case CertificateType::server:
Nan Zhoucf06ccd2021-12-28 16:25:45 -080038 return "server";
Nan Zhoue3d47cd2022-09-16 03:41:53 +000039 case CertificateType::client:
Nan Zhoucf06ccd2021-12-28 16:25:45 -080040 return "client";
41 default:
42 return "unsupported";
43 }
44}
45
46inline constexpr CertificateType stringToCertificateType(std::string_view type)
47{
48 if (type == "authority")
49 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000050 return CertificateType::authority;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080051 }
52 if (type == "server")
53 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000054 return CertificateType::server;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080055 }
56 if (type == "client")
57 {
Nan Zhoue3d47cd2022-09-16 03:41:53 +000058 return CertificateType::client;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080059 }
Nan Zhoue3d47cd2022-09-16 03:41:53 +000060 return CertificateType::unsupported;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080061}
62
63namespace internal
64{
65using CertificateInterface = sdbusplus::server::object_t<
66 sdbusplus::xyz::openbmc_project::Certs::server::Certificate,
67 sdbusplus::xyz::openbmc_project::Certs::server::Replace,
68 sdbusplus::xyz::openbmc_project::Object::server::Delete>;
Marri Devender Rao6ceec402019-02-01 03:15:19 -060069using InstallFunc = std::function<void(const std::string&)>;
Marri Devender Raocd30c492019-06-12 01:40:17 -050070using AppendPrivKeyFunc = std::function<void(const std::string&)>;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080071using X509Ptr = std::unique_ptr<X509, decltype(&::X509_free)>;
72} // namespace internal
Marri Devender Rao6ceec402019-02-01 03:15:19 -060073
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020074class Manager; // Forward declaration for Certificate Manager.
75
Marri Devender Rao6ceec402019-02-01 03:15:19 -060076/** @class Certificate
77 * @brief OpenBMC Certificate entry implementation.
78 * @details A concrete implementation for the
79 * xyz.openbmc_project.Certs.Certificate DBus API
Nan Zhoubf3cf752021-12-28 11:02:07 -080080 * xyz.openbmc_project.Certs.Install DBus API
Marri Devender Rao6ceec402019-02-01 03:15:19 -060081 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -080082class Certificate : public internal::CertificateInterface
Marri Devender Rao6ceec402019-02-01 03:15:19 -060083{
84 public:
85 Certificate() = delete;
86 Certificate(const Certificate&) = delete;
87 Certificate& operator=(const Certificate&) = delete;
88 Certificate(Certificate&&) = delete;
89 Certificate& operator=(Certificate&&) = delete;
90 virtual ~Certificate();
91
92 /** @brief Constructor for the Certificate Object
93 * @param[in] bus - Bus to attach to.
94 * @param[in] objPath - Object path to attach to
95 * @param[in] type - Type of the certificate
Marri Devender Rao6ceec402019-02-01 03:15:19 -060096 * @param[in] installPath - Path of the certificate to install
97 * @param[in] uploadPath - Path of the certificate file to upload
Nan Zhoucf06ccd2021-12-28 16:25:45 -080098 * @param[in] watchPtr - watch on self signed certificate
99 * @param[in] parent - the manager that owns the certificate
Willy Tu698a5742022-09-23 21:33:01 +0000100 * @param[in] restore - the certificate is created in the restore path
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600101 */
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500102 Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800103 CertificateType type, const std::string& installPath,
Willy Tu698a5742022-09-23 21:33:01 +0000104 const std::string& uploadPath, Watch* watch, Manager& parent,
105 bool restore);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100106
Nan Zhou6ec13c82021-12-30 11:34:50 -0800107 /** @brief Constructor for the Certificate Object; a variant for authorities
108 * list install
109 * @param[in] bus - Bus to attach to.
110 * @param[in] objPath - Object path to attach to
111 * @param[in] type - Type of the certificate
112 * @param[in] installPath - Path of the certificate to install
113 * @param[in] x509Store - an initialized X509 store used for certificate
114 * validation; Certificate object doesn't own it
115 * @param[in] pem - Content of the certificate file to upload; it shall be
116 * a single PEM encoded x509 certificate
117 * @param[in] watchPtr - watch on self signed certificate
118 * @param[in] parent - Pointer to the manager which owns the constructed
119 * Certificate object
Willy Tu698a5742022-09-23 21:33:01 +0000120 * @param[in] restore - the certificate is created in the restore path
Nan Zhou6ec13c82021-12-30 11:34:50 -0800121 */
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500122 Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
Nan Zhou6ec13c82021-12-30 11:34:50 -0800123 const CertificateType& type, const std::string& installPath,
124 X509_STORE& x509Store, const std::string& pem, Watch* watchPtr,
Willy Tu698a5742022-09-23 21:33:01 +0000125 Manager& parent, bool restore);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800126
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100127 /** @brief Validate and Replace/Install the certificate file
128 * Install/Replace the existing certificate file with another
129 * (possibly CA signed) Certificate file.
130 * @param[in] filePath - Certificate file path.
Willy Tu698a5742022-09-23 21:33:01 +0000131 * @param[in] restore - the certificate is created in the restore path
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100132 */
Willy Tu698a5742022-09-23 21:33:01 +0000133 void install(const std::string& filePath, bool restore);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600134
Nan Zhou6ec13c82021-12-30 11:34:50 -0800135 /** @brief Validate and Replace/Install the certificate file
136 * Install/Replace the existing certificate file with another
137 * (possibly CA signed) Certificate file.
138 * @param[in] x509Store - an initialized X509 store used for certificate
139 * validation; Certificate object doesn't own it
140 * @param[in] pem - a string buffer which stores a PEM encoded certificate.
Willy Tu698a5742022-09-23 21:33:01 +0000141 * @param[in] restore - the certificate is created in the restore path
Nan Zhou6ec13c82021-12-30 11:34:50 -0800142 */
Willy Tu698a5742022-09-23 21:33:01 +0000143 void install(X509_STORE& x509Store, const std::string& pem, bool restore);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800144
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500145 /** @brief Validate certificate and replace the existing certificate
146 * @param[in] filePath - Certificate file path.
147 */
148 void replace(const std::string filePath) override;
149
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500150 /** @brief Populate certificate properties by parsing certificate file
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500151 */
152 void populateProperties();
153
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200154 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100155 * @brief Obtain certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200156 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100157 * @return Certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200158 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100159 std::string getCertId() const;
160
161 /**
Nan Zhoubf3cf752021-12-28 11:02:07 -0800162 * @brief Check if provided certificate is the same as the current one.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100163 *
164 * @param[in] certPath - File path for certificate to check.
165 *
166 * @return Checking result. Return true if certificates are the same,
167 * false if not.
168 */
169 bool isSame(const std::string& certPath);
170
171 /**
172 * @brief Update certificate storage.
173 */
174 void storageUpdate();
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200175
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200176 /**
177 * @brief Delete the certificate
178 */
179 void delete_() override;
180
Nan Zhou6ec13c82021-12-30 11:34:50 -0800181 /**
182 * @brief Generate file name which is unique in the provided directory.
183 *
184 * @param[in] directoryPath - Directory path.
185 *
186 * @return File path.
187 */
188 static std::string generateUniqueFilePath(const std::string& directoryPath);
189
190 /**
191 * @brief Copies the certificate from sourceFilePath to installFilePath
192 *
193 * @param[in] sourceFilePath - Path to the source file.
194 * @param[in] certFilePath - Path to the destination file.
195 *
196 * @return void
197 */
198 static void copyCertificate(const std::string& certSrcFilePath,
199 const std::string& certFilePath);
200
201 /**
202 * @brief Returns the associated dbus object path.
203 */
204 std::string getObjectPath();
205
206 /**
207 * @brief Returns the associated cert file path.
208 */
209 std::string getCertFilePath();
210
211 /** @brief: Set the data member |certFilePath| to |path|
212 */
213 void setCertFilePath(const std::string& path);
214
215 /** @brief: Set the data member |certInstallPath| to |path|
216 */
217 void setCertInstallPath(const std::string& path);
218
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500219 private:
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200220 /**
Nan Zhoue869bb62021-12-30 11:34:42 -0800221 * @brief Populate certificate properties by parsing given certificate
222 * object
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500223 *
Nan Zhoue869bb62021-12-30 11:34:42 -0800224 * @param[in] cert The given certificate object
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500225 *
226 * @return void
227 */
Nan Zhoue869bb62021-12-30 11:34:42 -0800228 void populateProperties(X509& cert);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600229
Marri Devender Raocd30c492019-06-12 01:40:17 -0500230 /** @brief Check and append private key to the certificate file
231 * If private key is not present in the certificate file append the
232 * certificate file with private key existing in the system.
233 * @param[in] filePath - Certificate and key full file path.
234 * @return void.
235 */
236 void checkAndAppendPrivateKey(const std::string& filePath);
237
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600238 /** @brief Public/Private key compare function.
239 * Comparing private key against certificate public key
240 * from input .pem file.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500241 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600242 * @return Return true if Key compare is successful,
243 * false if not
244 */
245 bool compareKeys(const std::string& filePath);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500246
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100247 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100248 * @brief Generate authority certificate file path corresponding with
249 * OpenSSL requirements.
250 *
Nan Zhoubf3cf752021-12-28 11:02:07 -0800251 * Prepare authority certificate file path for provided certificate.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100252 * OpenSSL puts some restrictions on the certificate file name pattern.
253 * Certificate full file name needs to consists of basic file name which
254 * is certificate subject name hash and file name extension which is an
255 * integer. More over, certificates files names extensions must be
256 * consecutive integer numbers in case many certificates with the same
257 * subject name.
258 * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html
259 * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html
260 *
261 * @param[in] certSrcFilePath - Certificate source file path.
262 * @param[in] certDstDirPath - Certificate destination directory path.
263 *
264 * @return Authority certificate file path.
265 */
266 std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath,
267 const std::string& certDstDirPath);
268
269 /**
270 * @brief Generate authority certificate file path based on provided
271 * certificate source file path.
272 *
273 * @param[in] certSrcFilePath - Certificate source file path.
274 *
275 * @return Authority certificate file path.
276 */
277 std::string generateAuthCertFilePath(const std::string& certSrcFilePath);
278
279 /**
280 * @brief Generate certificate file path based on provided certificate
281 * source file path.
282 *
283 * @param[in] certSrcFilePath - Certificate source file path.
284 *
285 * @return Certificate file path.
286 */
287 std::string generateCertFilePath(const std::string& certSrcFilePath);
288
289 /** @brief Type specific function pointer map */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800290 std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600291
292 /** @brief object path */
293 std::string objectPath;
294
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100295 /** @brief Type of the certificate */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600296 CertificateType certType;
297
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100298 /** @brief Stores certificate ID */
299 std::string certId;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600300
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100301 /** @brief Stores certificate file path */
302 std::string certFilePath;
303
304 /** @brief Certificate file installation path */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800305 std::string certInstallPath;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500306
Marri Devender Raocd30c492019-06-12 01:40:17 -0500307 /** @brief Type specific function pointer map for appending private key */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800308 std::unordered_map<CertificateType, internal::AppendPrivKeyFunc>
309 appendKeyMap;
Marri Devender Raocd30c492019-06-12 01:40:17 -0500310
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800311 /** @brief Certificate file create/update watch
312 * Note that Certificate object doesn't own the pointer
313 */
314 Watch* certWatch;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200315
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200316 /** @brief Reference to Certificate Manager */
317 Manager& manager;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600318};
319
Nan Zhoue1289ad2021-12-28 11:02:56 -0800320} // namespace phosphor::certs