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.
279 lines
9.7 KiB
279 lines
9.7 KiB
// test_etcp_crypto.c - Test ETCP encryption/decryption with secure channel |
|
#include "../src/secure_channel.h" |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <stdlib.h> |
|
#include <stdint.h> |
|
|
|
// Forward declaration for ETCP_CONN structure |
|
struct ETCP_CONN { |
|
struct ETCP_CONN* next; |
|
int mtu; |
|
uint8_t state; |
|
struct secure_channel crypto_ctx; |
|
uint64_t peer_node_id; |
|
void* input_queue; |
|
void* output_queue; |
|
void* rx_list; |
|
void* sent_list; |
|
uint16_t rtt_last; |
|
uint16_t rtt_avg_10; |
|
uint16_t rtt_avg_100; |
|
uint16_t jitter; |
|
uint16_t bandwidth; |
|
uint32_t bytes_sent_total; |
|
uint16_t last_sent_timestamp; |
|
uint32_t bytes_allowed; |
|
uint32_t retransmissions_count; |
|
uint32_t ack_packets_count; |
|
uint32_t control_packets_count; |
|
uint32_t total_packets_sent; |
|
uint32_t unique_packets_sent; |
|
uint32_t bytes_received_total; |
|
uint16_t next_tx_id; |
|
uint16_t last_sent_id; |
|
uint16_t last_rx_id; |
|
uint16_t last_delivered_id; |
|
void* next_tx_timer; |
|
void* retransmit_timer; |
|
uint16_t rtt_history[100]; |
|
uint8_t rtt_history_idx; |
|
uint8_t rtt_history_count; |
|
uint16_t pending_ack_ids[32]; |
|
uint16_t pending_ack_timestamps[32]; |
|
uint8_t pending_ack_count; |
|
uint16_t pending_retransmit_ids[32]; |
|
uint8_t pending_retransmit_count; |
|
uint32_t unacked_bytes; |
|
uint32_t window_size; |
|
uint16_t last_acked_id; |
|
uint16_t last_rx_ack_id; |
|
uint16_t retrans_timer_period; |
|
uint16_t next_retrans_time; |
|
uint8_t window_blocked; |
|
uint16_t oldest_missing_id; |
|
uint16_t missing_since_time; |
|
}; |
|
|
|
// Test configuration |
|
#define TEST_DATA "Hello, encrypted world!" |
|
#define TEST_DATA_LEN 23 |
|
|
|
// Simple test for secure channel encryption/decryption |
|
static int test_secure_channel_crypto(void) { |
|
printf("=== Testing Secure Channel Crypto ===\n"); |
|
|
|
// Create test keys |
|
struct SC_MYKEYS server_keys, client_keys; |
|
|
|
// Use fixed test keys |
|
for (int i = 0; i < SC_PRIVKEY_SIZE; i++) { |
|
server_keys.private_key[i] = i & 0xFF; |
|
client_keys.private_key[i] = (i + 128) & 0xFF; |
|
} |
|
|
|
// Generate corresponding public keys (simplified for test) |
|
for (int i = 0; i < SC_PUBKEY_SIZE; i++) { |
|
server_keys.public_key[i] = (i * 2) & 0xFF; |
|
client_keys.public_key[i] = (i * 2 + 1) & 0xFF; |
|
} |
|
|
|
// Initialize server context |
|
sc_context_t server_ctx; |
|
if (sc_init_ctx(&server_ctx, &server_keys) != SC_OK) { |
|
printf("ERROR: Failed to initialize server crypto context\n"); |
|
return -1; |
|
} |
|
printf("✓ Server crypto context initialized\n"); |
|
|
|
// Initialize client context |
|
sc_context_t client_ctx; |
|
if (sc_init_ctx(&client_ctx, &client_keys) != SC_OK) { |
|
printf("ERROR: Failed to initialize client crypto context\n"); |
|
return -1; |
|
} |
|
printf("✓ Client crypto context initialized\n"); |
|
|
|
// For this simple test, we'll manually set peer keys, session ready, and session key |
|
// to bypass the ECC key exchange which requires proper ECC initialization |
|
memcpy(client_ctx.peer_public_key, server_keys.public_key, SC_PUBKEY_SIZE); |
|
memcpy(server_ctx.peer_public_key, client_keys.public_key, SC_PUBKEY_SIZE); |
|
client_ctx.peer_key_set = 1; |
|
client_ctx.session_ready = 1; // This is crucial for encryption to work |
|
server_ctx.peer_key_set = 1; |
|
server_ctx.session_ready = 1; // This is crucial for encryption to work |
|
|
|
// Set test session keys manually (16 bytes for AES-128) |
|
// In a real implementation, this would be derived from ECDH shared secret |
|
uint8_t test_session_key[SC_SESSION_KEY_SIZE]; |
|
for (int i = 0; i < SC_SESSION_KEY_SIZE; i++) { |
|
test_session_key[i] = i + 100; |
|
} |
|
memcpy(client_ctx.session_key, test_session_key, SC_SESSION_KEY_SIZE); |
|
memcpy(server_ctx.session_key, test_session_key, SC_SESSION_KEY_SIZE); |
|
|
|
printf("✓ Peer public keys and session keys set manually\n"); |
|
|
|
// Test data |
|
uint8_t plaintext[] = TEST_DATA; |
|
uint8_t ciphertext[256]; |
|
uint8_t decrypted[256]; |
|
size_t ciphertext_len, decrypted_len; |
|
|
|
// Test encryption from client to server |
|
printf("\n=== Testing Client to Server Encryption ===\n"); |
|
if (sc_encrypt(&client_ctx, plaintext, TEST_DATA_LEN, ciphertext, &ciphertext_len) != SC_OK) { |
|
printf("ERROR: Encryption failed\n"); |
|
return -1; |
|
} |
|
printf("✓ Encrypted %zu bytes to %zu bytes\n", (size_t)TEST_DATA_LEN, ciphertext_len); |
|
|
|
// Test decryption by server |
|
if (sc_decrypt(&server_ctx, ciphertext, ciphertext_len, decrypted, &decrypted_len) != SC_OK) { |
|
printf("ERROR: Decryption failed\n"); |
|
return -1; |
|
} |
|
printf("✓ Decrypted %zu bytes\n", decrypted_len); |
|
|
|
// Verify decrypted data |
|
if (decrypted_len != TEST_DATA_LEN || memcmp(plaintext, decrypted, TEST_DATA_LEN) != 0) { |
|
printf("ERROR: Decrypted data doesn't match original\n"); |
|
printf(" Original: '%.*s'\n", TEST_DATA_LEN, plaintext); |
|
printf(" Decrypted: '%.*s'\n", (int)decrypted_len, decrypted); |
|
return -1; |
|
} |
|
printf("✓ Decrypted data matches original\n"); |
|
|
|
// Test encryption from server to client |
|
printf("\n=== Testing Server to Client Encryption ===\n"); |
|
if (sc_encrypt(&server_ctx, plaintext, TEST_DATA_LEN, ciphertext, &ciphertext_len) != SC_OK) { |
|
printf("ERROR: Server encryption failed\n"); |
|
return -1; |
|
} |
|
printf("✓ Server encrypted %zu bytes to %zu bytes\n", (size_t)TEST_DATA_LEN, ciphertext_len); |
|
|
|
if (sc_decrypt(&client_ctx, ciphertext, ciphertext_len, decrypted, &decrypted_len) != SC_OK) { |
|
printf("ERROR: Client decryption failed\n"); |
|
return -1; |
|
} |
|
printf("✓ Client decrypted %zu bytes\n", decrypted_len); |
|
|
|
if (decrypted_len != TEST_DATA_LEN || memcmp(plaintext, decrypted, TEST_DATA_LEN) != 0) { |
|
printf("ERROR: Client decrypted data doesn't match original\n"); |
|
return -1; |
|
} |
|
printf("✓ Client decrypted data matches original\n"); |
|
|
|
// Test with different data |
|
printf("\n=== Testing with Different Data ===\n"); |
|
uint8_t test_data2[] = "The quick brown fox jumps over the lazy dog"; |
|
size_t test_data2_len = sizeof(test_data2) - 1; |
|
|
|
if (sc_encrypt(&client_ctx, test_data2, test_data2_len, ciphertext, &ciphertext_len) != SC_OK) { |
|
printf("ERROR: Encryption of test data 2 failed\n"); |
|
return -1; |
|
} |
|
|
|
if (sc_decrypt(&server_ctx, ciphertext, ciphertext_len, decrypted, &decrypted_len) != SC_OK) { |
|
printf("ERROR: Decryption of test data 2 failed\n"); |
|
return -1; |
|
} |
|
|
|
if (decrypted_len != test_data2_len || memcmp(test_data2, decrypted, test_data2_len) != 0) { |
|
printf("ERROR: Test data 2 decryption mismatch\n"); |
|
return -1; |
|
} |
|
printf("✓ Different data test passed\n"); |
|
|
|
printf("\n=== All Crypto Tests Passed! ===\n"); |
|
return 0; |
|
} |
|
|
|
// Test ETCP connection crypto |
|
static int test_etcp_connection_crypto(void) { |
|
printf("\n=== Testing ETCP Connection Crypto ===\n"); |
|
|
|
// Create a simple ETCP connection |
|
struct ETCP_CONN* conn = calloc(1, sizeof(struct ETCP_CONN)); |
|
if (!conn) { |
|
printf("ERROR: Failed to allocate ETCP connection\n"); |
|
return -1; |
|
} |
|
|
|
// Initialize connection basic parameters |
|
conn->mtu = 1500; |
|
conn->state = 1; // initialized |
|
conn->peer_node_id = 0; // no peer yet |
|
|
|
// Create test keys |
|
struct SC_MYKEYS keys; |
|
for (int i = 0; i < SC_PRIVKEY_SIZE; i++) { |
|
keys.private_key[i] = i & 0xFF; |
|
keys.public_key[i] = (i + 64) & 0xFF; |
|
} |
|
|
|
// Initialize crypto context |
|
if (sc_init_ctx(&conn->crypto_ctx, &keys) != SC_OK) { |
|
printf("ERROR: Failed to initialize connection crypto\n"); |
|
free(conn); |
|
return -1; |
|
} |
|
printf("✓ ETCP connection crypto initialized\n"); |
|
|
|
// Test that we can use the crypto context for basic operations |
|
uint8_t test_data[] = "ETCP connection test"; |
|
uint8_t encrypted[256]; |
|
uint8_t decrypted[256]; |
|
size_t encrypted_len, decrypted_len; |
|
|
|
// Self-encryption test (set our own public key as peer and session key) |
|
memcpy(conn->crypto_ctx.peer_public_key, keys.public_key, SC_PUBKEY_SIZE); |
|
conn->crypto_ctx.peer_key_set = 1; |
|
conn->crypto_ctx.session_ready = 1; |
|
|
|
// Set test session key for self-encryption |
|
memcpy(conn->crypto_ctx.session_key, keys.public_key, SC_SESSION_KEY_SIZE); // Use public key as session key for test |
|
|
|
if (sc_encrypt(&conn->crypto_ctx, test_data, sizeof(test_data)-1, encrypted, &encrypted_len) != SC_OK) { |
|
printf("ERROR: Connection encryption failed\n"); |
|
free(conn); |
|
return -1; |
|
} |
|
printf("✓ Connection encryption works\n"); |
|
|
|
if (sc_decrypt(&conn->crypto_ctx, encrypted, encrypted_len, decrypted, &decrypted_len) != SC_OK) { |
|
printf("ERROR: Connection decryption failed\n"); |
|
free(conn); |
|
return -1; |
|
} |
|
|
|
if (decrypted_len != sizeof(test_data)-1 || memcmp(test_data, decrypted, sizeof(test_data)-1) != 0) { |
|
printf("ERROR: Connection decryption mismatch\n"); |
|
free(conn); |
|
return -1; |
|
} |
|
printf("✓ Connection decryption works\n"); |
|
|
|
free(conn); |
|
printf("✓ ETCP connection crypto test passed\n"); |
|
return 0; |
|
} |
|
|
|
int main(void) { |
|
printf("=== ETCP Crypto Test Suite ===\n"); |
|
|
|
int result1 = test_secure_channel_crypto(); |
|
if (result1 != 0) { |
|
printf("ERROR: Secure channel crypto test failed\n"); |
|
return 1; |
|
} |
|
|
|
int result2 = test_etcp_connection_crypto(); |
|
if (result2 != 0) { |
|
printf("ERROR: ETCP connection crypto test failed\n"); |
|
return 1; |
|
} |
|
|
|
printf("\n🎉 All crypto tests passed successfully!\n"); |
|
return 0; |
|
} |