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

View File

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

View File

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

View File

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

View File

@ -4,6 +4,8 @@
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/opensslv.h>
#include <openssl/provider.h>
namespace ehs namespace ehs
{ {
@ -12,6 +14,11 @@ namespace ehs
if (!IsValid()) if (!IsValid())
return; return;
EVP_PKEY_free(pkey);
X509_free(cert);
if (sslHdl) if (sslHdl)
{ {
if (connection) if (connection)
@ -25,28 +32,28 @@ namespace ehs
} }
SSL::SSL() SSL::SSL()
: ctx(nullptr), sslHdl(nullptr) : server(false), ctx(nullptr), sslHdl(nullptr), cert(nullptr), pkey(nullptr)
{ {
} }
SSL::SSL(const IP &type) SSL::SSL(const IP &type, const bool &server)
: TCP(type), ctx(nullptr), sslHdl(nullptr) : TCP(type), server(server), ctx(nullptr), sslHdl(nullptr), cert(nullptr), pkey(nullptr)
{ {
SSL::Initialize(); SSL::Initialize();
} }
SSL::SSL(TCP&& tcp) noexcept 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) 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) 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); TCP::operator=(ssl);
server = ssl.server;
ctx = nullptr; ctx = nullptr;
sslHdl = nullptr; sslHdl = nullptr;
cert = nullptr;
pkey = nullptr;
return *this; return *this;
} }
@ -71,6 +81,40 @@ namespace ehs
return; return;
SSL_library_init(); 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() void SSL::Release()
@ -80,6 +124,12 @@ namespace ehs
if (!IsValid()) if (!IsValid())
return; return;
EVP_PKEY_free(pkey);
pkey = nullptr;
X509_free(cert);
cert = nullptr;
if (sslHdl) if (sslHdl)
{ {
if (connection) if (connection)
@ -107,26 +157,12 @@ namespace ehs
void SSL::Listen() 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); sslHdl = SSL_new(ctx);
SSL_set_fd(sslHdl, hdl); SSL_set_fd(sslHdl, hdl);
TCP::Listen(); TCP::Listen();
EHS_LOG_SUCCESS();
} }
SSL* SSL::Accept() SSL* SSL::Accept()
@ -142,8 +178,14 @@ namespace ehs
delete tcp; delete tcp;
client->ctx = nullptr; client->sslHdl = SSL_new(this->ctx);
client->sslHdl = SSL_new(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); SSL_set_fd(client->sslHdl, client->hdl);
int err = SSL_accept(client->sslHdl); int err = SSL_accept(client->sslHdl);
@ -153,6 +195,8 @@ namespace ehs
return {}; return {};
} }
EHS_LOG_SUCCESS();
return client; return client;
} }
@ -160,20 +204,6 @@ namespace ehs
{ {
TCP::Connect(address, port); 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); sslHdl = SSL_new(ctx);
SSL_set_fd(sslHdl, hdl); SSL_set_fd(sslHdl, hdl);
@ -226,40 +256,34 @@ namespace ehs
return received; 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); BIO* certBio = BIO_new_mem_buf(data, (int)size);
if (!cert) X509 *cert = PEM_read_bio_X509(certBio, nullptr, nullptr, nullptr);
{
EHS_LOG_INT(LogType::ERR, 0, "Invalid certificate.");
return;
}
if (SSL_CTX_use_certificate(ctx, cert) != 1) if (!SSL_CTX_use_certificate(ctx, cert))
{ {
EHS_LOG_INT(LogType::ERR, 1, "Failed to use certificate."); UInt_32 code = ERR_get_error();
return; EHS_LOG_INT(LogType::ERR, 0, ERR_error_string(code, nullptr));
} return;
}
X509_free(cert); BIO_free(certBio);
} }
void SSL::UsePrivateKey(const Byte* data, const UInt_64 size) void SSL::UsePrivateKey(const Char_8* data, const UInt_32 &size)
{ {
EVP_PKEY *key = d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &data, (long)size); BIO* keyBio = BIO_new_mem_buf(data, (int)size);
if (!key) EVP_PKEY* pkey = PEM_read_bio_PrivateKey(keyBio, nullptr, nullptr, nullptr);
{
EHS_LOG_INT(LogType::ERR, 0, "Invalid private key.");
return;
}
if (SSL_CTX_use_PrivateKey(ctx, key) != 1) if (!SSL_CTX_use_PrivateKey(ctx, pkey))
{ {
EHS_LOG_INT(LogType::ERR, 1, "Failed to use private key."); UInt_32 code = ERR_get_error();
return; EHS_LOG_INT(LogType::ERR, 0, ERR_error_string(code, nullptr));
} return;
}
EVP_PKEY_free(key); BIO_free(keyBio);
} }
bool SSL::IsValid() bool SSL::IsValid()