This commit is contained in:
PoliEcho 2025-05-31 12:27:09 +02:00
commit aac8841c0a
11 changed files with 342 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
certs
build
.vscode
src_ref

70
Makefile Normal file
View File

@ -0,0 +1,70 @@
# Compiler and flags
CPPC = g++
CPPC_FLAGS = -std=c++23 -s -O3 -lssl -lcrypto -march=native -fstack-protector-strong -D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -fPIE -pie -Wall -Wextra -Wformat -Wformat=2 -Werror=format-security -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,--as-needed
DEBUG_FLAGS = -ggdb -std=c++23 -lssl -lcrypto -march=native -fstack-protector-strong -D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -fPIE -pie -Wall -Wextra -Wformat -Wformat=2 -Werror=format-security -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,--as-needed
DEBUG_ASANITIZE = -fsanitize=address -ggdb -fno-omit-frame-pointer -std=c++23 -lssl -lcrypto -march=native -fstack-protector-strong -D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -fPIE -pie -Wall -Wextra -Wformat -Wformat=2 -Werror=format-security -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,--as-needed
SRC_PATH_CLIENT := src/client
SRC_PATH_SERVER := src/server
SRC_PATH_COMMON := src/common
OBJ_PATH := build/obj
BIN_PATH := build/bin
OBJ_PATH_CLIENT := $(OBJ_PATH)/client
OBJ_PATH_SERVER := $(OBJ_PATH)/server
OBJ_PATH_COMMON := build/obj/common
BIN_NAME_CLIENT := if_client
BIN_NAME_SERVER := if_server
SRC_FILES_CLIENT := $(shell find $(SRC_PATH_CLIENT) -name '*.cpp')
OBJ_FILES_CLIENT := $(patsubst $(SRC_PATH_CLIENT)/%.cpp,$(OBJ_PATH_CLIENT)/%.o,$(SRC_FILES_CLIENT))
SRC_FILES_SERVER := $(shell find $(SRC_PATH_SERVER) -name '*.cpp')
OBJ_FILES_SERVER := $(patsubst $(SRC_PATH_SERVER)/%.cpp,$(OBJ_PATH_SERVER)/%.o,$(SRC_FILES_SERVER))
SRC_FILES_COMMON := $(shell find $(SRC_PATH_COMMON) -name '*.cpp')
OBJ_FILES_COMMON := $(patsubst $(SRC_PATH_COMMON)/%.cpp,$(OBJ_PATH_COMMON)/%.o,$(SRC_FILES_COMMON))
all: make-build-dir $(BIN_PATH)/$(BIN_NAME_CLIENT) $(BIN_PATH)/$(BIN_NAME_SERVER)
debug: CPPC_FLAGS = $(DEBUG_FLAGS)
debug: make-build-dir $(BIN_PATH)/$(BIN_NAME_CLIENT) $(BIN_PATH)/$(BIN_NAME_SERVER)
asan: CPPC_FLAGS = $(DEBUG_ASANITIZE)
asan: make-build-dir $(BIN_PATH)/$(BIN_NAME_CLIENT) $(BIN_PATH)/$(BIN_NAME_SERVER)
make-build-dir:
mkdir -p $(OBJ_PATH_CLIENT)
mkdir -p $(OBJ_PATH_SERVER)
mkdir -p $(OBJ_PATH_COMMON)
mkdir -p $(BIN_PATH)
$(BIN_PATH)/$(BIN_NAME_CLIENT): $(OBJ_FILES_CLIENT) $(OBJ_FILES_COMMON)
$(CPPC) $(CPPC_FLAGS) $^ -o $@
$(BIN_PATH)/$(BIN_NAME_SERVER): $(OBJ_FILES_SERVER) $(OBJ_FILES_COMMON)
$(CPPC) $(CPPC_FLAGS) $^ -o $@
$(OBJ_PATH_COMMON)/%.o: $(SRC_PATH_COMMON)/%.cpp
$(CPPC) $(CPPC_FLAGS) -c $< -o $@
$(OBJ_PATH_CLIENT)/%.o: $(SRC_PATH_CLIENT)/%.cpp
$(CPPC) $(CPPC_FLAGS) -c $< -o $@
$(OBJ_PATH_SERVER)/%.o: $(SRC_PATH_SERVER)/%.cpp
$(CPPC) $(CPPC_FLAGS) -c $< -o $@
install:
@install -vpm 755 -o root -g root $(BIN_PATH)/$(BIN_NAME_CLIENT) /usr/bin/
clean:
rm -fr build
.PHONY: all clean install debug asan

