From 66ff3d26e501d906dd1748ac79c94c16f513f7d9 Mon Sep 17 00:00:00 2001 From: neru Date: Tue, 12 May 2026 16:41:55 -0300 Subject: [PATCH] feat: add CertificateManager --- src/proxy/tinymitm/ssl.cpp | 127 +++++++++++++++++++++++++++++++++++++ src/proxy/tinymitm/ssl.h | 36 +++++++++++ 2 files changed, 163 insertions(+) create mode 100644 src/proxy/tinymitm/ssl.cpp create mode 100644 src/proxy/tinymitm/ssl.h diff --git a/src/proxy/tinymitm/ssl.cpp b/src/proxy/tinymitm/ssl.cpp new file mode 100644 index 0000000..4d05953 --- /dev/null +++ b/src/proxy/tinymitm/ssl.cpp @@ -0,0 +1,127 @@ +#include "ssl.h" + +#define WOLFSSL_ALT_NAMES + +#include + +#include +#include +#include +#include +#include + +#include + +/* + CertificateManager implementation +*/ +CertificateManager::CertificateManager() : _rng(new WC_RNG()), _caKey(nullptr), _sessionKey(nullptr) {} + +CertificateManager::~CertificateManager() +{ + for (auto& pair : _hostContexts) + wolfSSL_CTX_free(pair.second); +} + +bool CertificateManager::init() +{ + if (wc_InitRng(_rng.get()) != 0) return false; + + // session init + _sessionKey.reset(new RsaKey()); + wc_InitRsaKey(_sessionKey.get(), nullptr); + if (wc_MakeRsaKey(_sessionKey.get(), 2048, 65537, _rng.get()) != 0) return false; + + // der cache + _sessionKeyDer.resize(4096); + int derLen = wc_RsaKeyToDer(_sessionKey.get(), _sessionKeyDer.data(), (word32)_sessionKeyDer.size()); + if (derLen < 0) return false; + _sessionKeyDer.resize(derLen); + + if (loadCA()) return true; + return generateCA(); +} + +WOLFSSL_CTX* CertificateManager::createHostContext(const std::string& host) +{ + std::lock_guard lock(_mutex); + if (_hostContexts.count(host)) return _hostContexts[host]; + if (!_caKey) return nullptr; + + auto cert = std::make_unique(); + memset(cert.get(), 0, sizeof(Cert)); + wc_InitCert(cert.get()); + + strncpy(cert->subject.commonName, host.c_str(), sizeof(cert->subject.commonName)); + cert->sigType = CTC_SHA256wRSA; + cert->daysValid = 365; + + uint32_t serial = std::hash{}(host) & 0x7FFFFFFF; + memcpy(cert->serial, &serial, sizeof(serial)); + cert->serialSz = sizeof(serial); + + wc_SetAltNames(cert.get(), host.c_str()); + + std::vector hostCertDer(4096); + int certLen = + wc_MakeCert(cert.get(), hostCertDer.data(), (word32)hostCertDer.size(), _sessionKey.get(), nullptr, _rng.get()); + + certLen = wc_SignCert(cert->bodySz, cert->sigType, hostCertDer.data(), (word32)hostCertDer.size(), _caKey.get(), + nullptr, _rng.get()); + + hostCertDer.resize(certLen); + + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + if (!ctx) return nullptr; + + if (wolfSSL_CTX_use_certificate_buffer(ctx, hostCertDer.data(), (long)hostCertDer.size(), WOLFSSL_FILETYPE_ASN1) != + WOLFSSL_SUCCESS || + wolfSSL_CTX_use_PrivateKey_buffer(ctx, _sessionKeyDer.data(), (long)_sessionKeyDer.size(), + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) + { + wolfSSL_CTX_free(ctx); + return nullptr; + } + + _hostContexts[host] = ctx; + return ctx; +} + +bool CertificateManager::generateCA() +{ + _caKey.reset(new RsaKey()); + wc_InitRsaKey(_caKey.get(), nullptr); + + if (wc_MakeRsaKey(_caKey.get(), 2048, 65537, _rng.get()) != 0) + { + return false; + } + + auto cert = std::make_unique(); + memset(cert.get(), 0, sizeof(Cert)); + wc_InitCert(cert.get()); + + strncpy(cert->subject.commonName, "TinyMITM-CA", sizeof(cert->subject.commonName)); + cert->isCA = 1; + cert->sigType = CTC_SHA256wRSA; + cert->daysValid = 3650; + + _caCertDer.resize(4096); + + int certLen = + wc_MakeCert(cert.get(), _caCertDer.data(), (word32)_caCertDer.size(), _caKey.get(), nullptr, _rng.get()); + if (certLen < 0) return false; + + certLen = wc_SignCert(cert->bodySz, cert->sigType, _caCertDer.data(), (word32)_caCertDer.size(), _caKey.get(), + nullptr, _rng.get()); + + if (certLen < 0) return false; + _caCertDer.resize(certLen); + + return true; +} + +bool CertificateManager::loadCA() +{ + return false; +} diff --git a/src/proxy/tinymitm/ssl.h b/src/proxy/tinymitm/ssl.h new file mode 100644 index 0000000..ff3969e --- /dev/null +++ b/src/proxy/tinymitm/ssl.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "raai-helper.h" + +class CertificateManager +{ + public: + CertificateManager(); + ~CertificateManager(); + + bool init(); + + WOLFSSL_CTX* createHostContext(const std::string& host); + + private: + bool generateCA(); + bool loadCA(); + + std::unique_ptr _caKey; + std::unique_ptr _sessionKey; + + std::vector _caCertDer; + std::vector _sessionKeyDer; + + std::unique_ptr _rng; + + std::mutex _mutex; + + std::unordered_map _hostContexts; +};