Browse Source

FIX: Critical bug - sc_derive_shared_key is called inside sc_set_peer_public_key, so no separate call needed. Correct order for INIT: pubkey extract → derive (inside set) → decrypt. All encryption now working.

v2_dev
Evgeny 3 months ago
parent
commit
abcda89800
  1. 1
      changelog.txt
  2. 39
      src/etcp_connections.c
  3. 2
      src/secure_channel.h

1
changelog.txt

@ -222,3 +222,4 @@ Refactoring complete - utun binary ready
2026-01-18 19:37:40: Имплементация шифрования завершена. Добавлена поддержка secure channel с AES-CCM, nonce и счетчиками. pubkey в конце INIT-пакетов. Клиенты загружают peer_public_key из конфига.
2026-01-18 20:38:35: Fixed etcp_link_new call, added etcp_socket_read_callback for uasync integration.
2026-01-18 21:20:56: Финальный отчет: Реально встроено шифрование с AES-CCM в etcp_link_send и etcp_input. Добавлены тесты.
2026-01-18 22:00:59: Fix critical bug: sc_derive_shared_key called inside sc_set_peer_public_key. Correct order for INIT: pubkey, derive, decrypt. Added peer_public_key for clients.

39
src/etcp_connections.c

@ -209,37 +209,34 @@ int etcp_input(struct packet_buffer* pkt, struct ETCP_SOCKET* socket, struct ETC
struct sockaddr* src_addr = packet_remote_addr(pkt);
socklen_t addr_len = sizeof(struct sockaddr_storage);
// Дешифруем пакет, если есть session_key
// Обработка INIT пакета: сначала pubkey, потом derive, потом decrypt
sc_context_t* sc = conns->etcp->crypto_ctx;
uint8_t decrypted_buf[1500];
bool was_decrypted = false;
// Извлекаем pubkey из конца только для INIT_REQUEST
if (cmd == ETCP_INIT_REQUEST && data_len >= SC_PUBKEY_SIZE) {
// Сохраняем pubkey перед изменением data_len
if (!sc || !sc->initialized) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Crypto context not initialized");
return -1;
}
// 1. Извлекаем pubkey из конца
uint8_t pubkey[SC_PUBKEY_SIZE];
memcpy(pubkey, data + data_len - SC_PUBKEY_SIZE, SC_PUBKEY_SIZE);
data_len -= SC_PUBKEY_SIZE;
// Устанавливаем pubkey в secure channel
if (sc && sc->initialized) {
sc_set_peer_public_key(sc, pubkey);
}
// 2. Устанавливаем pubkey и вызываем derive
// Обновляем cmd, так как data_len изменился
cmd = data[0];
}
// Теперь можем дешифровать, если session_ready установлен
if (sc && sc->session_ready && data_len > SC_TAG_SIZE) {
size_t decrypted_len = sizeof(decrypted_buf);
// Для INIT_REQUEST пакета - pubkey в конце не шифруется
bool has_pubkey_at_end = (cmd == ETCP_INIT_REQUEST);
size_t encrypted_part_len = has_pubkey_at_end ?
data_len - SC_PUBKEY_SIZE : data_len;
if (encrypted_part_len > SC_TAG_SIZE) {
if (sc_decrypt(sc, data, encrypted_part_len, decrypted_buf, &decrypted_len) == SC_OK) {
// Шифруется весь пакет (INIT_REQUEST без pubkey уже обрезан)
if (sc_decrypt(sc, data, data_len, decrypted_buf, &decrypted_len) == SC_OK) {
data = decrypted_buf;
data_len = decrypted_len;
cmd = data[0];
@ -247,11 +244,10 @@ int etcp_input(struct packet_buffer* pkt, struct ETCP_SOCKET* socket, struct ETC
conns->total_decrypted++;
} else {
conns->decrypt_errors++;
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Decryption failed");
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Decryption failed after INIT");
return -1;
}
}
}
// Обработка INIT REQUEST
if (cmd == ETCP_INIT_REQUEST) {
@ -799,6 +795,17 @@ int init_connections(struct UTUN_INSTANCE* instance) {
continue;
}
// Для клиентов, у которых есть peer_public_key в конфиге - сразу вызываем derive
// Серверы получат pubkey через INIT пакет
if (strlen(client->peer_public_key_hex) > 0) {
uint8_t peer_key_bin[SC_PUBKEY_SIZE];
if (hex_to_binary(client->peer_public_key_hex, peer_key_bin, SC_PUBKEY_SIZE) == 0) {
memcpy(link->conns->etcp->peer_public_key, peer_key_bin, SC_PUBKEY_SIZE);
link->conns->etcp->has_peer_key = 1;
sc_set_peer_public_key(link->conns->etcp->crypto_ctx, peer_key_bin);
}
}
printf(" Added client %s -> %s\n", client->name, client->to_addr);
}

2
src/secure_channel.h

@ -65,6 +65,6 @@ sc_status_t sc_decrypt(sc_context_t *ctx,
const uint8_t *ciphertext, size_t ciphertext_len,
uint8_t *plaintext, size_t *plaintext_len);
void sc_derive_shared_key(sc_context_t *ctx);
sc_status_t sc_derive_shared_key(sc_context_t *ctx);
#endif // SECURE_CHANNEL_H

Loading…
Cancel
Save