blob: e2864ebb9fada0e96e65510e24cefcd3ee7ca87c [file] [log] [blame]
#pragma once
#include "watch.hpp"
#include <openssl/ossl_typ.h>
#include <openssl/x509.h>
#include <sdbusplus/server/object.hpp>
#include <xyz/openbmc_project/Certs/Certificate/server.hpp>
#include <xyz/openbmc_project/Certs/Replace/server.hpp>
#include <xyz/openbmc_project/Object/Delete/server.hpp>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
namespace phosphor::certs
{
// Certificate types
enum class CertificateType
{
authority,
server,
client,
unsupported,
};
inline constexpr const char* certificateTypeToString(CertificateType type)
{
switch (type)
{
case CertificateType::authority:
return "authority";
case CertificateType::server:
return "server";
case CertificateType::client:
return "client";
default:
return "unsupported";
}
}
inline constexpr CertificateType stringToCertificateType(std::string_view type)
{
if (type == "authority")
{
return CertificateType::authority;
}
if (type == "server")
{
return CertificateType::server;
}
if (type == "client")
{
return CertificateType::client;
}
return CertificateType::unsupported;
}
namespace internal
{
using CertificateInterface = sdbusplus::server::object_t<
sdbusplus::xyz::openbmc_project::Certs::server::Certificate,
sdbusplus::xyz::openbmc_project::Certs::server::Replace,
sdbusplus::xyz::openbmc_project::Object::server::Delete>;
using InstallFunc = std::function<void(const std::string&)>;
using AppendPrivKeyFunc = std::function<void(const std::string&)>;
using X509Ptr = std::unique_ptr<X509, decltype(&::X509_free)>;
} // namespace internal
class Manager; // Forward declaration for Certificate Manager.
/** @class Certificate
* @brief OpenBMC Certificate entry implementation.
* @details A concrete implementation for the
* xyz.openbmc_project.Certs.Certificate DBus API
* xyz.openbmc_project.Certs.Install DBus API
*/
class Certificate : public internal::CertificateInterface
{
public:
Certificate() = delete;
Certificate(const Certificate&) = delete;
Certificate& operator=(const Certificate&) = delete;
Certificate(Certificate&&) = delete;
Certificate& operator=(Certificate&&) = delete;
virtual ~Certificate();
/** @brief Constructor for the Certificate Object
* @param[in] bus - Bus to attach to.
* @param[in] objPath - Object path to attach to
* @param[in] type - Type of the certificate
* @param[in] installPath - Path of the certificate to install
* @param[in] uploadPath - Path of the certificate file to upload
* @param[in] watchPtr - watch on self signed certificate
* @param[in] parent - the manager that owns the certificate
* @param[in] restore - the certificate is created in the restore path
*/
Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
CertificateType type, const std::string& installPath,
const std::string& uploadPath, Watch* watch, Manager& parent,
bool restore);
/** @brief Constructor for the Certificate Object; a variant for authorities
* list install
* @param[in] bus - Bus to attach to.
* @param[in] objPath - Object path to attach to
* @param[in] type - Type of the certificate
* @param[in] installPath - Path of the certificate to install
* @param[in] x509Store - an initialized X509 store used for certificate
* validation; Certificate object doesn't own it
* @param[in] pem - Content of the certificate file to upload; it shall be
* a single PEM encoded x509 certificate
* @param[in] watchPtr - watch on self signed certificate
* @param[in] parent - Pointer to the manager which owns the constructed
* Certificate object
* @param[in] restore - the certificate is created in the restore path
*/
Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
const CertificateType& type, const std::string& installPath,
X509_STORE& x509Store, const std::string& pem, Watch* watchPtr,
Manager& parent, bool restore);
/** @brief Validate and Replace/Install the certificate file
* Install/Replace the existing certificate file with another
* (possibly CA signed) Certificate file.
* @param[in] filePath - Certificate file path.
* @param[in] restore - the certificate is created in the restore path
*/
void install(const std::string& filePath, bool restore);
/** @brief Validate and Replace/Install the certificate file
* Install/Replace the existing certificate file with another
* (possibly CA signed) Certificate file.
* @param[in] x509Store - an initialized X509 store used for certificate
* validation; Certificate object doesn't own it
* @param[in] pem - a string buffer which stores a PEM encoded certificate.
* @param[in] restore - the certificate is created in the restore path
*/
void install(X509_STORE& x509Store, const std::string& pem, bool restore);
/** @brief Validate certificate and replace the existing certificate
* @param[in] filePath - Certificate file path.
*/
void replace(const std::string filePath) override;
/** @brief Populate certificate properties by parsing certificate file
*/
void populateProperties();
/**
* @brief Obtain certificate ID.
*
* @return Certificate ID.
*/
std::string getCertId() const;
/**
* @brief Check if provided certificate is the same as the current one.
*
* @param[in] certPath - File path for certificate to check.
*
* @return Checking result. Return true if certificates are the same,
* false if not.
*/
bool isSame(const std::string& certPath);
/**
* @brief Update certificate storage.
*/
void storageUpdate();
/**
* @brief Delete the certificate
*/
void delete_() override;
/**
* @brief Generate file name which is unique in the provided directory.
*
* @param[in] directoryPath - Directory path.
*
* @return File path.
*/
static std::string generateUniqueFilePath(const std::string& directoryPath);
/**
* @brief Copies the certificate from sourceFilePath to installFilePath
*
* @param[in] sourceFilePath - Path to the source file.
* @param[in] certFilePath - Path to the destination file.
*
* @return void
*/
static void copyCertificate(const std::string& certSrcFilePath,
const std::string& certFilePath);
/**
* @brief Returns the associated dbus object path.
*/
std::string getObjectPath();
/**
* @brief Returns the associated cert file path.
*/
std::string getCertFilePath();
/** @brief: Set the data member |certFilePath| to |path|
*/
void setCertFilePath(const std::string& path);
/** @brief: Set the data member |certInstallPath| to |path|
*/
void setCertInstallPath(const std::string& path);
private:
/**
* @brief Populate certificate properties by parsing given certificate
* object
*
* @param[in] cert The given certificate object
*
* @return void
*/
void populateProperties(X509& cert);
/** @brief Check and append private key to the certificate file
* If private key is not present in the certificate file append the
* certificate file with private key existing in the system.
* @param[in] filePath - Certificate and key full file path.
* @return void.
*/
void checkAndAppendPrivateKey(const std::string& filePath);
/** @brief Public/Private key compare function.
* Comparing private key against certificate public key
* from input .pem file.
* @param[in] filePath - Certificate and key full file path.
* @return Return true if Key compare is successful,
* false if not
*/
bool compareKeys(const std::string& filePath);
/**
* @brief Generate authority certificate file path corresponding with
* OpenSSL requirements.
*
* Prepare authority certificate file path for provided certificate.
* OpenSSL puts some restrictions on the certificate file name pattern.
* Certificate full file name needs to consists of basic file name which
* is certificate subject name hash and file name extension which is an
* integer. More over, certificates files names extensions must be
* consecutive integer numbers in case many certificates with the same
* subject name.
* https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/reference/ssl__context/add_verify_path.html
* https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_load_verify_locations.html
*
* @param[in] certSrcFilePath - Certificate source file path.
* @param[in] certDstDirPath - Certificate destination directory path.
*
* @return Authority certificate file path.
*/
std::string generateAuthCertFileX509Path(const std::string& certSrcFilePath,
const std::string& certDstDirPath);
/**
* @brief Generate authority certificate file path based on provided
* certificate source file path.
*
* @param[in] certSrcFilePath - Certificate source file path.
*
* @return Authority certificate file path.
*/
std::string generateAuthCertFilePath(const std::string& certSrcFilePath);
/**
* @brief Generate certificate file path based on provided certificate
* source file path.
*
* @param[in] certSrcFilePath - Certificate source file path.
*
* @return Certificate file path.
*/
std::string generateCertFilePath(const std::string& certSrcFilePath);
/** @brief Type specific function pointer map */
std::unordered_map<CertificateType, internal::InstallFunc> typeFuncMap;
/** @brief object path */
std::string objectPath;
/** @brief Type of the certificate */
CertificateType certType;
/** @brief Stores certificate ID */
std::string certId;
/** @brief Stores certificate file path */
std::string certFilePath;
/** @brief Certificate file installation path */
std::string certInstallPath;
/** @brief Type specific function pointer map for appending private key */
std::unordered_map<CertificateType, internal::AppendPrivKeyFunc>
appendKeyMap;
/** @brief Certificate file create/update watch
* Note that Certificate object doesn't own the pointer
*/
Watch* certWatch;
/** @brief Reference to Certificate Manager */
Manager& manager;
};
} // namespace phosphor::certs