blob: c96017f4bff43d2820a2a207526ce12ea57d6d8d [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{
24 Authority,
25 Server,
26 Client,
27 Unsupported,
28};
29
30inline constexpr const char* certificateTypeToString(CertificateType type)
31{
32 switch (type)
33 {
34 case CertificateType::Authority:
35 return "authority";
36 case CertificateType::Server:
37 return "server";
38 case CertificateType::Client:
39 return "client";
40 default:
41 return "unsupported";
42 }
43}
44
45inline constexpr CertificateType stringToCertificateType(std::string_view type)
46{
47 if (type == "authority")
48 {
49 return CertificateType::Authority;
50 }
51 if (type == "server")
52 {
53 return CertificateType::Server;
54 }
55 if (type == "client")
56 {
57 return CertificateType::Client;
58 }
59 return CertificateType::Unsupported;
60}
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
Marri Devender Rao6ceec402019-02-01 03:15:19 -060099 */
100 Certificate(sdbusplus::bus::bus& bus, const std::string& objPath,
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800101 CertificateType type, const std::string& installPath,
102 const std::string& uploadPath, Watch* watch, Manager& parent);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100103
104 /** @brief Validate and Replace/Install the certificate file
105 * Install/Replace the existing certificate file with another
106 * (possibly CA signed) Certificate file.
107 * @param[in] filePath - Certificate file path.
108 */
109 void install(const std::string& filePath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600110
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500111 /** @brief Validate certificate and replace the existing certificate
112 * @param[in] filePath - Certificate file path.
113 */
114 void replace(const std::string filePath) override;
115
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500116 /** @brief Populate certificate properties by parsing certificate file
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500117 */
118 void populateProperties();
119
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200120 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100121 * @brief Obtain certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200122 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100123 * @return Certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200124 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100125 std::string getCertId() const;
126
127 /**
Nan Zhoubf3cf752021-12-28 11:02:07 -0800128 * @brief Check if provided certificate is the same as the current one.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100129 *
130 * @param[in] certPath - File path for certificate to check.
131 *
132 * @return Checking result. Return true if certificates are the same,
133 * false if not.
134 */
135 bool isSame(const std::string& certPath);
136
137 /**
138 * @brief Update certificate storage.
139 */
140 void storageUpdate();
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200141
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200142 /**
143 * @brief Delete the certificate
144 */
145 void delete_() override;
146
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500147 private:
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200148 /**
Nan Zhoucf811c42021-12-02 14:56:17 -0800149 * @brief Return error if ceritificate NotBefore date is lt 1970
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500150 *
Nan Zhoucf811c42021-12-02 14:56:17 -0800151 * Parse the certificate and return error if certificate NotBefore date
152 * is lt 1970.
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500153 *
154 * @param[in] cert Reference to certificate object uploaded
155 *
156 * @return void
157 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800158 void validateCertificateStartDate(X509& cert);
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500159
160 /**
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200161 * @brief Populate certificate properties by parsing given certificate file
162 *
163 * @param[in] certPath Path to certificate that should be parsed
164 *
165 * @return void
166 */
167 void populateProperties(const std::string& certPath);
168
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100169 /** @brief Load Certificate file into the X509 structure.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500170 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600171 * @return pointer to the X509 structure.
172 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800173 internal::X509Ptr loadCert(const std::string& filePath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600174
Marri Devender Raocd30c492019-06-12 01:40:17 -0500175 /** @brief Check and append private key to the certificate file
176 * If private key is not present in the certificate file append the
177 * certificate file with private key existing in the system.
178 * @param[in] filePath - Certificate and key full file path.
179 * @return void.
180 */
181 void checkAndAppendPrivateKey(const std::string& filePath);
182
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600183 /** @brief Public/Private key compare function.
184 * Comparing private key against certificate public key
185 * from input .pem file.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500186 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600187 * @return Return true if Key compare is successful,
188 * false if not
189 */
190 bool compareKeys(const std::string& filePath);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500191
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100192 /**
193 * @brief Generate certificate ID based on provided certificate file.
194 *
195 * @param[in] certPath - Certificate file path.
196 *
197 * @return Certificate ID as formatted string.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600198 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100199 std::string generateCertId(const std::string& certPath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600200
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200201 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100202 * @brief Generate file name which is unique in the provided directory.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200203 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100204 * @param[in] directoryPath - Directory path.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200205 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100206 * @return File path.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200207 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100208 std::string generateUniqueFilePath(const std::string& directoryPath);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200209
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100210 /**
211 * @brief Generate authority certificate file path corresponding with
212 * OpenSSL requirements.
213 *
Nan Zhoubf3cf752021-12-28 11:02:07 -0800214 * Prepare authority certificate file path for provided certificate.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100215 * OpenSSL puts some restrictions on the certificate file name pattern.
216 * Certificate full file name needs to consists of basic file name which
217 * is certificate subject name hash and file name extension which is an
218 * integer. More over, certificates files names extensions must be
219 * consecutive integer numbers in case many certificates with the same
220 * subject name.
221 * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html
222 * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html
223 *
224 * @param[in] certSrcFilePath - Certificate source file path.
225 * @param[in] certDstDirPath - Certificate destination directory path.
226 *
227 * @return Authority certificate file path.
228 */
229 std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath,
230 const std::string& certDstDirPath);
231
232 /**
233 * @brief Generate authority certificate file path based on provided
234 * certificate source file path.
235 *
236 * @param[in] certSrcFilePath - Certificate source file path.
237 *
238 * @return Authority certificate file path.
239 */
240 std::string generateAuthCertFilePath(const std::string& certSrcFilePath);
241
242 /**
243 * @brief Generate certificate file path based on provided certificate
244 * source file path.
245 *
246 * @param[in] certSrcFilePath - Certificate source file path.
247 *
248 * @return Certificate file path.
249 */
250 std::string generateCertFilePath(const std::string& certSrcFilePath);
251
252 /** @brief Type specific function pointer map */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800253 std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600254
255 /** @brief object path */
256 std::string objectPath;
257
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100258 /** @brief Type of the certificate */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600259 CertificateType certType;
260
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100261 /** @brief Stores certificate ID */
262 std::string certId;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600263
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100264 /** @brief Stores certificate file path */
265 std::string certFilePath;
266
267 /** @brief Certificate file installation path */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800268 std::string certInstallPath;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500269
Marri Devender Raocd30c492019-06-12 01:40:17 -0500270 /** @brief Type specific function pointer map for appending private key */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800271 std::unordered_map<CertificateType, internal::AppendPrivKeyFunc>
272 appendKeyMap;
Marri Devender Raocd30c492019-06-12 01:40:17 -0500273
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800274 /** @brief Certificate file create/update watch
275 * Note that Certificate object doesn't own the pointer
276 */
277 Watch* certWatch;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200278
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200279 /** @brief Reference to Certificate Manager */
280 Manager& manager;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600281};
282
Nan Zhoue1289ad2021-12-28 11:02:56 -0800283} // namespace phosphor::certs