feat: add CA install fn, load and gen fns, and decode helper

This commit is contained in:
2026-05-12 18:21:32 -03:00
parent 81dcb60e08
commit 691489215d
2 changed files with 127 additions and 16 deletions
+117 -12
View File
@@ -12,6 +12,12 @@
#include <fstream> #include <fstream>
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")
#endif
/* /*
CertificateManager implementation CertificateManager implementation
*/ */
@@ -38,8 +44,7 @@ bool CertificateManager::init()
if (derLen < 0) return false; if (derLen < 0) return false;
_sessionKeyDer.resize(derLen); _sessionKeyDer.resize(derLen);
if (loadCA()) return true; return true;
return generateCA();
} }
WOLFSSL_CTX* CertificateManager::createHostContext(const std::string& host) WOLFSSL_CTX* CertificateManager::createHostContext(const std::string& host)
@@ -87,41 +92,141 @@ WOLFSSL_CTX* CertificateManager::createHostContext(const std::string& host)
return ctx; 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()); _caKey.reset(new RsaKey());
wc_InitRsaKey(_caKey.get(), nullptr); wc_InitRsaKey(_caKey.get(), nullptr);
if (wc_MakeRsaKey(_caKey.get(), 2048, 65537, _rng.get()) != 0) if (wc_MakeRsaKey(_caKey.get(), 2048, 65537, _rng.get()) != 0) return false;
{
return false;
}
auto cert = std::make_unique<Cert>(); auto cert = std::make_unique<Cert>();
memset(cert.get(), 0, sizeof(Cert)); memset(cert.get(), 0, sizeof(Cert));
wc_InitCert(cert.get()); 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->isCA = 1;
cert->sigType = CTC_SHA256wRSA; cert->sigType = CTC_SHA256wRSA;
cert->daysValid = 3650; cert->daysValid = days;
_caCertDer.resize(4096); _caCertDer.resize(4096);
int certLen = int certLen =
wc_MakeCert(cert.get(), _caCertDer.data(), (word32)_caCertDer.size(), _caKey.get(), nullptr, _rng.get()); wc_MakeCert(cert.get(), _caCertDer.data(), (word32)_caCertDer.size(), _caKey.get(), nullptr, _rng.get());
if (certLen < 0) return false; if (certLen < 0) return false;
certLen = wc_SignCert(cert->bodySz, cert->sigType, _caCertDer.data(), (word32)_caCertDer.size(), _caKey.get(), certLen = wc_SignCert(cert->bodySz, cert->sigType, _caCertDer.data(), (word32)_caCertDer.size(), _caKey.get(),
nullptr, _rng.get()); nullptr, _rng.get());
if (certLen < 0) return false; if (certLen < 0) return false;
_caCertDer.resize(certLen); _caCertDer.resize(certLen);
std::vector<unsigned char> keyDer(4096);
int keyDerLen = wc_RsaKeyToDer(_caKey.get(), keyDer.data(), (word32)keyDer.size());
if (keyDerLen < 0) return false;
std::vector<unsigned char> 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<unsigned char> 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; return true;
} }
bool CertificateManager::loadCA() bool CertificateManager::loadCA(const char* certPath, const char* keyPath)
{ {
auto readFile = [](const char* path) -> std::vector<unsigned char> {
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<unsigned char> buffer((size_t)size);
if (file.read((char*)buffer.data(), size)) return buffer;
return {};
};
std::vector<unsigned char> certPem = readFile(certPath);
std::vector<unsigned char> keyPem = readFile(keyPath);
if (certPem.empty() || keyPem.empty()) return false;
std::vector<unsigned char> certDer;
std::vector<unsigned char> 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; 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<unsigned char>& certDer, const std::vector<unsigned char>& 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<RsaKey, RAAIHelper> 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;
} }
+8 -2
View File
@@ -18,9 +18,15 @@ class CertificateManager
WOLFSSL_CTX* createHostContext(const std::string& host); 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: private:
bool generateCA(); bool decodeCA(const std::vector<unsigned char>& certDer, const std::vector<unsigned char>& keyDer);
bool loadCA();
std::unique_ptr<RsaKey, RAAIHelper> _caKey; std::unique_ptr<RsaKey, RAAIHelper> _caKey;
std::unique_ptr<RsaKey, RAAIHelper> _sessionKey; std::unique_ptr<RsaKey, RAAIHelper> _sessionKey;