You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

219 lines
7.9 KiB

// test_etcp_crypto.c - Test ETCP encryption/decryption with secure channel
#include "etcp.h"
#include "config_parser.h"
#include "secure_channel.h"
#include "etcp_connections.h"
#include "packet_buffer.h"
#include "packet_pool.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
// Test configuration
#define TEST_PORT 42345
#define CLIENT_PORT 42346
#define TEST_DATA "Hello, encrypted world!"
#define TEST_DATA_LEN 23
// Helper: create UDP socket bound to port
static int create_udp_socket(int port) {
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) return -1;
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
close(fd);
return -1;
}
return fd;
}
// Helper: generate test keys
static void generate_test_keys(uint8_t* server_priv, uint8_t* server_pub,
uint8_t* client_priv, uint8_t* client_pub) {
// Use fixed test keys for reproducibility
const char* server_priv_hex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
const char* server_pub_hex = "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789";
const char* client_priv_hex = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210";
const char* client_pub_hex = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
for (int i = 0; i < 32; i++) {
sscanf(server_priv_hex + i*2, "%2hhx", &server_priv[i]);
sscanf(server_pub_hex + i*2, "%2hhx", &server_pub[i]);
sscanf(client_priv_hex + i*2, "%2hhx", &client_priv[i]);
sscanf(client_pub_hex + i*2, "%2hhx", &client_pub[i]);
}
}
// Helper: hex to binary
static int hex_to_bin(const char* hex, uint8_t* bin, size_t len) {
if (strlen(hex) != len * 2) return -1;
for (size_t i = 0; i < len; i++) {
if (sscanf(hex + i*2, "%2hhx", &bin[i]) != 1) return -1;
}
return 0;
}
int main(void) {
printf("=== ETCP Crypto Test ===\n");
// Generate test keys
uint8_t server_priv[32], server_pub[32];
uint8_t client_priv[32], client_pub[32];
generate_test_keys(server_priv, server_pub, client_priv, client_pub);
// Create UDP sockets
int server_fd = create_udp_socket(TEST_PORT);
int client_fd = create_udp_socket(CLIENT_PORT);
if (server_fd < 0 || client_fd < 0) {
printf("ERROR: Failed to create sockets\n");
return 1;
}
// Create ETCP instances
struct ETCP_CONN* server_etcp = calloc(1, sizeof(struct ETCP_CONN));
struct ETCP_CONN* client_etcp = calloc(1, sizeof(struct ETCP_CONN));
if (!server_etcp || !client_etcp) {
printf("ERROR: Failed to allocate ETCP instances\n");
return 1;
}
// Initialize secure channels
server_etcp->crypto_ctx = calloc(1, sizeof(sc_context_t));
client_etcp->crypto_ctx = calloc(1, sizeof(sc_context_t));
if (!server_etcp->crypto_ctx || !client_etcp->crypto_ctx) {
printf("ERROR: Failed to allocate crypto contexts\n");
return 1;
}
// Set keys
memcpy(server_etcp->crypto_ctx->private_key, server_priv, 32);
memcpy(server_etcp->crypto_ctx->public_key, server_pub, 32);
server_etcp->crypto_ctx->initialized = 1;
memcpy(client_etcp->crypto_ctx->private_key, client_priv, 32);
memcpy(client_etcp->crypto_ctx->public_key, client_pub, 32);
client_etcp->crypto_ctx->initialized = 1;
// Client sets server's public key as peer
memcpy(client_etcp->peer_public_key, server_pub, 32);
client_etcp->has_peer_key = 1;
sc_set_peer_public_key(client_etcp->crypto_ctx, server_pub);
// Server will get client's public key from INIT packet
// Create connections managers
struct ETCP_CONNECTIONS* server_conns = etcp_connections_init(server_etcp, "127.0.0.1", 0);
struct ETCP_CONNECTIONS* client_conns = etcp_connections_init(client_etcp, "127.0.0.1", 0);
if (!server_conns || !client_conns) {
printf("ERROR: Failed to create connections\n");
return 1;
}
// Create client link (client initiates connection)
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(TEST_PORT);
struct ETCP_LINK* client_link = etcp_link_new(client_etcp, &client_conns->socket, client_conns,
(struct sockaddr*)&server_addr, sizeof(server_addr));
if (!client_link) {
printf("ERROR: Failed to create client link\n");
return 1;
}
// Send INIT from client to server
printf("Sending INIT from client...\n");
if (etcp_link_send_init(client_link, 1500, 30) < 0) {
printf("ERROR: Failed to send INIT\n");
return 1;
}
// Server should receive INIT and create link
usleep(100000); // 100ms
struct sockaddr_in from_addr;
socklen_t from_len = sizeof(from_addr);
uint8_t buffer[2048];
ssize_t received = recvfrom(server_fd, buffer, sizeof(buffer), MSG_DONTWAIT,
(struct sockaddr*)&from_addr, &from_len);
if (received > 0) {
printf("Server received %zd bytes\n", received);
// Process packet on server - use packet pool
struct packet_buffer* pkt = packet_pool_get(&server_etcp->packet_pool);
if (pkt) {
memcpy(packet_data(pkt), buffer, received);
pkt->metadata.data_len = received;
pkt->metadata.remote_addr = *(struct sockaddr_storage*)&from_addr;
pkt->metadata.s = &server_conns->socket;
if (etcp_input(pkt, &server_conns->socket, server_conns) == 0) {
printf("Server processed INIT successfully\n");
// Check that server got client's public key
if (server_etcp->has_peer_key) {
printf("Server received client's public key\n");
}
}
packet_pool_put(&server_etcp->packet_pool, pkt);
}
}
// Test encrypted data transfer
printf("\nTesting encrypted data transfer...\n");
const char* test_data = TEST_DATA;
if (etcp_link_send(client_etcp, client_link, (const uint8_t*)test_data, TEST_DATA_LEN) == 0) {
printf("Client sent encrypted data\n");
}
usleep(100000);
received = recvfrom(server_fd, buffer, sizeof(buffer), MSG_DONTWAIT,
(struct sockaddr*)&from_addr, &from_len);
if (received > 0) {
printf("Server received %zd encrypted bytes\n", received);
// In real scenario, etcp_input would decrypt and process
}
// Print statistics
printf("\n=== Statistics ===\n");
size_t enc_err, dec_err, send_err, total_enc, total_dec;
etcp_connections_get_crypto_stats(server_conns, &enc_err, &dec_err, &send_err, NULL, &total_enc, &total_dec);
printf("Server: encrypted=%zu, decrypted=%zu, errors=%zu/%zu/%zu\n",
total_enc, total_dec, enc_err, dec_err, send_err);
etcp_connections_get_crypto_stats(client_conns, &enc_err, &dec_err, &send_err, NULL, &total_enc, &total_dec);
printf("Client: encrypted=%zu, decrypted=%zu, errors=%zu/%zu/%zu\n",
total_enc, total_dec, enc_err, dec_err, send_err);
// Cleanup
close(server_fd);
close(client_fd);
free(server_etcp->crypto_ctx);
free(client_etcp->crypto_ctx);
free(server_etcp);
free(client_etcp);
printf("\n=== Test completed ===\n");
return 0;
}