Browse Source

obf

nodeinfo-routing-update
jeka 1 month ago
parent
commit
783f229711
  1. 31
      src/etcp_connections.c
  2. 3
      src/routing.c
  3. 30
      src/secure_channel.c
  4. 7
      src/secure_channel.h
  5. 26
      src/tun_if.c
  6. 12
      src/tun_if.h
  7. 27
      src/tun_windows.c
  8. 2
      tests/Makefile.am

31
src/etcp_connections.c

@ -54,7 +54,7 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) {
}
dgram->link = link;
dgram->noencrypt_len = SC_PUBKEY_SIZE;
dgram->noencrypt_len = SC_PUBKEY_ENC_SIZE;
size_t offset = 0;
// reset=1: ETCP_INIT_REQUEST (0x02), reset=0: ETCP_INIT_REQUEST_NOINIT (0x04)
@ -78,10 +78,18 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) {
dgram->data[offset++] = link->local_link_id;
memcpy(dgram->data + offset, link->etcp->instance->my_keys.public_key, SC_PUBKEY_SIZE);
// Шифруем public_key inplace используя собственный ключ
sc_sha_transcode(link->etcp->crypto_ctx.peer_public_key, SC_PUBKEY_SIZE, dgram->data + offset, SC_PUBKEY_SIZE);
dgram->data_len = offset + SC_PUBKEY_SIZE;
uint8_t salt[SC_PUBKEY_ENC_SALT_SIZE];
random_bytes(salt, sizeof(salt));
memcpy(dgram->data + offset, salt, SC_PUBKEY_ENC_SALT_SIZE);
offset += SC_PUBKEY_ENC_SALT_SIZE;
uint8_t obfuscated_pubkey[SC_PUBKEY_SIZE];
sc_obfuscate_pubkey(salt, link->etcp->crypto_ctx.peer_public_key,
link->etcp->instance->my_keys.public_key, obfuscated_pubkey);
memcpy(dgram->data + offset, obfuscated_pubkey, SC_PUBKEY_SIZE);
offset += SC_PUBKEY_SIZE;
dgram->data_len = offset;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Sending INIT request to link, node_id=%llu, retry=%d", (unsigned long long)node_id, link->init_retry_count);
@ -800,7 +808,7 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
// Try INIT decryption (for incoming connection requests)
// This handles: no link found, or link without session, or normal decrypt failed
if (recv_len<=SC_PUBKEY_SIZE) {
if (recv_len <= SC_PUBKEY_ENC_SIZE) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: packet too small for init, size=%zd", recv_len);
errorcode=1;
goto ec_fr;
@ -809,15 +817,18 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
struct secure_channel sc;
sc_init_ctx(&sc, &e_sock->instance->my_keys);
// Расшифровываем public_key inplace используя собственный ключ
sc_sha_transcode(e_sock->instance->my_keys.public_key, SC_PUBKEY_SIZE, data + recv_len - SC_PUBKEY_SIZE, SC_PUBKEY_SIZE);
const uint8_t* salt = data + recv_len - SC_PUBKEY_ENC_SIZE;
const uint8_t* encrypted_pubkey = salt + SC_PUBKEY_ENC_SALT_SIZE;
uint8_t decrypted_pubkey[SC_PUBKEY_SIZE];
sc_obfuscate_pubkey(salt, e_sock->instance->my_keys.public_key, encrypted_pubkey, decrypted_pubkey);
if (sc_set_peer_public_key(&sc, &data[recv_len-SC_PUBKEY_SIZE], SC_PEER_PUBKEY_BIN)!=SC_OK) {
if (sc_set_peer_public_key(&sc, decrypted_pubkey, SC_PEER_PUBKEY_BIN)!=SC_OK) {
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to set peer public key during init");
errorcode=2;
goto ec_fr;
}
if (sc_decrypt(&sc, data, recv_len-SC_PUBKEY_SIZE, (uint8_t*)&pkt->timestamp, &pkt_len)) {
if (sc_decrypt(&sc, data, recv_len - SC_PUBKEY_ENC_SIZE, (uint8_t*)&pkt->timestamp, &pkt_len)) {
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "etcp_connections_read_callback: failed to decrypt init packet");
errorcode=3;
goto ec_fr;

3
src/routing.c

@ -3,6 +3,7 @@
#include "routing.h"
#include "route_lib.h"
#include "tun_if.h"
#include "packet_dump.h"
#include "etcp.h"
#include "etcp_api.h"
#include "pkt_normalizer.h"
@ -162,6 +163,8 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_data_get(instance->tun->output_queue);
while (pkt) {
if (pkt->ll.dgram && pkt->ll.len > 0) {
// Дамп пакета из TUN
dump_ip_packet("TUN->routing", (const uint8_t*)pkt->ll.dgram, pkt->ll.len);
// Extract destination IP for routing
uint32_t dst_ip = extract_dst_ip(pkt->ll.dgram, pkt->ll.len);
if (dst_ip == 0) {

30
src/secure_channel.c

@ -808,7 +808,7 @@ sc_status_t sc_sha_transcode(const uint8_t *key, size_t key_len, uint8_t *data,
return SC_ERR_INVALID_ARG;
}
uint8_t sha_hash[SC_SHA256_BLOCK_SIZE];
uint8_t sha_hash[SC_HASH_SIZE];
SC_SHA256_CTX ctx;
sc_sha256_init(&ctx);
@ -816,8 +816,34 @@ sc_status_t sc_sha_transcode(const uint8_t *key, size_t key_len, uint8_t *data,
sc_sha256_final(&ctx, sha_hash);
for (size_t i = 0; i < data_len; i++) {
data[i] ^= sha_hash[i % SC_SHA256_BLOCK_SIZE];
data[i] ^= sha_hash[i % SC_HASH_SIZE];
}
return SC_OK;
}
sc_status_t sc_obfuscate_pubkey(const uint8_t *salt, const uint8_t *peer_pubkey, const uint8_t *pubkey, uint8_t *output) {
if (!salt || !peer_pubkey || !pubkey || !output) {
return SC_ERR_INVALID_ARG;
}
uint8_t sha1[SC_HASH_SIZE];
uint8_t sha2[SC_HASH_SIZE];
SC_SHA256_CTX ctx;
sc_sha256_init(&ctx);
sc_sha256_update(&ctx, salt, SC_PUBKEY_ENC_SALT_SIZE);
sc_sha256_update(&ctx, peer_pubkey, SC_PUBKEY_SIZE);
sc_sha256_final(&ctx, sha1);
sc_sha256_init(&ctx);
sc_sha256_update(&ctx, peer_pubkey, SC_PUBKEY_SIZE);
sc_sha256_update(&ctx, salt, SC_PUBKEY_ENC_SALT_SIZE);
sc_sha256_final(&ctx, sha2);
for (size_t i = 0; i < SC_PUBKEY_SIZE; i++) {
output[i] = pubkey[i] ^ sha1[i] ^ sha2[i];
}
return SC_OK;
}

7
src/secure_channel.h

@ -15,6 +15,10 @@
#define SC_TAG_SIZE 8
#define SC_CRC32_SIZE 4
// Шифрование pubkey при передаче (salt + double SHA256 XOR)
#define SC_PUBKEY_ENC_SALT_SIZE 8
#define SC_PUBKEY_ENC_SIZE (SC_PUBKEY_SIZE + SC_PUBKEY_ENC_SALT_SIZE)
// Коды возврата
#define SC_OK 0
#define SC_ERR_INVALID_ARG -1
@ -68,4 +72,7 @@ sc_status_t sc_decrypt(sc_context_t *ctx, const uint8_t *ciphertext, size_t ciph
// SHA256-based transcode: XOR data with SHA256(key)
sc_status_t sc_sha_transcode(const uint8_t *key, size_t key_len, uint8_t *data, size_t data_len);
// Obfuscate pubkey при передаче: XOR с SHA256(salt+peer_pubkey) || SHA256(peer_pubkey+salt)
sc_status_t sc_obfuscate_pubkey(const uint8_t *salt, const uint8_t *peer_pubkey, const uint8_t *pubkey, uint8_t *output);
#endif // SECURE_CHANNEL_H

26
src/tun_if.c

@ -267,6 +267,32 @@ struct ll_queue* tun_get_input_queue(struct tun_if* tun) { return tun ? tun->in
struct ll_queue* tun_get_output_queue(struct tun_if* tun) { return tun ? tun->output_queue : NULL; }
int tun_is_test_mode(struct tun_if* tun) { return tun ? tun->test_mode : -1; }
// ===================================================================
// Callback для обработки пакетов из TUN в main thread
// Вызывается через uasync_post из read thread (Windows)
// ===================================================================
void tun_packet_handler(void* arg) {
struct tun_packet_data* pd = (struct tun_packet_data*)arg;
if (!pd || !pd->tun || !pd->entry) {
if (pd) free(pd);
return;
}
struct tun_if* tun = pd->tun;
struct ll_entry* entry = pd->entry;
// Освободить временную структуру
free(pd);
// Положить в очередь (уже в main thread)
int ok = queue_data_put(tun->output_queue, entry, 0);
if (ok != 0) {
queue_entry_free(entry);
tun->read_errors++;
}
// Статистика уже обновлена в read thread
}
int tun_inject_packet(struct tun_if* tun, const uint8_t* buf, size_t len)
{
if (!tun || !buf || len == 0 || len > TUN_MAX_PACKET_SIZE) return -1;

12
src/tun_if.h

@ -14,9 +14,16 @@
struct UASYNC;
struct utun_config;
struct ll_queue;
struct ll_entry;
struct memory_pool;
struct ETCP_FRAGMENT; // используется внутри, определён в etcp.h
// Структура для передачи данных из TUN потока в main thread
struct tun_packet_data {
struct tun_if* tun;
struct ll_entry* entry;
};
#ifdef __cplusplus
extern "C" {
#endif
@ -104,6 +111,11 @@ int tun_inject_packet(struct tun_if* tun, const uint8_t* buf, size_t len);
*/
ssize_t tun_read_packet(struct tun_if* tun, uint8_t* buf, size_t len);
/**
* @brief Callback для обработки пакетов из TUN в main thread (через uasync_post)
*/
void tun_packet_handler(void* arg);
// ===================================================================
// Platform-specific internal functions
// (реализованы в tun_linux.c / tun_windows.c)

27
src/tun_windows.c

@ -278,23 +278,26 @@ DWORD WINAPI tun_read_thread_proc(LPVOID arg)
pkt->ll.dgram = data;
pkt->ll.len = n;
EnterCriticalSection(&tun->output_queue_lock);
int ok = queue_data_put(tun->output_queue, (struct ll_entry*)pkt, 0);
LeaveCriticalSection(&tun->output_queue_lock);
if (ok != 0) {
// Создать структуру для передачи в main thread
struct tun_packet_data* pd = malloc(sizeof(*pd));
if (!pd) {
free(data);
memory_pool_free(tun->pool, pkt);
tun->read_errors++;
} else {
tun->bytes_read += n;
tun->packets_read++;
dump_ip_packet("TUN->", buf, n);
continue;
}
}
pd->tun = tun;
pd->entry = (struct ll_entry*)pkt;
// Статистика
tun->bytes_read += n;
tun->packets_read++;
// Дамп пакета
dump_ip_packet("TUN->", buf, n);
if (got_packet) {
uasync_post(tun->ua, tun_output_notify, tun);
// Передать данные в main thread через uasync_post
uasync_post(tun->ua, tun_packet_handler, pd);
}
}
return 0;

2
tests/Makefile.am

@ -138,7 +138,7 @@ test_pkt_normalizer_etcp_LDADD = $(ETCP_FULL_OBJS) $(SECURE_CHANNEL_OBJS) $(CRYP
test_pkt_normalizer_standalone_SOURCES = test_pkt_normalizer_standalone.c
test_pkt_normalizer_standalone_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
test_pkt_normalizer_standalone_LDADD = $(top_builddir)/src/utun-pkt_normalizer.o $(top_builddir)/src/utun-route_lib.o $(top_builddir)/src/utun-routing.o $(top_builddir)/src/utun-etcp_api.o $(TINYCRYPT_OBJS) $(COMMON_LIBS)
test_pkt_normalizer_standalone_LDADD = $(top_builddir)/src/utun-pkt_normalizer.o $(top_builddir)/src/utun-route_lib.o $(top_builddir)/src/utun-routing.o $(top_builddir)/src/utun-packet_dump.o $(top_builddir)/src/utun-etcp_api.o $(TINYCRYPT_OBJS) $(COMMON_LIBS)
test_etcp_api_SOURCES = test_etcp_api.c
test_etcp_api_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source

Loading…
Cancel
Save