This commit is contained in:
Karutoh 2025-05-22 23:56:00 -07:00
parent fbd8464043
commit 159428ea76
5 changed files with 105 additions and 67 deletions

View File

@ -1,5 +1,7 @@
#pragma once
#include <openssl/types.h>
#include "ehs/EHS.h"
#include "ehs/Str.h"
#include "TCP.h"
@ -15,15 +17,18 @@ namespace ehs
class EHS_LIB_IO SSL : public TCP
{
private:
bool server;
SSL_CTX* ctx;
::SSL* sslHdl;
X509 *cert;
EVP_PKEY* pkey;
public:
~SSL() override;
SSL();
SSL(const IP &type);
SSL(const IP &type, const bool &server);
SSL(TCP&& tcp) noexcept;
@ -49,9 +54,9 @@ namespace ehs
UInt_64 Receive(Byte* const buffer, const UInt_32 size) override;
void UseCertificate(const Byte* data, const UInt_64 size);
void UseCertificate(const Char_8* data, const UInt_32 &size);
void UsePrivateKey(const Byte* data, const UInt_64 size);
void UsePrivateKey(const Char_8* data, const UInt_32 &size);
bool IsValid();
};

View File

@ -41,6 +41,7 @@ namespace ehs
TEXT_PLAIN,
TEXT_HTML,
TEXT_XML,
IMG_X_ICON,
NONE
};

View File

@ -264,6 +264,8 @@ namespace ehs
return "text/html";
case ContentType::TEXT_XML:
return "text/xml";
case ContentType::IMG_X_ICON:
return "image/x-icon";
default:
return "";
}
@ -287,6 +289,8 @@ namespace ehs
return ContentType::TEXT_HTML;
else if (value == "text/xml")
return ContentType::TEXT_XML;
else if (value == "image/x-icon")
return ContentType::IMG_X_ICON;
else
return ContentType::NONE;
}

View File

@ -343,6 +343,8 @@ namespace ehs
return "text/html";
case ContentType::TEXT_XML:
return "text/xml";
case ContentType::IMG_X_ICON:
return "image/x-icon";
default:
return "";
}
@ -366,6 +368,8 @@ namespace ehs
return ContentType::TEXT_HTML;
else if (value == "text/xml")
return ContentType::TEXT_XML;
else if (value == "image/x-icon")
return ContentType::IMG_X_ICON;
else
return ContentType::NONE;
}

View File

