diff --git a/src/unlocker/cert_manager.cpp b/src/unlocker/cert_manager.cpp index 9a801ef..310681f 100644 --- a/src/unlocker/cert_manager.cpp +++ b/src/unlocker/cert_manager.cpp @@ -22,12 +22,13 @@ std::string randomizeString(size_t length) return result; } -CertManager::CertManager() {} +CertManager::CertManager() : _sessionPkey(nullptr) {} CertManager::~CertManager() { if (_caPkey) EVP_PKEY_free(_caPkey); if (_caCert) X509_free(_caCert); + if (_sessionPkey) EVP_PKEY_free(_sessionPkey); for (auto& pair : _hostContexts) SSL_CTX_free(pair.second); @@ -35,6 +36,15 @@ CertManager::~CertManager() bool CertManager::Init() { + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr); + if (pctx) + { + EVP_PKEY_keygen_init(pctx); + EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048); + EVP_PKEY_keygen(pctx, &_sessionPkey); + EVP_PKEY_CTX_free(pctx); + } + if (LoadCA()) { Log::verbose("Loaded existing CA certificate."); @@ -138,12 +148,8 @@ SSL_CTX* CertManager::CreateHostContext(const std::string& host) Log::verbose("Generating dynamic certificate for {}", host); - EVP_PKEY* pkey = nullptr; - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr); - EVP_PKEY_keygen_init(pctx); - EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048); - EVP_PKEY_keygen(pctx, &pkey); - EVP_PKEY_CTX_free(pctx); + EVP_PKEY* pkey = _sessionPkey; + if (!pkey) return nullptr; X509* cert = X509_new(); X509_set_version(cert, 2); @@ -174,11 +180,30 @@ SSL_CTX* CertManager::CreateHostContext(const std::string& host) X509_sign(cert, _caPkey, EVP_sha256()); SSL_CTX* ctx = SSL_CTX_new(TLS_server_method()); + + SSL_CTX_set_alpn_select_cb( + ctx, + [](SSL* ssl, const unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen, + void* arg) -> int { + for (unsigned int i = 0; i < inlen;) + { + unsigned int len = in[i]; + if (len == 8 && memcmp(&in[i + 1], "http/1.1", 8) == 0) + { + *out = &in[i + 1]; + *outlen = (unsigned char)len; + return SSL_TLSEXT_ERR_OK; + } + i += len + 1; + } + return SSL_TLSEXT_ERR_NOACK; + }, + nullptr); + SSL_CTX_use_certificate(ctx, cert); SSL_CTX_use_PrivateKey(ctx, pkey); X509_free(cert); - EVP_PKEY_free(pkey); _hostContexts[host] = ctx; return ctx; diff --git a/src/unlocker/cert_manager.h b/src/unlocker/cert_manager.h index da1f8a3..6a09b46 100644 --- a/src/unlocker/cert_manager.h +++ b/src/unlocker/cert_manager.h @@ -19,6 +19,7 @@ private: EVP_PKEY* _caPkey = nullptr; X509* _caCert = nullptr; + EVP_PKEY* _sessionPkey = nullptr; std::mutex _mutex; std::unordered_map _hostContexts;