17
misc/gen.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
# generate_certs.sh
# Requires oqsprovider installed (dnf install oqsprovider)
# Generate CA
openssl genpkey -algorithm mldsa87 -out ca.key
openssl req -x509 -new -key ca.key -out ca.crt -subj "/CN=PQC CA"
# Generate server cert
openssl genpkey -algorithm mldsa44 -out server.key
openssl req -new -key server.key -out server.csr -subj "/CN=Post-Quantum Server"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
# Generate client cert
openssl genpkey -algorithm mldsa87 -out client.key
openssl req -new -key client.key -out client.csr -subj "/CN=Post-Quantum Client"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt

61
src/client/main.cpp Normal file
View File

@ -0,0 +1,61 @@
#include "../common/cleanup.h"
#include "../common/const.h"
#include "../common/global.h"
#include "../common/tls.h"
#include <arpa/inet.h>
#include <csignal>
#include <iostream>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <sys/socket.h>
#include <unistd.h>
SSL_CTX *ctx;
int sockfd;
int main() {
std::signal(SIGTERM, safe_exit);
std::signal(SIGINT, safe_exit);
std::signal(SIGQUIT, safe_exit);
std::signal(SIGHUP, safe_exit);
// error signal handlers
signal(SIGSEGV, safe_exit);
ctx = create_context(false);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
std::cerr << "Socket creation failed: " << strerror(errno) << std::endl;
return 1;
}
std::cout << "Socket created successfully (fd: " << sockfd << ")"
<< std::endl;
sockaddr_in serv_addr{};
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
if (connect(sockfd, (sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
std::cerr << "Connection failed: " << strerror(errno) << std::endl;
return 1;
}
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
int result = SSL_connect(ssl);
if (result != 1) {
int ssl_error = SSL_get_error(ssl, result);
std::cerr << "SSL_connect failed with error code: " << ssl_error
<< std::endl;
ERR_print_errors_fp(stderr);
return 1;
}
std::cout << "SSL connection established successfully" << std::endl;
handle_connection(ssl);
SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return 0;
}

31
src/common/cleanup.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "global.h"
#include <csignal>
#include <iostream>
#include <openssl/ssl.h>
void safe_exit(int code) {
switch (code) {
case SIGTERM:
std::cerr << "\nreceived SIGTERM exiting...\n";
break;
case SIGINT:
std::cerr << "\nreceived SIGINT exiting...\n";
break;
case SIGQUIT:
std::cerr << "\nreceived SIGQUIT exiting...\n";
break;
case SIGHUP:
std::cerr << "\nreceived SIGHUP exiting...\n";
break;
case SIGSEGV:
std::cerr << "\nreceived SIGSEGV(segmentation fault) exiting...\nIf this "
"repeats please report it as a bug\n";
break;
default:
break;
}
SSL_CTX_free(ctx);
close(sockfd);
exit(code);
}

4
src/common/cleanup.h Normal file
View File

@ -0,0 +1,4 @@
#ifndef _IF_CLEANUP_HG_
#define _IF_CLEANUP_HG_
void safe_exit(int code);
#endif

5
src/common/const.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef _IF_CONST_HG_
#define _IF_CONST_HG_
#define CERTS_DIR "certs/"
#define PORT 11723
#endif

6
src/common/global.h Normal file
View File

@ -0,0 +1,6 @@
#include <openssl/crypto.h>
#ifndef _IF_GLOBAL_HG_
#define _IF_GLOBAL_HG_
extern SSL_CTX *ctx;
extern int sockfd;
#endif

74
src/common/tls.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "const.h"
#include <iostream>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <string>
#include <thread>
SSL_CTX *create_context(bool is_server) {
const SSL_METHOD *method =
is_server ? TLS_server_method() : TLS_client_method();
SSL_CTX *ctx = SSL_CTX_new(method);
SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
if (is_server) {
SSL_CTX_use_certificate_file(ctx, CERTS_DIR "server.crt", SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, CERTS_DIR "server.key", SSL_FILETYPE_PEM);
} else {
SSL_CTX_use_certificate_file(ctx, CERTS_DIR "client.crt", SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, CERTS_DIR "client.key", SSL_FILETYPE_PEM);
}
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, nullptr);
SSL_CTX_load_verify_locations(ctx, CERTS_DIR "ca.crt", nullptr);
return ctx;
}
void handle_connection(SSL *ssl) {
char buf[1024];
std::cout << "Starting connection handler for SSL session" << std::endl;
std::thread send_thread([ssl]() {
while (true) {
std::string msg;
std::cout << "Enter message: ";
std::getline(std::cin, msg);
if (msg == "quit") {
std::cout << "Terminating send thread" << std::endl;
break;
}
int bytes_sent = SSL_write(ssl, msg.c_str(), msg.size());
if (bytes_sent <= 0) {
int ssl_error = SSL_get_error(ssl, bytes_sent);
std::cerr << "SSL_write failed with error: " << ssl_error << std::endl;
ERR_print_errors_fp(stderr);
break;
}
std::cout << "Sent " << bytes_sent << " bytes to server" << std::endl;
}
});
while (true) {
int bytes = SSL_read(ssl, buf, sizeof(buf) - 1);
if (bytes > 0) {
buf[bytes] = '\0';
std::cout << "Received " << bytes << " bytes from server: " << buf
<< std::endl;
} else if (bytes == 0) {
std::cout << "Connection closed by peer" << std::endl;
break;
} else {
int ssl_error = SSL_get_error(ssl, bytes);
std::cerr << "SSL_read failed with error: " << ssl_error << std::endl;
ERR_print_errors_fp(stderr);
break;
}
}
std::clog << "joining treads";
send_thread.join();
std::cout << "Connection handler finished" << std::endl;
}