@ -4,6 +4,8 @@
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/opensslv.h>
#include <openssl/provider.h>
namespace ehs
{
@ -12,6 +14,11 @@ namespace ehs
if (!IsValid())
return;
EVP_PKEY_free(pkey);
X509_free(cert);
if (sslHdl)
{
if (connection)
@ -25,28 +32,28 @@ namespace ehs
}
SSL::SSL()
: ctx(nullptr), sslHdl(nullptr)
: server(false), ctx(nullptr), sslHdl(nullptr), cert(nullptr), pkey(nullptr)
{
}
SSL::SSL(const IP &type)
: TCP(type), ctx(nullptr), sslHdl(nullptr)
SSL::SSL(const IP &type, const bool &server)
: TCP(type), server(server), ctx(nullptr), sslHdl(nullptr), cert(nullptr), pkey(nullptr)
{
SSL::Initialize();
}
SSL::SSL(TCP&& tcp) noexcept
: TCP(std::move(tcp)), ctx(nullptr), sslHdl(nullptr)
: TCP(std::move(tcp)), server(false), ctx(nullptr), sslHdl(nullptr), cert(nullptr), pkey(nullptr)
{
}
SSL::SSL(const TCP& tcp)
: TCP(tcp), ctx(nullptr), sslHdl(nullptr)
: TCP(tcp), server(false), ctx(nullptr), sslHdl(nullptr), cert(nullptr), pkey(nullptr)
{
}
SSL::SSL(const SSL& ssl)
: TCP(ssl), ctx(nullptr), sslHdl(nullptr)
: TCP(ssl), server(ssl.server), ctx(nullptr), sslHdl(nullptr), cert(nullptr), pkey(nullptr)
{
}
@ -57,8 +64,11 @@ namespace ehs
TCP::operator=(ssl);
server = ssl.server;
ctx = nullptr;
sslHdl = nullptr;
cert = nullptr;
pkey = nullptr;
return *this;
}
@ -71,6 +81,40 @@ namespace ehs
return;
SSL_library_init();
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, nullptr);
OSSL_PROVIDER_load(nullptr, "default");
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
if (server)
{
ctx = SSL_CTX_new(TLS_server_method());
if (!ctx)
{
UInt_32 code = ERR_get_error();
EHS_LOG_INT(LogType::ERR, 0, ERR_error_string(code, nullptr));
}
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5");
SSL_CTX_set_ciphersuites(ctx,
"TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:"
"TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256"
);
}
else
{
ctx = SSL_CTX_new(TLS_client_method());
if (!ctx)
{
UInt_32 code = ERR_get_error();
EHS_LOG_INT(LogType::ERR, 0, ERR_error_string(code, nullptr));
}
SSL_CTX_set_default_verify_paths(ctx);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, nullptr);
}
}
void SSL::Release()
@ -80,6 +124,12 @@ namespace ehs
if (!IsValid())
return;
EVP_PKEY_free(pkey);
pkey = nullptr;
X509_free(cert);
cert = nullptr;
if (sslHdl)
{
if (connection)
@ -107,26 +157,12 @@ namespace ehs
void SSL::Listen()
{
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(TLS_server_method());
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5");
SSL_CTX_set_ciphersuites(ctx,
"TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:"
"TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256"
);
#if OPENSSL_VERSION_NUMBER < 0x10101000L
SSL_CTX_set_ecdh_auto(ctx, 1);
#endif
sslHdl = SSL_new(ctx);
SSL_set_fd(sslHdl, hdl);
TCP::Listen();
EHS_LOG_SUCCESS();
}
SSL* SSL::Accept()
@ -142,8 +178,14 @@ namespace ehs
delete tcp;
client->ctx = nullptr;
client->sslHdl = SSL_new(ctx);
client->sslHdl = SSL_new(this->ctx);
if (!client->sslHdl)
{
UInt_32 code = ERR_get_error();
EHS_LOG_INT(LogType::ERR, 0, ERR_error_string(code, nullptr));
return nullptr;
}
SSL_set_fd(client->sslHdl, client->hdl);
int err = SSL_accept(client->sslHdl);
@ -153,6 +195,8 @@ namespace ehs
return {};
}
EHS_LOG_SUCCESS();
return client;
}
@ -160,20 +204,6 @@ namespace ehs
{
TCP::Connect(address, port);
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(TLS_client_method());
if (!ctx)
{
EHS_LOG_INT(LogType::ERR, 0, "Failed to creat SSL context.");
return;
}
SSL_CTX_set_default_verify_paths(ctx);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, nullptr);
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
sslHdl = SSL_new(ctx);
SSL_set_fd(sslHdl, hdl);
@ -226,40 +256,34 @@ namespace ehs
return received;
}
void SSL::UseCertificate(const Byte* data, const UInt_64 size)
void SSL::UseCertificate(const Char_8* data, const UInt_32 &size)
{
X509 *cert = d2i_X509(nullptr, &data, (long)size);
if (!cert)
BIO* certBio = BIO_new_mem_buf(data, (int)size);
X509 *cert = PEM_read_bio_X509(certBio, nullptr, nullptr, nullptr);
if (!SSL_CTX_use_certificate(ctx, cert))
{
EHS_LOG_INT(LogType::ERR, 0, "Invalid certificate.");
UInt_32 code = ERR_get_error();
EHS_LOG_INT(LogType::ERR, 0, ERR_error_string(code, nullptr));
return;
}
if (SSL_CTX_use_certificate(ctx, cert) != 1)
BIO_free(certBio);
}
void SSL::UsePrivateKey(const Char_8* data, const UInt_32 &size)
{
EHS_LOG_INT(LogType::ERR, 1, "Failed to use certificate.");
BIO* keyBio = BIO_new_mem_buf(data, (int)size);
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(keyBio, nullptr, nullptr, nullptr);
if (!SSL_CTX_use_PrivateKey(ctx, pkey))
{
UInt_32 code = ERR_get_error();
EHS_LOG_INT(LogType::ERR, 0, ERR_error_string(code, nullptr));
return;
}
X509_free(cert);
}
void SSL::UsePrivateKey(const Byte* data, const UInt_64 size)
{
EVP_PKEY *key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &data, (long)size);
if (!key)
{
EHS_LOG_INT(LogType::ERR, 0, "Invalid private key.");
return;
}
if (SSL_CTX_use_PrivateKey(ctx, key) != 1)
{
EHS_LOG_INT(LogType::ERR, 1, "Failed to use private key.");
return;
}
EVP_PKEY_free(key);
BIO_free(keyBio);
}
bool SSL::IsValid()