// test_etcp_link_crypto_working.c - Working test with ETCP_LINK encryption via UDP #include "etcp.h" #include "etcp_connections.h" #include "secure_channel.h" #include "packet_pool.h" #include "crc32.h" #include #include #include #include #include #include #include #include #define TEST_PORT_SERVER 22345 #define TEST_PORT_CLIENT 22346 #define TEST_DATA "Hello, encrypted ETCP_LINK!" // Fixed test keys (hex strings) static const char* SERVER_PRIV = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; static const char* SERVER_PUB = "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"; static const char* CLIENT_PRIV = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"; static const char* CLIENT_PUB = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; 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; } // Create UDP socket 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) { perror("bind"); close(fd); return -1; } printf("[SOCK] Created socket on port %d (fd=%d)\n", port, fd); return fd; } // Helper structure for test instance typedef struct { struct ETCP_CONN* etcp; struct ETCP_CONNECTIONS* conns; int socket_fd; uint64_t node_id; const char* name; } test_inst_t; // Initialize crypto context static int init_crypto(struct ETCP_CONN* etcp, const char* priv_hex, const char* pub_hex) { etcp->crypto_ctx = calloc(1, sizeof(sc_context_t)); if (!etcp->crypto_ctx) return -1; uint8_t priv[32], pub[32]; if (hex_to_bin(priv_hex, priv, 32) < 0 || hex_to_bin(pub_hex, pub, 32) < 0) { return -1; } memcpy(etcp->crypto_ctx->private_key, priv, 32); memcpy(etcp->crypto_ctx->public_key, pub, 32); etcp->crypto_ctx->initialized = 1; return 0; } // Create test instance test_inst_t* create_test_inst(const char* name, uint64_t node_id, const char* priv_hex, const char* pub_hex, const char* peer_pub_hex, int bind_port) { test_inst_t* inst = calloc(1, sizeof(test_inst_t)); if (!inst) return NULL; inst->name = name; inst->node_id = node_id; // Create ETCP_CONN inst->etcp = calloc(1, sizeof(struct ETCP_CONN)); if (!inst->etcp) goto error; inst->etcp->node_id = node_id; inst->etcp->state = 1; // Init crypto if (init_crypto(inst->etcp, priv_hex, pub_hex) < 0) { fprintf(stderr, "%s: Failed to init crypto\n", name); goto error; } // Set peer key if provided if (peer_pub_hex) { uint8_t peer_pub[32]; if (hex_to_bin(peer_pub_hex, peer_pub, 32) == 0) { memcpy(inst->etcp->peer_public_key, peer_pub, 32); inst->etcp->has_peer_key = 1; sc_set_peer_public_key(inst->etcp->crypto_ctx, peer_pub); } } // Init packet pool packet_pool_init(&inst->etcp->packet_pool); // Create UDP socket inst->socket_fd = create_udp_socket(bind_port); if (inst->socket_fd < 0) goto error; // Create connections inst->conns = etcp_connections_init(inst->etcp, "127.0.0.1", bind_port); if (!inst->conns) goto error; printf("[INST] %s: Created on port %d (node_id: %llx)\n", name, bind_port, (unsigned long long)node_id); return inst; error: if (inst) { if (inst->etcp) { free(inst->etcp->crypto_ctx); packet_pool_destroy(&inst->etcp->packet_pool); } free(inst->etcp); if (inst->socket_fd >= 0) close(inst->socket_fd); } free(inst); return NULL; } // Destroy test instance void destroy_test_inst(test_inst_t* inst) { if (!inst) return; etcp_destroy(inst->etcp); if (inst->socket_fd >= 0) close(inst->socket_fd); free(inst); } // Create link between instances struct ETCP_LINK* create_test_link(test_inst_t* local, test_inst_t* remote, int remote_port) { struct sockaddr_in remote_addr; memset(&remote_addr, 0, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); remote_addr.sin_port = htons(remote_port); struct ETCP_LINK* link = etcp_link_new(local->etcp, &local->conns->socket, local->conns, (struct sockaddr*)&remote_addr, sizeof(remote_addr)); if (!link) { fprintf(stderr, "Failed to create link\n"); return NULL; } if (etcp_link_add_to_connections(local->conns, link) < 0) { fprintf(stderr, "Failed to add link to connections\n"); etcp_link_close(link); return NULL; } return link; } // Send encrypted data and print stats static int test_send_encrypted(struct ETCP_LINK* link, const uint8_t* data, size_t len) { printf("[SEND] Sending %zu bytes...\n", len); size_t before_enc = link->conns->total_encrypted; int ret = etcp_link_send(link->etcp, link, data, len); size_t after_enc = link->conns->total_encrypted; if (ret < 0) { fprintf(stderr, "[SEND] Failed (enc_errors=%zu)\n", link->conns->encrypt_errors); return -1; } if (after_enc > before_enc) { printf("[SEND] ✅ Sent and encrypted (%zu bytes)\n", len); } else { printf("[SEND] ⚠️ Sent without encryption (session not ready)\n"); } return 0; } // Receive and decrypt static int test_receive_decrypt(test_inst_t* inst, uint8_t* out_data, size_t* out_len) { struct sockaddr_in from_addr; socklen_t from_len = sizeof(from_addr); uint8_t recv_buffer[2048]; ssize_t received = recvfrom(inst->socket_fd, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr*)&from_addr, &from_len); if (received < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return 0; // No data } perror("[RECV] recvfrom"); return -1; } printf("[RECV] Received %zd bytes\n", received); // Check if encrypted (simple heuristic: encrypted starts with cmd byte then aes output) if (received > 20 && recv_buffer[0] == 0x02) { // cmd byte printf("[RECV] Looks like encrypted packet\n"); } // For now, just copy raw bytes (later will decrypt) memcpy(out_data, recv_buffer, received < 2048 ? received : 2047); *out_len = received; return 1; // Got data } int main(void) { printf("=== ETCP Link Encryption Test ===\n\n"); // Create instances test_inst_t* server = create_test_inst("SERVER", 0x1111111111111111ULL, SERVER_PRIV, SERVER_PUB, NULL, TEST_PORT_SERVER); test_inst_t* client = create_test_inst("CLIENT", 0x2222222222222222ULL, CLIENT_PRIV, CLIENT_PUB, SERVER_PUB, TEST_PORT_CLIENT); if (!server || !client) { fprintf(stderr, "Failed to create instances\n"); return 1; } // Create link from client to server struct ETCP_LINK* client_link = create_test_link(client, server, TEST_PORT_SERVER); if (!client_link) return 1; // Send test data printf("\n[TEST] Sending encrypted data...\n"); if (test_send_encrypted(client_link, (const uint8_t*)TEST_DATA, strlen(TEST_DATA)) < 0) { fprintf(stderr, "Send failed\n"); return 1; } // Server receives usleep(50000); uint8_t recv_buffer[2048]; size_t recv_len = 0; int ret = test_receive_decrypt(server, recv_buffer, &recv_len); if (ret > 0) { printf("[RECV] Server got %zu bytes\n", recv_len); printf(" First 20 bytes: "); for (int i = 0; i < 20 && i < recv_len; i++) printf("%02x ", recv_buffer[i]); printf("\n"); } // Check stats printf("\n=== Statistics ===\n"); size_t enc_err, dec_err, send_err, recv_err, total_enc, total_dec; etcp_connections_get_crypto_stats(server->conns, &enc_err, &dec_err, &send_err, &recv_err, &total_enc, &total_dec); printf("SERVER: enc=%zu, dec=%zu, err=(enc:%zu,dec:%zu,send:%zu,recv:%zu)\n", total_enc, total_dec, enc_err, dec_err, send_err, recv_err); etcp_connections_get_crypto_stats(client->conns, &enc_err, &dec_err, &send_err, &recv_err, &total_enc, &total_dec); printf("CLIENT: enc=%zu, dec=%zu, err=(enc:%zu,dec:%zu,send:%zu,recv:%zu)\n", total_enc, total_dec, enc_err, dec_err, send_err, recv_err); if (total_enc > 0) { printf("\n✅ SUCCESS: Data was encrypted and sent!\n"); } else { printf("\n❌ FAIL: No encryption happened\n"); } // Cleanup destroy_test_inst(server); destroy_test_inst(client); printf("\n=== Test completed ===\n"); return 0; }