7
src/common/tls.h Normal file
View File

@ -0,0 +1,7 @@
#include <openssl/ssl.h>
#ifndef _IF_TLS_HG_
#define _IF_TLS_HG_
SSL_CTX *create_context(bool is_server);
void handle_connection(SSL *ssl);
#endif

63
src/server/main.cpp Normal file
View File

@ -0,0 +1,63 @@
#include "../common/cleanup.h"
#include "../common/const.h"
#include "../common/global.h"
#include "../common/tls.h"
#include <arpa/inet.h>
#include <csignal>
#include <iostream>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <sys/socket.h>
#include <unistd.h>
SSL_CTX *ctx;
int sockfd;
int main() {
std::signal(SIGTERM, safe_exit);
std::signal(SIGINT, safe_exit);
std::signal(SIGQUIT, safe_exit);
std::signal(SIGHUP, safe_exit);
// error signal handlers
signal(SIGSEGV, safe_exit);
ctx = create_context(true);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
std::cerr << "Socket creation failed: " << strerror(errno) << std::endl;
return 1;
}
std::cout << "Socket created successfully (fd: " << sockfd << ")"
<< std::endl;
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (sockaddr *)&addr, sizeof(addr)) != 0) {
std::cerr << "Bind failed: " << strerror(errno) << std::endl;
return 1;
}
listen(sockfd, 5);
while (true) {
sockaddr_in client_addr{};
socklen_t len = sizeof(client_addr);
int client_fd = accept(sockfd, (sockaddr *)&client_addr, &len);
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_fd);
SSL_accept(ssl);
handle_connection(ssl);
SSL_shutdown(ssl);
SSL_free(ssl);
close(client_fd);
}
SSL_CTX_free(ctx);
close(sockfd);
return 0;
}