-
Notifications
You must be signed in to change notification settings - Fork 12
/
certs_manager.hpp
344 lines (303 loc) · 14.1 KB
/
certs_manager.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
#pragma once
#include "certificate.hpp"
#include "csr.hpp"
#include "watch.hpp"
#include <openssl/evp.h>
#include <openssl/ossl_typ.h>
#include <openssl/x509.h>
#include <cstdint>
#include <filesystem>
#include <memory>
#include <sdbusplus/server/object.hpp>
#include <sdeventplus/source/child.hpp>
#include <sdeventplus/source/event.hpp>
#include <string>
#include <vector>
#include <xyz/openbmc_project/Certs/CSR/Create/server.hpp>
#include <xyz/openbmc_project/Certs/Install/server.hpp>
#include <xyz/openbmc_project/Certs/InstallAll/server.hpp>
#include <xyz/openbmc_project/Certs/ReplaceAll/server.hpp>
#include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
namespace phosphor::certs
{
namespace internal
{
using ManagerInterface = sdbusplus::server::object_t<
sdbusplus::xyz::openbmc_project::Certs::server::Install,
sdbusplus::xyz::openbmc_project::Certs::CSR::server::Create,
sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll,
sdbusplus::xyz::openbmc_project::Certs::server::InstallAll,
sdbusplus::xyz::openbmc_project::Certs::server::ReplaceAll>;
}
class Manager : public internal::ManagerInterface
{
public:
/* Define all of the basic class operations:
* Not allowed:
* - Default constructor is not possible due to member
* reference
* - Move operations due to 'this' being registered as the
* 'context' with sdbus.
* Allowed:
* - copy
* - Destructor.
*/
Manager() = delete;
Manager(const Manager&) = delete;
Manager& operator=(const Manager&) = delete;
Manager(Manager&&) = delete;
Manager& operator=(Manager&&) = delete;
virtual ~Manager() = default;
/** @brief Constructor to put object onto bus at a dbus path.
* @param[in] bus - Bus to attach to.
* @param[in] event - sd event handler.
* @param[in] path - Path to attach at.
* @param[in] type - Type of the certificate.
* @param[in] unit - Unit consumed by this certificate.
* @param[in] installPath - Certificate installation path.
*/
Manager(sdbusplus::bus_t& bus, sdeventplus::Event& event, const char* path,
CertificateType type, const std::string& unit,
const std::string& installPath);
/** @brief Implementation for Install
* Replace the existing certificate key file with another
* (possibly CA signed) Certificate key file.
*
* @param[in] filePath - Certificate key file path.
*
* @return Certificate object path.
*/
std::string install(const std::string filePath) override;
/** @brief Implementation for InstallAll
* Install the authority list and restart the associated services.
*
* @param[in] path - Path of the file that contains a list of root
* certificates.
*
* @return D-Bus object path to created objects.
*/
std::vector<sdbusplus::message::object_path>
installAll(std::string path) override;
/** @brief Implementation for ReplaceAll
* Replace the current authority lists and restart the associated services.
*
* @param[in] path - Path of file that contains multiple root certificates.
*
* @return D-Bus object path to created objects.
*/
std::vector<sdbusplus::message::object_path>
replaceAll(std::string filePath) override;
/** @brief Implementation for DeleteAll
* Delete all objects in the collection.
*/
void deleteAll() override;
/** @brief Delete the certificate.
*/
void deleteCertificate(const Certificate* const certificate);
/** @brief Replace the certificate.
*/
void replaceCertificate(Certificate* const certificate,
const std::string& filePath);
/** @brief Generate Private key and CSR file
* Generates the Private key file and CSR file based on the input
* parameters. Validation of the parameters is callers responsibility.
* At present supports only RSA algorithm type
*
* @param[in] alternativeNames - Additional hostnames of the component that
* is being secured.
* @param[in] challengePassword - The challenge password to be applied to
* the certificate for revocation requests.
* @param[in] city - The city or locality of the organization making the
* request. For Example Austin
* @param[in] commonName - The fully qualified domain name of the component
* that is being secured.
* @param[in] contactPerson - The name of the user making the request.
* @param[in] country - The country of the organization making the request.
* @param[in] email - The email address of the contact within the
* organization making the request.
* @param[in] givenName - The given name of the user making the request.
* @param[in] initials - The initials of the user making the request.
* @param[in] keyBitLength - The length of the key in bits, if needed based
* on the value of the KeyPairAlgorithm parameter.
* @param[in] keyCurveId - The curve ID to be used with the key, if needed
* based on the value of the KeyPairAlgorithm parameter.
* @param[in] keyPairAlgorithm - The type of key pair for use with signing
* algorithms. Valid built-in algorithm names for private key
* generation are: RSA, DSA, DH and EC.
* @param[in] keyUsage - Key usage extensions define the purpose of the
* public key contained in a certificate. Valid Key usage extensions
* and its usage description.
* - ClientAuthentication: The public key is used for TLS WWW client
* authentication.
* - CodeSigning: The public key is used for the signing of executable
* code
* - CRLSigning: The public key is used for verifying signatures on
* certificate revocation lists (CLRs).
* - DataEncipherment: The public key is used for directly enciphering
* raw user data without the use of an intermediate symmetric
* cipher.
* - DecipherOnly: The public key could be used for deciphering data
* while performing key agreement.
* - DigitalSignature: The public key is used for verifying digital
* signatures, other than signatures on certificatesand CRLs.
* - EmailProtection: The public key is used for email protection.
* - EncipherOnly: Thepublic key could be used for enciphering data
* while performing key agreement.
* - KeyCertSign: The public key is used for verifying signatures on
* public key certificates.
* - KeyEncipherment: The public key is used for enciphering private or
* secret keys.
* - NonRepudiation: The public key is used to verify digital
* signatures, other than signatures on certificates and CRLs, and
* used to provide a non-repudiation service that protects against
* the signing entity falsely denying some action.
* - OCSPSigning: The public key is used for signing OCSP responses.
* - ServerAuthentication: The public key is used for TLS WWW server
* authentication.
* - Timestamping: The public key is used for binding the hash of an
* object to a time.
* @param[in] organization - The legal name of the organization. This
* should not be abbreviated and should include suffixes such as Inc,
* Corp, or LLC.For example, IBM Corp.
* @param[in] organizationalUnit - The name of the unit or division of the
* organization making the request.
* @param[in] state - The state or province where the organization is
* located. This should not be abbreviated. For example, Texas.
* @param[in] surname - The surname of the user making the request.
* @param[in] unstructuredName - The unstructured name of the subject.
*
* @return path[std::string] - The object path of the D-Bus object
* representing CSR string. Note: For new CSR request will overwrite
* the existing CSR in the system.
*/
std::string generateCSR(
std::vector<std::string> alternativeNames,
std::string challengePassword, std::string city, std::string commonName,
std::string contactPerson, std::string country, std::string email,
std::string givenName, std::string initials, int64_t keyBitLength,
std::string keyCurveId, std::string keyPairAlgorithm,
std::vector<std::string> keyUsage, std::string organization,
std::string organizationalUnit, std::string state, std::string surname,
std::string unstructuredName) override;
/** @brief Get reference to certificates' collection
*
* @return Reference to certificates' collection
*/
std::vector<std::unique_ptr<Certificate>>& getCertificates();
/** @brief Systemd unit reload or reset helper function
* Reload if the unit supports it and use a restart otherwise.
* @param[in] unit - service need to reload.
*/
virtual void reloadOrReset(const std::string& unit);
private:
void generateCSRHelper(std::vector<std::string> alternativeNames,
std::string challengePassword, std::string city,
std::string commonName, std::string contactPerson,
std::string country, std::string email,
std::string givenName, std::string initials,
int64_t keyBitLength, std::string keyCurveId,
std::string keyPairAlgorithm,
std::vector<std::string> keyUsage,
std::string organization,
std::string organizationalUnit, std::string state,
std::string surname, std::string unstructuredName);
/** @brief Generate RSA Key pair and get private key from key pair
* @param[in] keyBitLength - KeyBit length.
* @return Pointer to RSA private key
*/
std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
generateRSAKeyPair(const int64_t keyBitLength);
/** @brief Generate EC Key pair and get private key from key pair
* @param[in] p_KeyCurveId - Curve ID
* @return Pointer to EC private key
*/
std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
generateECKeyPair(const std::string& pKeyCurveId);
/** @brief Write private key data to file
*
* @param[in] pKey - pointer to private key
* @param[in] privKeyFileName - private key filename
*/
void writePrivateKey(
const std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>& pKey,
const std::string& privKeyFileName);
/** @brief Add the specified CSR field with the data
* @param[in] x509Name - Structure used in setting certificate properties
* @param[in] field - field name
* @param[in] bytes - field value in bytes
*/
void addEntry(X509_NAME* x509Name, const char* field,
const std::string& bytes);
/** @brief Check if usage is extended key usage
* @param[in] usage - key usage value
* @return true if part of extended key usage
*/
bool isExtendedKeyUsage(const std::string& usage);
/** @brief Create CSR D-Bus object by reading the data in the CSR file
* @param[in] statis - SUCCESS/FAILURE In CSR generation.
*/
void createCSRObject(const Status& status);
/** @brief Write generated CSR data to file
*
* @param[in] filePath - CSR file path.
* @param[in] x509Req - OpenSSL Request Pointer.
*/
void writeCSR(
const std::string& filePath,
const std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>& x509Req);
/** @brief Load certificate
* Load certificate and create certificate object
*/
void createCertificates();
/** @brief Create RSA private key file
* Create RSA private key file by generating rsa key if not created
*/
void createRSAPrivateKeyFile();
/** @brief Getting RSA private key
* Getting RSA private key from generated file
* @param[in] keyBitLength - Key bit length
* @return Pointer to RSA key
*/
std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>
getRSAKeyPair(const int64_t keyBitLength);
/** @brief Update certificate storage (remove outdated files, recreate
* symbolic links, etc.).
*/
void storageUpdate();
/** @brief Check if provided certificate is unique across all certificates
* on the internal list.
* @param[in] certFilePath - Path to the file with certificate for
* uniqueness check.
* @param[in] certToDrop - Pointer to the certificate from the internal
* list which should be not taken into account while uniqueness check.
* @return Checking result. True if certificate is unique, false if
* not.
*/
bool isCertificateUnique(const std::string& certFilePath,
const Certificate* const certToDrop = nullptr);
/** @brief sdbusplus handler */
sdbusplus::bus_t& bus;
// sdevent Event handle
sdeventplus::Event& event;
/** @brief object path */
std::string objectPath;
/** @brief Type of the certificate **/
CertificateType certType;
/** @brief Unit name associated to the service **/
std::string unitToRestart;
/** @brief Certificate file installation path **/
std::string certInstallPath;
/** @brief Collection of pointers to certificate */
std::vector<std::unique_ptr<Certificate>> installedCerts;
/** @brief pointer to CSR */
std::unique_ptr<CSR> csrPtr = nullptr;
/** @brief SDEventPlus child pointer added to event loop */
std::unique_ptr<sdeventplus::source::Child> childPtr = nullptr;
/** @brief Watch on self signed certificates */
std::unique_ptr<Watch> certWatchPtr = nullptr;
/** @brief Parent path i.e certificate directory path */
std::filesystem::path certParentInstallPath;
/** @brief Certificate ID pool */
uint64_t certIdCounter = 1;
};
} // namespace phosphor::certs