feat: add CertificateManager
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
#include "ssl.h"
|
||||
|
||||
#define WOLFSSL_ALT_NAMES
|
||||
|
||||
#include <wolfssl/options.h>
|
||||
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/wolfcrypt/rsa.h>
|
||||
#include <wolfssl/wolfcrypt/asn.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
/*
|
||||
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<std::mutex> lock(_mutex);
|
||||
if (_hostContexts.count(host)) return _hostContexts[host];
|
||||
if (!_caKey) return nullptr;
|
||||
|
||||
auto cert = std::make_unique<Cert>();
|
||||
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<std::string>{}(host) & 0x7FFFFFFF;
|
||||
memcpy(cert->serial, &serial, sizeof(serial));
|
||||
cert->serialSz = sizeof(serial);
|
||||
|
||||
wc_SetAltNames(cert.get(), host.c_str());
|
||||
|
||||
std::vector<unsigned char> 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<Cert>();
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#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<RsaKey, WolfSSLDeleter> _caKey;
|
||||
std::unique_ptr<RsaKey, WolfSSLDeleter> _sessionKey;
|
||||
|
||||
std::vector<unsigned char> _caCertDer;
|
||||
std::vector<unsigned char> _sessionKeyDer;
|
||||
|
||||
std::unique_ptr<WC_RNG, WolfSSLDeleter> _rng;
|
||||
|
||||
std::mutex _mutex;
|
||||
|
||||
std::unordered_map<std::string, WOLFSSL_CTX*> _hostContexts;
|
||||
};
|
||||
Reference in New Issue
Block a user