blob: ce2a737f69c849ab9ecd425a22ff725df217874b [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>
8#include <phosphor-logging/elog.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
Nan Zhoue1289ad2021-12-28 11:02:56 -080013namespace phosphor::certs
Marri Devender Rao6ceec402019-02-01 03:15:19 -060014{
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020015using DeleteIface = sdbusplus::xyz::openbmc_project::Object::server::Delete;
Patrick Williams5f0f6d42021-12-03 13:40:36 -060016using CertificateIface =
17 sdbusplus::xyz::openbmc_project::Certs::server::Certificate;
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050018using ReplaceIface = sdbusplus::xyz::openbmc_project::Certs::server::Replace;
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020019using CertIfaces = sdbusplus::server::object::object<CertificateIface,
20 ReplaceIface, DeleteIface>;
Marri Devender Raoedd11312019-02-27 08:45:10 -060021
Marri Devender Rao6ceec402019-02-01 03:15:19 -060022using CertificateType = std::string;
Marri Devender Rao6ceec402019-02-01 03:15:19 -060023using CertInstallPath = std::string;
24using CertUploadPath = std::string;
25using InputType = std::string;
26using InstallFunc = std::function<void(const std::string&)>;
Marri Devender Raocd30c492019-06-12 01:40:17 -050027using AppendPrivKeyFunc = std::function<void(const std::string&)>;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050028using CertWatchPtr = std::unique_ptr<Watch>;
Marri Devender Rao6ceec402019-02-01 03:15:19 -060029using namespace phosphor::logging;
30
31// for placeholders
32using namespace std::placeholders;
33namespace fs = std::filesystem;
34
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020035class Manager; // Forward declaration for Certificate Manager.
36
Marri Devender Rao6ceec402019-02-01 03:15:19 -060037// Supported Types.
38static constexpr auto SERVER = "server";
39static constexpr auto CLIENT = "client";
40static constexpr auto AUTHORITY = "authority";
41
42// RAII support for openSSL functions.
43using X509_Ptr = std::unique_ptr<X509, decltype(&::X509_free)>;
Kowalski, Kamildb029c92019-07-08 17:09:39 +020044using X509_STORE_CTX_Ptr =
45 std::unique_ptr<X509_STORE_CTX, decltype(&::X509_STORE_CTX_free)>;
Marri Devender Rao6ceec402019-02-01 03:15:19 -060046
47/** @class Certificate
48 * @brief OpenBMC Certificate entry implementation.
49 * @details A concrete implementation for the
50 * xyz.openbmc_project.Certs.Certificate DBus API
Nan Zhoubf3cf752021-12-28 11:02:07 -080051 * xyz.openbmc_project.Certs.Install DBus API
Marri Devender Rao6ceec402019-02-01 03:15:19 -060052 */
Marri Devender Raoedd11312019-02-27 08:45:10 -060053class Certificate : public CertIfaces
Marri Devender Rao6ceec402019-02-01 03:15:19 -060054{
55 public:
56 Certificate() = delete;
57 Certificate(const Certificate&) = delete;
58 Certificate& operator=(const Certificate&) = delete;
59 Certificate(Certificate&&) = delete;
60 Certificate& operator=(Certificate&&) = delete;
61 virtual ~Certificate();
62
63 /** @brief Constructor for the Certificate Object
64 * @param[in] bus - Bus to attach to.
65 * @param[in] objPath - Object path to attach to
66 * @param[in] type - Type of the certificate
Marri Devender Rao6ceec402019-02-01 03:15:19 -060067 * @param[in] installPath - Path of the certificate to install
68 * @param[in] uploadPath - Path of the certificate file to upload
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050069 * @param[in] watchPtr - watch on self signed certificate pointer
Marri Devender Rao6ceec402019-02-01 03:15:19 -060070 */
71 Certificate(sdbusplus::bus::bus& bus, const std::string& objPath,
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010072 const CertificateType& type, const CertInstallPath& installPath,
73 const CertUploadPath& uploadPath, const CertWatchPtr& watchPtr,
74 Manager& parent);
75
76 /** @brief Validate and Replace/Install the certificate file
77 * Install/Replace the existing certificate file with another
78 * (possibly CA signed) Certificate file.
79 * @param[in] filePath - Certificate file path.
80 */
81 void install(const std::string& filePath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -060082
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050083 /** @brief Validate certificate and replace the existing certificate
84 * @param[in] filePath - Certificate file path.
85 */
86 void replace(const std::string filePath) override;
87
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050088 /** @brief Populate certificate properties by parsing certificate file
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050089 */
90 void populateProperties();
91
Kowalski, Kamildb029c92019-07-08 17:09:39 +020092 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010093 * @brief Obtain certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +020094 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010095 * @return Certificate ID.
Kowalski, Kamildb029c92019-07-08 17:09:39 +020096 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010097 std::string getCertId() const;
98
99 /**
Nan Zhoubf3cf752021-12-28 11:02:07 -0800100 * @brief Check if provided certificate is the same as the current one.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100101 *
102 * @param[in] certPath - File path for certificate to check.
103 *
104 * @return Checking result. Return true if certificates are the same,
105 * false if not.
106 */
107 bool isSame(const std::string& certPath);
108
109 /**
110 * @brief Update certificate storage.
111 */
112 void storageUpdate();
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200113
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200114 /**
115 * @brief Delete the certificate
116 */
117 void delete_() override;
118
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500119 private:
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200120 /**
Nan Zhoucf811c42021-12-02 14:56:17 -0800121 * @brief Return error if ceritificate NotBefore date is lt 1970
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500122 *
Nan Zhoucf811c42021-12-02 14:56:17 -0800123 * Parse the certificate and return error if certificate NotBefore date
124 * is lt 1970.
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500125 *
126 * @param[in] cert Reference to certificate object uploaded
127 *
128 * @return void
129 */
Nan Zhoucf811c42021-12-02 14:56:17 -0800130 void validateCertificateStartDate(const X509_Ptr& cert);
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500131
132 /**
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200133 * @brief Populate certificate properties by parsing given certificate file
134 *
135 * @param[in] certPath Path to certificate that should be parsed
136 *
137 * @return void
138 */
139 void populateProperties(const std::string& certPath);
140
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100141 /** @brief Load Certificate file into the X509 structure.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500142 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600143 * @return pointer to the X509 structure.
144 */
145 X509_Ptr loadCert(const std::string& filePath);
146
Marri Devender Raocd30c492019-06-12 01:40:17 -0500147 /** @brief Check and append private key to the certificate file
148 * If private key is not present in the certificate file append the
149 * certificate file with private key existing in the system.
150 * @param[in] filePath - Certificate and key full file path.
151 * @return void.
152 */
153 void checkAndAppendPrivateKey(const std::string& filePath);
154
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600155 /** @brief Public/Private key compare function.
156 * Comparing private key against certificate public key
157 * from input .pem file.
Marri Devender Raocd30c492019-06-12 01:40:17 -0500158 * @param[in] filePath - Certificate and key full file path.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600159 * @return Return true if Key compare is successful,
160 * false if not
161 */
162 bool compareKeys(const std::string& filePath);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500163
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100164 /**
165 * @brief Generate certificate ID based on provided certificate file.
166 *
167 * @param[in] certPath - Certificate file path.
168 *
169 * @return Certificate ID as formatted string.
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600170 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100171 std::string generateCertId(const std::string& certPath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600172
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200173 /**
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100174 * @brief Generate file name which is unique in the provided directory.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200175 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100176 * @param[in] directoryPath - Directory path.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200177 *
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100178 * @return File path.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200179 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100180 std::string generateUniqueFilePath(const std::string& directoryPath);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200181
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100182 /**
183 * @brief Generate authority certificate file path corresponding with
184 * OpenSSL requirements.
185 *
Nan Zhoubf3cf752021-12-28 11:02:07 -0800186 * Prepare authority certificate file path for provided certificate.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100187 * OpenSSL puts some restrictions on the certificate file name pattern.
188 * Certificate full file name needs to consists of basic file name which
189 * is certificate subject name hash and file name extension which is an
190 * integer. More over, certificates files names extensions must be
191 * consecutive integer numbers in case many certificates with the same
192 * subject name.
193 * https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html
194 * https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html
195 *
196 * @param[in] certSrcFilePath - Certificate source file path.
197 * @param[in] certDstDirPath - Certificate destination directory path.
198 *
199 * @return Authority certificate file path.
200 */
201 std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath,
202 const std::string& certDstDirPath);
203
204 /**
205 * @brief Generate authority certificate file path based on provided
206 * certificate source file path.
207 *
208 * @param[in] certSrcFilePath - Certificate source file path.
209 *
210 * @return Authority certificate file path.
211 */
212 std::string generateAuthCertFilePath(const std::string& certSrcFilePath);
213
214 /**
215 * @brief Generate certificate file path based on provided certificate
216 * source file path.
217 *
218 * @param[in] certSrcFilePath - Certificate source file path.
219 *
220 * @return Certificate file path.
221 */
222 std::string generateCertFilePath(const std::string& certSrcFilePath);
223
224 /** @brief Type specific function pointer map */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600225 std::unordered_map<InputType, InstallFunc> typeFuncMap;
226
227 /** @brief sdbusplus handler */
228 sdbusplus::bus::bus& bus;
229
230 /** @brief object path */
231 std::string objectPath;
232
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100233 /** @brief Type of the certificate */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600234 CertificateType certType;
235
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100236 /** @brief Stores certificate ID */
237 std::string certId;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600238
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100239 /** @brief Stores certificate file path */
240 std::string certFilePath;
241
242 /** @brief Certificate file installation path */
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600243 CertInstallPath certInstallPath;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500244
Marri Devender Raocd30c492019-06-12 01:40:17 -0500245 /** @brief Type specific function pointer map for appending private key */
246 std::unordered_map<InputType, AppendPrivKeyFunc> appendKeyMap;
247
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500248 /** @brief Certificate file create/update watch */
249 const CertWatchPtr& certWatchPtr;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200250
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200251 /** @brief Reference to Certificate Manager */
252 Manager& manager;
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600253};
254
Nan Zhoue1289ad2021-12-28 11:02:56 -0800255} // namespace phosphor::certs