commit aac8841c0af0d55b36bf8e3f7a60aa4cb2e895a6 Author: PoliEcho Date: Sat May 31 12:27:09 2025 +0200 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6854b56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +certs +build +.vscode +src_ref \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c894e8d --- /dev/null +++ b/Makefile @@ -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 diff --git a/misc/gen.sh b/misc/gen.sh new file mode 100755 index 0000000..4a041d1 --- /dev/null +++ b/misc/gen.sh @@ -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 diff --git a/src/client/main.cpp b/src/client/main.cpp new file mode 100644 index 0000000..9ae547a --- /dev/null +++ b/src/client/main.cpp @@ -0,0 +1,61 @@ +#include "../common/cleanup.h" +#include "../common/const.h" +#include "../common/global.h" +#include "../common/tls.h" +#include +#include +#include +#include +#include +#include +#include +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; +} diff --git a/src/common/cleanup.cpp b/src/common/cleanup.cpp new file mode 100644 index 0000000..e822518 --- /dev/null +++ b/src/common/cleanup.cpp @@ -0,0 +1,31 @@ +#include "global.h" +#include +#include +#include +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); +} \ No newline at end of file diff --git a/src/common/cleanup.h b/src/common/cleanup.h new file mode 100644 index 0000000..bccb087 --- /dev/null +++ b/src/common/cleanup.h @@ -0,0 +1,4 @@ +#ifndef _IF_CLEANUP_HG_ +#define _IF_CLEANUP_HG_ +void safe_exit(int code); +#endif \ No newline at end of file diff --git a/src/common/const.h b/src/common/const.h new file mode 100644 index 0000000..d96e9f4 --- /dev/null +++ b/src/common/const.h @@ -0,0 +1,5 @@ +#ifndef _IF_CONST_HG_ +#define _IF_CONST_HG_ +#define CERTS_DIR "certs/" +#define PORT 11723 +#endif \ No newline at end of file diff --git a/src/common/global.h b/src/common/global.h new file mode 100644 index 0000000..37cb822 --- /dev/null +++ b/src/common/global.h @@ -0,0 +1,6 @@ +#include +#ifndef _IF_GLOBAL_HG_ +#define _IF_GLOBAL_HG_ +extern SSL_CTX *ctx; +extern int sockfd; +#endif \ No newline at end of file diff --git a/src/common/tls.cpp b/src/common/tls.cpp new file mode 100644 index 0000000..0116125 --- /dev/null +++ b/src/common/tls.cpp @@ -0,0 +1,74 @@ +#include "const.h" +#include +#include +#include +#include +#include + +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; +} diff --git a/src/common/tls.h b/src/common/tls.h new file mode 100644 index 0000000..1e83218 --- /dev/null +++ b/src/common/tls.h @@ -0,0 +1,7 @@ +#include + +#ifndef _IF_TLS_HG_ +#define _IF_TLS_HG_ +SSL_CTX *create_context(bool is_server); +void handle_connection(SSL *ssl); +#endif \ No newline at end of file diff --git a/src/server/main.cpp b/src/server/main.cpp new file mode 100644 index 0000000..b26f66a --- /dev/null +++ b/src/server/main.cpp @@ -0,0 +1,63 @@ +#include "../common/cleanup.h" +#include "../common/const.h" +#include "../common/global.h" +#include "../common/tls.h" +#include +#include +#include +#include +#include +#include +#include +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; +}