From 6760a941e1cb88c768e9d51e3f5ee15c94e745ca Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sun, 18 Jan 2026 20:46:12 +0300 Subject: [PATCH] CRITICAL FIX: Actually implement encryption in etcp_link_send and decryption in etcp_input using sc_encrypt/sc_decrypt. --- src/etcp_connections.c | 84 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/src/etcp_connections.c b/src/etcp_connections.c index 90d1659..ae5ce6f 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -203,11 +203,57 @@ int etcp_input(struct packet_buffer* pkt, struct ETCP_SOCKET* socket, struct ETC if (pkt->metadata.data_len < 1) return -1; uint8_t* data = pkt->data; + size_t data_len = pkt->metadata.data_len; uint8_t cmd = data[0]; struct sockaddr* src_addr = packet_remote_addr(pkt); socklen_t addr_len = sizeof(struct sockaddr_storage); + // Дешифруем пакет, если есть session_key + sc_context_t* sc = conns->etcp->crypto_ctx; + uint8_t decrypted_buf[1500]; + bool was_decrypted = false; + + 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) { + data = decrypted_buf; + data_len = decrypted_len; + cmd = data[0]; + was_decrypted = true; + conns->total_decrypted++; + } else { + conns->decrypt_errors++; + DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Decryption failed"); + return -1; + } + } + } + + // Извлекаем pubkey из конца только для INIT_REQUEST + if (cmd == ETCP_INIT_REQUEST && data_len >= SC_PUBKEY_SIZE) { + // Сохраняем pubkey перед изменением data_len + 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); + } + + // Обновляем cmd, так как data_len изменился + cmd = data[0]; + } + + // Обработка INIT REQUEST if (cmd == ETCP_INIT_REQUEST) { if (pkt->metadata.data_len < 1 + 8 + SC_PUBKEY_SIZE + 2 + 2) { return -1; @@ -312,13 +358,45 @@ int etcp_link_init(struct ETCP_CONN* etcp, struct ETCP_LINK* link) { (void)etcp; } int etcp_link_send(struct ETCP_CONN* etcp, struct ETCP_LINK* link, - const uint8_t* data, size_t len) { + const uint8_t* data, size_t len) { if (!etcp || !link || !data || len == 0) return -1; link->last_activity = time(NULL); - return etcp_socket_send((struct ETCP_SOCKET*)link->socket, data, len, - (struct sockaddr*)&link->remote_addr); + sc_context_t* sc = etcp->crypto_ctx; + int fd = link->socket->fd; + + if (sc && sc->session_ready && len < 1400) { + uint8_t encrypted_buf[1500]; + size_t encrypted_len = sizeof(encrypted_buf); + + if (sc_encrypt(sc, data, len, encrypted_buf, &encrypted_len) == SC_OK) { + ssize_t sent = sendto(fd, encrypted_buf, encrypted_len, MSG_DONTWAIT, + (struct sockaddr*)&link->remote_addr, + link->remote_addr_len); + + if (sent < 0) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + link->conns->send_errors++; + DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "sendto failed: %s", strerror(errno)); + } + return -1; + } + + link->conns->total_encrypted++; + return 0; + } else { + link->conns->encrypt_errors++; + DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Encryption failed"); + return -1; + } + } + + ssize_t sent = sendto(fd, data, len, MSG_DONTWAIT, + (struct sockaddr*)&link->remote_addr, + link->remote_addr_len); + + return (sent >= 0) ? 0 : -1; } int etcp_link_send_init(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval) {