generated from EVerest/everest-template
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated for certificate directory support
- added certificate bundle wrapper - added general openssl types - added some helpers - updated certificate delete for bundle support Signed-off-by: Ioan Bogdan <[email protected]>
- Loading branch information
1 parent
f621aab
commit b88dd99
Showing
9 changed files
with
698 additions
and
327 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
|
||
#ifndef EVSE_UTILITIES_HPP | ||
#define EVSE_UTILITIES_HPP | ||
|
||
#include <filesystem> | ||
#include <fstream> | ||
#include <iostream> | ||
|
||
namespace evse_security { | ||
|
||
class EvseUtils { | ||
public: | ||
static bool delete_file(const std::filesystem::path& file_path) { | ||
if (std::filesystem::is_regular_file(file_path)) | ||
return std::filesystem::remove(file_path); | ||
|
||
return false; | ||
} | ||
|
||
static bool read_from_file(const std::filesystem::path& file_path, std::string& out_data) { | ||
if (std::filesystem::is_regular_file(file_path)) { | ||
std::ifstream file(file_path, std::ios::binary); | ||
|
||
if (file.is_open()) { | ||
out_data = std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
static bool write_to_file(const std::filesystem::path& file_path, const std::string& data, | ||
std::ios::openmode mode) { | ||
try { | ||
std::ofstream fs(file_path, mode | std::ios::binary); | ||
if (!fs.is_open()) { | ||
// EVLOG_error << "Error opening file: " << file_path; | ||
return false; | ||
} | ||
fs.write(data.c_str(), data.size()); | ||
|
||
if (!fs) { | ||
// EVLOG_error << "Error writing to file: " << file_path; | ||
return false; | ||
} | ||
return true; | ||
} catch (const std::exception& e) { | ||
// EVLOG_error << "Unknown error occured while writing to file: " << file_path; | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
static std::string get_random_file_name(const std::string& extension) { | ||
char path[] = "XXXXXX"; | ||
mktemp(path); | ||
|
||
return std::string(path) + extension; | ||
} | ||
}; | ||
|
||
} // namespace evse_security | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#ifndef EVSE_SEC_TYPES_HPP | ||
#define EVSE_SEC_TYPES_HPP | ||
|
||
#include <memory> | ||
#include <openssl/x509v3.h> | ||
|
||
template <> class std::default_delete<X509> { | ||
public: | ||
void operator()(X509* ptr) const { | ||
::X509_free(ptr); | ||
} | ||
}; | ||
|
||
template <> class std::default_delete<X509_STORE> { | ||
public: | ||
void operator()(X509_STORE* ptr) const { | ||
::X509_STORE_free(ptr); | ||
} | ||
}; | ||
|
||
template <> class std::default_delete<X509_STORE_CTX> { | ||
public: | ||
void operator()(X509_STORE_CTX* ptr) const { | ||
::X509_STORE_CTX_free(ptr); | ||
} | ||
}; | ||
|
||
template <> class std::default_delete<X509_REQ> { | ||
public: | ||
void operator()(X509_REQ* ptr) const { | ||
::X509_REQ_free(ptr); | ||
} | ||
}; | ||
|
||
template <> class std::default_delete<EVP_PKEY> { | ||
public: | ||
void operator()(EVP_PKEY* ptr) const { | ||
::EVP_PKEY_free(ptr); | ||
} | ||
}; | ||
|
||
template <> class std::default_delete<BIO> { | ||
public: | ||
void operator()(BIO* ptr) const { | ||
::BIO_free(ptr); | ||
} | ||
}; | ||
|
||
namespace evse_security { | ||
|
||
using X509_ptr = std::unique_ptr<X509>; | ||
using X509_STORE_ptr = std::unique_ptr<X509_STORE>; | ||
using X509_STORE_CTX_ptr = std::unique_ptr<X509_STORE_CTX>; | ||
using X509_REQ_ptr = std::unique_ptr<X509_REQ>; | ||
using EVP_PKEY_ptr = std::unique_ptr<EVP_PKEY>; | ||
using BIO_ptr = std::unique_ptr<BIO>; | ||
|
||
} // namespace evse_security | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
|
||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright Pionix GmbH and Contributors to EVerest | ||
#ifndef X509_BUNDLE_HPP | ||
#define X509_BUNDLE_HPP | ||
|
||
#include <x509_wrapper.hpp> | ||
|
||
namespace evse_security { | ||
|
||
/// @brief X509 certificate bundle, used for holding multiple X509Wrappers. Supports | ||
/// operations like add/delete importing/exporting certificates | ||
class X509CertificateBundle { | ||
public: | ||
X509CertificateBundle(const std::filesystem::path& path, const EncodingFormat encoding); | ||
X509CertificateBundle(const std::string& certificate, const EncodingFormat encoding); | ||
|
||
public: | ||
/// @brief Gets if this certificate bundle comes from a single certificate bundle file | ||
/// @return | ||
bool is_using_bundle_file() { | ||
return (source == X509CertificateSource::FILE); | ||
} | ||
|
||
/// @brief Gets if this certificate bundle comes from an entire directory | ||
/// @return | ||
bool is_using_directory() { | ||
return (source == X509CertificateSource::DIRECTORY); | ||
} | ||
|
||
public: | ||
/// @brief Splits the certificate (chain) into single certificates | ||
/// @return vector containing single certificates | ||
std::vector<X509Wrapper> split(); | ||
|
||
/// @brief If we already have the certificate | ||
bool contains_certificate(const X509Wrapper& certificate); | ||
/// @brief If we already have the certificate | ||
bool contains_certificate(const CertificateHashData& certificate_hash); | ||
|
||
/// @brief Updates a single certificate in the chain. Only in memory, use @ref export_certificates to filesystem | ||
/// export | ||
/// @param certificate certificate to update | ||
/// @return true if the certificate was found and updated, false otherwise. If true is returned the provided | ||
/// certificate is invalidated | ||
bool update_certificate(X509Wrapper& certificate); | ||
|
||
/// @brief Deletes a single certificate in the chain. Only in memory, use @ref export_certificates to filesystem | ||
/// export | ||
/// @return true if the certificate was found and deleted, false otherwise | ||
bool delete_certificate(const X509Wrapper& certificate); | ||
bool delete_certificate(const CertificateHashData& data); | ||
|
||
/// @brief Deletes all certificates. Only in memory, use @ref export_certificates to filesystem export | ||
void delete_all_certificates(); | ||
|
||
/// @brief Returns a full exportable representation of a certificate bundle file in PEM format | ||
std::string to_export_string() const; | ||
|
||
/// @brief Exports the full certificate chain either as individual files if it is using a directory | ||
/// or as a bundle if it uses a bundle file, at the initially provided path. Also deletes/adds the updated | ||
/// certificates | ||
/// @return true on success, false otherwise | ||
bool export_certificates(); | ||
|
||
/// @brief Syncs the file structure with the certificate store adding certificates that are not found on the | ||
/// storeage and deleting the certificates that are not contained in this bundle | ||
bool sync_to_certificate_store(); | ||
|
||
public: | ||
static std::vector<X509_ptr> load_certificates(const std::string& data, const EncodingFormat encoding); | ||
|
||
static bool is_certificate_file(const std::filesystem::path& file) { | ||
return std::filesystem::is_regular_file(file) && | ||
((file.extension() == PEM_EXTENSION) || (file.extension() == DER_EXTENSION)); | ||
} | ||
|
||
private: | ||
/// @brief Adds to our certificate list the certificates found in the file | ||
/// @return number of added certificates | ||
void add_certifcates(const std::string& data, const EncodingFormat encoding, | ||
const std::optional<std::filesystem::path>& path); | ||
|
||
private: | ||
// Certificates in this chain, can only be loaded either from a bundle or a dir folder, never combined | ||
std::vector<X509Wrapper> certificates; | ||
// Relevant bundle or directory for this certificate chain | ||
std::filesystem::path path; | ||
// Source from where we created the certificates. If 'string' the 'export' functions will not work | ||
X509CertificateSource source; | ||
}; | ||
|
||
} // namespace evse_security | ||
|
||
#endif // X509_BUNDLE_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.