From 691489215d414f3ab9701a7afbf1364e59b15928 Mon Sep 17 00:00:00 2001 From: neru Date: Tue, 12 May 2026 18:21:32 -0300 Subject: [PATCH] feat: add CA install fn, load and gen fns, and decode helper --- src/proxy/tinymitm/ssl.cpp | 131 +++++++++++++++++++++++++++++++++---- src/proxy/tinymitm/ssl.h | 12 +++- 2 files changed, 127 insertions(+), 16 deletions(-) diff --git a/src/proxy/tinymitm/ssl.cpp b/src/proxy/tinymitm/ssl.cpp index a1e25a5..c332eec 100644 --- a/src/proxy/tinymitm/ssl.cpp +++ b/src/proxy/tinymitm/ssl.cpp @@ -12,6 +12,12 @@ #include +#ifdef _WIN32 + #include + #include + #pragma comment(lib, "crypt32.lib") +#endif + /* CertificateManager implementation */ @@ -38,8 +44,7 @@ bool CertificateManager::init() if (derLen < 0) return false; _sessionKeyDer.resize(derLen); - if (loadCA()) return true; - return generateCA(); + return true; } WOLFSSL_CTX* CertificateManager::createHostContext(const std::string& host) @@ -87,41 +92,141 @@ WOLFSSL_CTX* CertificateManager::createHostContext(const std::string& host) return ctx; } -bool CertificateManager::generateCA() +#ifdef _WIN32 +bool CertificateManager::installCertificate() +{ + if (_caCertDer.empty()) return false; + + PCCERT_CONTEXT certCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _caCertDer.data(), + (DWORD)_caCertDer.size()); + + if (!certCtx) return false; + HCERTSTORE rootStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"Root"); + bool success = false; + if (rootStore) + { + success = CertAddCertificateContextToStore(rootStore, certCtx, CERT_STORE_ADD_REPLACE_EXISTING, NULL); + CertCloseStore(rootStore, 0); + } + CertFreeCertificateContext(certCtx); + return success; +} +#endif + +bool CertificateManager::generateAndSaveCA(const char* caName, int days, const std::string& certPath, + const std::string& keyPath) { _caKey.reset(new RsaKey()); wc_InitRsaKey(_caKey.get(), nullptr); - if (wc_MakeRsaKey(_caKey.get(), 2048, 65537, _rng.get()) != 0) - { - return false; - } + 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_s(cert->subject.commonName, sizeof(cert->subject.commonName), "TinyMITM-CA", _TRUNCATE); + strncpy_s(cert->subject.commonName, sizeof(cert->subject.commonName), caName, _TRUNCATE); cert->isCA = 1; cert->sigType = CTC_SHA256wRSA; - cert->daysValid = 3650; + cert->daysValid = days; _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); + std::vector keyDer(4096); + int keyDerLen = wc_RsaKeyToDer(_caKey.get(), keyDer.data(), (word32)keyDer.size()); + if (keyDerLen < 0) return false; + + std::vector keyPem(4096); + int keyPemLen = + wc_DerToPem(keyDer.data(), (word32)keyDerLen, keyPem.data(), (word32)keyPem.size(), PRIVATEKEY_TYPE); + + std::ofstream kOut(keyPath, std::ios::binary); + if (!kOut.is_open()) return false; + kOut.write((char*)keyPem.data(), keyPemLen); + + std::vector certPem(4096); + int certPemLen = + wc_DerToPem(_caCertDer.data(), (word32)_caCertDer.size(), certPem.data(), (word32)certPem.size(), CERT_TYPE); + + std::ofstream cOut(certPath, std::ios::binary); + if (!cOut.is_open()) return false; + cOut.write((char*)certPem.data(), certPemLen); + return true; } -bool CertificateManager::loadCA() +bool CertificateManager::loadCA(const char* certPath, const char* keyPath) { - return false; + auto readFile = [](const char* path) -> std::vector { + std::ifstream file(path, std::ios::binary | std::ios::ate); + if (!file.is_open()) return {}; + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + std::vector buffer((size_t)size); + if (file.read((char*)buffer.data(), size)) return buffer; + return {}; + }; + + std::vector certPem = readFile(certPath); + std::vector keyPem = readFile(keyPath); + + if (certPem.empty() || keyPem.empty()) return false; + + std::vector certDer; + std::vector keyDer; + DerBuffer* derBuff = nullptr; + + int ret = wc_PemToDer(certPem.data(), (long)certPem.size(), CERT_TYPE, &derBuff, nullptr, nullptr, nullptr); + if (ret == 0 && derBuff) + { + certDer.assign(derBuff->buffer, derBuff->buffer + derBuff->length); + free(derBuff->buffer); + free(derBuff); + } + else + return false; + + derBuff = nullptr; + ret = wc_PemToDer(keyPem.data(), (long)keyPem.size(), PRIVATEKEY_TYPE, &derBuff, nullptr, nullptr, nullptr); + if (ret == 0 && derBuff) + { + keyDer.assign(derBuff->buffer, derBuff->buffer + derBuff->length); + free(derBuff->buffer); + free(derBuff); + } + else + return false; + + return decodeCA(certDer, keyDer); +} +bool CertificateManager::decodeCA(const std::vector& certDer, const std::vector& keyDer) +{ + if (certDer.empty() || keyDer.empty()) return false; + + RsaKey* rawKey = new RsaKey(); + if (wc_InitRsaKey(rawKey, nullptr) != 0) + { + delete rawKey; + return false; + } + + std::unique_ptr tempKey(rawKey, RAAIHelper()); + + word32 idx = 0; + int ret = wc_RsaPrivateKeyDecode(keyDer.data(), &idx, tempKey.get(), (word32)keyDer.size()); + + if (ret != 0) return false; + + _caKey = std::move(tempKey); + _caCertDer = certDer; + + return true; } diff --git a/src/proxy/tinymitm/ssl.h b/src/proxy/tinymitm/ssl.h index 59026c9..8fd8a3d 100644 --- a/src/proxy/tinymitm/ssl.h +++ b/src/proxy/tinymitm/ssl.h @@ -18,9 +18,15 @@ class CertificateManager WOLFSSL_CTX* createHostContext(const std::string& host); +#ifdef _WIN32 + bool installCertificate(); +#endif + + bool generateAndSaveCA(const char* caName, int days, const std::string& certPath, const std::string& keyPath); + bool loadCA(const char* certPath, const char* keyPath); + private: - bool generateCA(); - bool loadCA(); + bool decodeCA(const std::vector& certDer, const std::vector& keyDer); std::unique_ptr _caKey; std::unique_ptr _sessionKey; @@ -31,6 +37,6 @@ class CertificateManager std::unique_ptr _rng; std::mutex _mutex; - + std::unordered_map _hostContexts; };