blob: 46479e40bfc1d407fe83559dbb668c9b9fa8845d [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
Marri Devender Rao6ceec402019-02-01 03:15:19 -06005#include <openssl/x509.h>
6
7#include <filesystem>
Nan Zhoucf06ccd2021-12-28 16:25:45 -08008#include <functional>
9#include <memory>
10#include <optional>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060011#include <phosphor-logging/elog.hpp>
Marri Devender Raoedd11312019-02-27 08:45:10 -060012#include <xyz/openbmc_project/Certs/Certificate/server.hpp>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050013#include <xyz/openbmc_project/Certs/Replace/server.hpp>
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020014#include <xyz/openbmc_project/Object/Delete/server.hpp>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060015
Nan Zhoue1289ad2021-12-28 11:02:56 -080016namespace phosphor::certs
Marri Devender Rao6ceec402019-02-01 03:15:19 -060017{
Marri Devender Raoedd11312019-02-27 08:45:10 -060018
Nan Zhoucf06ccd2021-12-28 16:25:45 -080019// Certificate types
20enum class CertificateType
21{
22 Authority,
23 Server,
24 Client,
25 Unsupported,
26};
27
28inline constexpr const char* certificateTypeToString(CertificateType type)
29{
30 switch (type)
31 {
32 case CertificateType::Authority:
33 return "authority";
34 case CertificateType::Server:
35 return "server";
36 case CertificateType::Client:
37 return "client";
38 default:
39 return "unsupported";
40 }
41}
42
43inline constexpr CertificateType stringToCertificateType(std::string_view type)
44{
45 if (type == "authority")
46 {
47 return CertificateType::Authority;
48 }
49 if (type == "server")
50 {
51 return CertificateType::Server;
52 }
53 if (type == "client")
54 {
55 return CertificateType::Client;
56 }
57 return CertificateType::Unsupported;
58}
59
60namespace internal
61{
62using CertificateInterface = sdbusplus::server::object_t<
63 sdbusplus::xyz::openbmc_project::Certs::server::Certificate,
64 sdbusplus::xyz::openbmc_project::Certs::server::Replace,
65 sdbusplus::xyz::openbmc_project::Object::server::Delete>;
Marri Devender Rao6ceec402019-02-01 03:15:19 -060066using InstallFunc = std::function<void(const std::string&)>;
Marri Devender Raocd30c492019-06-12 01:40:17 -050067using AppendPrivKeyFunc = std::function<void(const std::string&)>;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080068using X509Ptr = std::unique_ptr<X509, decltype(&::X509_free)>;
69} // namespace internal
Marri Devender Rao6ceec402019-02-01 03:15:19 -060070
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020071class Manager; // Forward declaration for Certificate Manager.
72
Marri Devender Rao6ceec402019-02-01 03:15:19 -060073/** @class Certificate
74 * @brief OpenBMC Certificate entry implementation.
75 * @details A concrete implementation for the
76 * xyz.openbmc_project.Certs.Certificate DBus API
Nan Zhoubf3cf752021-12-28 11:02:07 -080077 * xyz.openbmc_project.Certs.Install DBus API
Marri Devender Rao6ceec402019-02-01 03:15:19 -060078 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -080079class Certificate : public internal::CertificateInterface
Marri Devender Rao6ceec402019-02-01 03:15:19 -060080{
81 public:
82 Certificate() = delete;
83 Certificate(const Certificate&) = delete;
84 Certificate& operator=(const Certificate&) = delete;
85 Certificate(Certificate&&) = delete;
86 Certificate& operator=(Certificate&&) = delete;
87 virtual ~Certificate();
88
89 /** @brief Constructor for the Certificate Object
90 * @param[in] bus - Bus to attach to.
91 * @param[in] objPath - Object path to attach to
92 * @param[in] type - Type of the certificate
Marri Devender Rao6ceec402019-02-01 03:15:19 -060093 * @param[in] installPath - Path of the certificate to install
94 * @param[in] uploadPath - Path of the certificate file to upload
Nan Zhoucf06ccd2021-12-28 16:25:45 -080095 * @param[in] watchPtr - watch on self signed certificate
96 * @param[in] parent - the manager that owns the certificate
Marri Devender Rao6ceec402019-02-01 03:15:19 -060097 */
98 Certificate(sdbusplus::bus::bus& bus, const std::string& objPath,
Nan Zhoucf06ccd2021-12-28 16:25:45 -080099 CertificateType type, const std::string& installPath,
100 const std::string& uploadPath, Watch* watch, Manager& parent);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100101
102 /** @brief Validate and Replace/Install the certificate file
103 * Install/Replace the existing certificate file with another
104 * (possibly CA signed) Certificate file.
105 * @param[in] filePath - Certificate file path.
106 */
107 void install(const std::string& filePath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600108
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500109 /** @brief Validate certificate and replace the existing certificate
110 * @param[in] filePath - Certificate file path.
111 */
112 void replace(const std::string filePath) override;
113
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500114 /** @brief Populate certificate properties by parsing certificate file
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500115 */
116 void populateProperties();
117
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200118 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100119 * @brief Obtain certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200120 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100121 * @return Certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200122 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100123 std::string getCertId() const;
124
125 /**
Nan Zhoubf3cf752021-12-28 11:02:07 -0800126 * @brief Check if provided certificate is the same as the current one.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100127 *
128 * @param[in] certPath - File path for certificate to check.
129 *
130 * @return Checking result. Return true if certificates are the same,
131 * false if not.
132 */
133 bool isSame(const std::string& certPath);
134
135 /**
136 * @brief Update certificate storage.
137 */
138 void storageUpdate();
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200139
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200140 /**
141 * @brief Delete the certificate
142 */
143 void delete_() override;
144
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500145 private:
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200146 /**
Nan Zhoucf811c42021-12-02 14:56:17 -0800147 * @brief Return error if ceritificate NotBefore date is lt 1970
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500148 *
Nan Zhoucf811c42021-12-02 14:56:17 -0800149 * Parse the certificate and return error if certificate NotBefore date
150 * is lt 1970.
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500151 *
152 * @param[in] cert Reference to certificate object uploaded
153 *
154 * @return void
155 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800156 void validateCertificateStartDate(X509& cert);
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500157
158 /**
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200159 * @brief Populate certificate properties by parsing given certificate file
160 *
161 * @param[in] certPath Path to certificate that should be parsed
162 *
163 * @return void
164 */
165 void populateProperties(const std::string& certPath);
166
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100167 /** @brief Load Certificate file into the X509 structure.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500168 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600169 * @return pointer to the X509 structure.
170 */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800171 internal::X509Ptr loadCert(const std::string& filePath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600172
Marri Devender Raocd30c492019-06-12 01:40:17 -0500173 /** @brief Check and append private key to the certificate file
174 * If private key is not present in the certificate file append the
175 * certificate file with private key existing in the system.
176 * @param[in] filePath - Certificate and key full file path.
177 * @return void.
178 */
179 void checkAndAppendPrivateKey(const std::string& filePath);
180
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600181 /** @brief Public/Private key compare function.
182 * Comparing private key against certificate public key
183 * from input .pem file.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500184 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600185 * @return Return true if Key compare is successful,
186 * false if not
187 */
188 bool compareKeys(const std::string& filePath);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500189
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100190 /**
191 * @brief Generate certificate ID based on provided certificate file.
192 *
193 * @param[in] certPath - Certificate file path.
194 *
195 * @return Certificate ID as formatted string.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600196 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100197 std::string generateCertId(const std::string& certPath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600198
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200199 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100200 * @brief Generate file name which is unique in the provided directory.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200201 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100202 * @param[in] directoryPath - Directory path.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200203 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100204 * @return File path.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200205 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100206 std::string generateUniqueFilePath(const std::string& directoryPath);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200207
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100208 /**
209 * @brief Generate authority certificate file path corresponding with
210 * OpenSSL requirements.
211 *
Nan Zhoubf3cf752021-12-28 11:02:07 -0800212 * Prepare authority certificate file path for provided certificate.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100213 * OpenSSL puts some restrictions on the certificate file name pattern.
214 * Certificate full file name needs to consists of basic file name which
215 * is certificate subject name hash and file name extension which is an
216 * integer. More over, certificates files names extensions must be
217 * consecutive integer numbers in case many certificates with the same
218 * subject name.
219 * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html
220 * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html
221 *
222 * @param[in] certSrcFilePath - Certificate source file path.
223 * @param[in] certDstDirPath - Certificate destination directory path.
224 *
225 * @return Authority certificate file path.
226 */
227 std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath,
228 const std::string& certDstDirPath);
229
230 /**
231 * @brief Generate authority certificate file path based on provided
232 * certificate source file path.
233 *
234 * @param[in] certSrcFilePath - Certificate source file path.
235 *
236 * @return Authority certificate file path.
237 */
238 std::string generateAuthCertFilePath(const std::string& certSrcFilePath);
239
240 /**
241 * @brief Generate certificate file path based on provided certificate
242 * source file path.
243 *
244 * @param[in] certSrcFilePath - Certificate source file path.
245 *
246 * @return Certificate file path.
247 */
248 std::string generateCertFilePath(const std::string& certSrcFilePath);
249
250 /** @brief Type specific function pointer map */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800251 std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600252
253 /** @brief object path */
254 std::string objectPath;
255
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100256 /** @brief Type of the certificate */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600257 CertificateType certType;
258
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100259 /** @brief Stores certificate ID */
260 std::string certId;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600261
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100262 /** @brief Stores certificate file path */
263 std::string certFilePath;
264
265 /** @brief Certificate file installation path */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800266 std::string certInstallPath;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500267
Marri Devender Raocd30c492019-06-12 01:40:17 -0500268 /** @brief Type specific function pointer map for appending private key */
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800269 std::unordered_map<CertificateType, internal::AppendPrivKeyFunc>
270 appendKeyMap;
Marri Devender Raocd30c492019-06-12 01:40:17 -0500271
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800272 /** @brief Certificate file create/update watch
273 * Note that Certificate object doesn't own the pointer
274 */
275 Watch* certWatch;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200276
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200277 /** @brief Reference to Certificate Manager */
278 Manager& manager;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600279};
280
Nan Zhoue1289ad2021-12-28 11:02:56 -0800281} // namespace phosphor::certs