android: voice messages + attachments architecture plan, build fixes

This commit is contained in:
evgeny committed 2026-07-28 23:07:23 +03:00
1 parent f8d7c21a79
commit e751e6ee69
17 files changed
+299 -329

No files matched your search

+29 -2
View File
@@ -226,6 +226,27 @@ static struct ETCP_CONN* cs_find_conn_for_node(struct UTUN_INSTANCE* inst, uint6
return NULL;
}
/* ── helper: find active ETCP_CONN by pubkey (for invite: same physical node, different node_id) ── */
static struct ETCP_CONN* cs_find_conn_by_pubkey(struct UTUN_INSTANCE* inst,
const uint8_t* pubkey_bin,
uint64_t* out_node_id) {
struct ll_entry* entry = inst->connections ? inst->connections->head : NULL;
while (entry) {
struct conn_queue_entry* ce = (struct conn_queue_entry*)entry->data;
struct ETCP_CONN* conn = ce->conn;
if (conn && conn->initialized && conn->links_up
&& memcmp(conn->crypto_ctx.peer_public_key, pubkey_bin, 32) == 0) {
*out_node_id = conn->peer_node_id;
DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "%s: find_conn_by_pubkey MATCH conn=%s peer=0x%016llx",
CS_ID, conn->log_name, (unsigned long long)conn->peer_node_id);
return conn;
}
entry = entry->next;
}
return NULL;
}
/* ── helper: check if peer has active ETCP link ── */
static int cs_is_peer_online(struct UTUN_INSTANCE* inst, uint64_t peer_id) {
@@ -642,11 +663,17 @@ static void cm_invite_trampoline(void* arg) {
}
struct ETCP_CONN* existing = instance_find_conn(inst, node_id);
if (!existing) existing = cs_find_conn_by_pubkey(inst, inv->pubkey, &node_id);
if (existing) {
if (existing->links_up) {
DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "%s: invite conn already UP node=0x%016llx, reusing", CS_ID, (unsigned long long)node_id);
if (g_cs && g_cs->pending_invite_ch_id != 0 && !g_cs->info_req_timer)
if (g_cs && g_cs->pending_invite_ch_id != 0 && !g_cs->info_req_timer) {
if (node_id != existing->peer_node_id)
DEBUG_WARN(DEBUG_CATEGORY_DB_SYNC,
"%s: invite node_id mismatch: derived=%016llx ETCP=%016llx — using ETCP",
CS_ID, (unsigned long long)node_id, (unsigned long long)existing->peer_node_id);
cs_on_conn_up(existing, NULL);
}
} else {
DEBUG_INFO(DEBUG_CATEGORY_DB_SYNC, "%s: invite conn in progress node=0x%016llx, waiting UP", CS_ID, (unsigned long long)node_id);
}
+3 -6
View File
@@ -10,7 +10,7 @@
#include "../../lib/debug_config.h"
#include "../../lib/mem.h"
#include "../../lib/u_async.h"
#include "../../lib/sha256.h"
#include <openssl/sha.h>
#include "../../lib/sqlite3.h"
#include "../../lib/platform_compat.h"
#include <string.h>
@@ -131,10 +131,7 @@ static void db_sqlite_close(struct DB_SYNC* db)
static void db_sha256(const uint8_t* data, size_t len, uint8_t hash[32])
{
SC_SHA256_CTX ctx;
sc_sha256_init(&ctx);
sc_sha256_update(&ctx, data, len);
sc_sha256_final(&ctx, hash);
SHA256(data, len, hash);
}
static uint64_t db_hash64(const uint8_t* data, size_t len)
@@ -1220,7 +1217,7 @@ static void db_sync_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
const char* tbl = (const char*)sqlite3_column_text(st, 0);
const char* ch_id = (const char*)sqlite3_column_text(st, 1);
if (!ch_id || !ch_id[0]) continue;
uint64_t h; { uint8_t sh[32]; SC_SHA256_CTX ctx; sc_sha256_init(&ctx); sc_sha256_update(&ctx, (const uint8_t*)ch_id, strlen(ch_id)); sc_sha256_final(&ctx, sh); memcpy(&h, sh, 8); }
uint64_t h; { uint8_t sh[32]; SHA256((const uint8_t*)ch_id, strlen(ch_id), sh); memcpy(&h, sh, 8); }
if (h == hash) {
si = db_sync_instance_add(db->inst, tbl, hash, 1);
if (si) { si_peer_add(si, src); }
+23 -27
View File
@@ -17,7 +17,6 @@
#include <stdio.h>
#include <fcntl.h>
#include "crc32.h"
#include "../lib/sha256.h"
#include <openssl/evp.h>
#include <openssl/sha.h>
@@ -99,29 +98,29 @@ static sc_status_t verify_and_strip_crc32(uint8_t *plaintext_with_crc, size_t to
}
static void sc_derive_session_key(const uint8_t *shared_secret, uint8_t *session_key) {
SC_SHA256_CTX sha_ctx;
SHA256_CTX sha_ctx;
uint8_t hash[SC_HASH_SIZE];
sc_sha256_init(&sha_ctx);
sc_sha256_update(&sha_ctx, shared_secret, SC_SHARED_SECRET_SIZE);
sc_sha256_update(&sha_ctx, (const uint8_t *)"uTun-v3-session", 15);
sc_sha256_final(&sha_ctx, hash);
SHA256_Init(&sha_ctx);
SHA256_Update(&sha_ctx, shared_secret, SC_SHARED_SECRET_SIZE);
SHA256_Update(&sha_ctx, (const uint8_t *)"uTun-v3-session", 15);
SHA256_Final(hash, &sha_ctx);
memcpy(session_key, hash, SC_SESSION_KEY_SIZE);
}
// Derive 12-byte nonce for stream cipher from session key + stream_id
static void sc_stream_derive_nonce(const uint8_t *session_key, uint32_t stream_id, uint8_t *nonce_out) {
SC_SHA256_CTX sha_ctx;
SHA256_CTX sha_ctx;
uint8_t hash[SC_HASH_SIZE];
uint8_t stream_id_le[4];
stream_id_le[0] = (uint8_t)(stream_id >> 0);
stream_id_le[1] = (uint8_t)(stream_id >> 8);
stream_id_le[2] = (uint8_t)(stream_id >> 16);
stream_id_le[3] = (uint8_t)(stream_id >> 24);
sc_sha256_init(&sha_ctx);
sc_sha256_update(&sha_ctx, session_key, SC_SESSION_KEY_SIZE);
sc_sha256_update(&sha_ctx, stream_id_le, sizeof(stream_id_le));
sc_sha256_update(&sha_ctx, (const uint8_t *)"uTun3-stream", 12);
sc_sha256_final(&sha_ctx, hash);
SHA256_Init(&sha_ctx);
SHA256_Update(&sha_ctx, session_key, SC_SESSION_KEY_SIZE);
SHA256_Update(&sha_ctx, stream_id_le, sizeof(stream_id_le));
SHA256_Update(&sha_ctx, (const uint8_t *)"uTun3-stream", 12);
SHA256_Final(hash, &sha_ctx);
memcpy(nonce_out, hash, SC_STREAM_NONCE_SIZE);
}
@@ -424,8 +423,8 @@ sc_status_t sc_derive_ed25519_pubkey(const uint8_t *x25519_privkey, uint8_t *ed2
uint64_t sc_derive_node_id_from_pubkey(const uint8_t *public_key) {
if (!public_key) { DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "sc_derive_node_id_from_pubkey: NULL public_key"); return 0; }
uint8_t sha_hash[SC_HASH_SIZE]; SC_SHA256_CTX ctx;
sc_sha256_init(&ctx); sc_sha256_update(&ctx, public_key, SC_PUBKEY_SIZE); sc_sha256_final(&ctx, sha_hash);
uint8_t sha_hash[SC_HASH_SIZE];
SHA256(public_key, SC_PUBKEY_SIZE, sha_hash);
uint64_t node_id;
memcpy(&node_id, sha_hash, 8);
node_id &= 0x7FFFFFFFFFFFFFFFULL;
@@ -572,10 +571,7 @@ sc_status_t sc_ed25519_verify(const uint8_t pubkey[32], const uint8_t* msg, size
sc_status_t sc_sha_transcode(const uint8_t *key, size_t key_len, uint8_t *data, size_t data_len) {
if (!key || !data || key_len == 0 || data_len == 0) return SC_ERR_INVALID_ARG;
uint8_t sha_hash[SC_HASH_SIZE];
SC_SHA256_CTX ctx;
sc_sha256_init(&ctx);
sc_sha256_update(&ctx, key, key_len);
sc_sha256_final(&ctx, sha_hash);
SHA256(key, key_len, sha_hash);
for (size_t i = 0; i < data_len; i++) data[i] ^= sha_hash[i % SC_HASH_SIZE];
return SC_OK;
}
@@ -583,15 +579,15 @@ sc_status_t sc_sha_transcode(const uint8_t *key, size_t key_len, uint8_t *data,
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 sha[SC_HASH_SIZE*2];
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, sha);
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, sha+SC_HASH_SIZE);
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, salt, SC_PUBKEY_ENC_SALT_SIZE);
SHA256_Update(&ctx, peer_pubkey, SC_PUBKEY_SIZE);
SHA256_Final(sha, &ctx);
SHA256_Init(&ctx);
SHA256_Update(&ctx, peer_pubkey, SC_PUBKEY_SIZE);
SHA256_Update(&ctx, salt, SC_PUBKEY_ENC_SALT_SIZE);
SHA256_Final(sha + SC_HASH_SIZE, &ctx);
for (size_t i = 0; i < SC_PUBKEY_SIZE; i++) output[i] = pubkey[i] ^ sha[i];
return SC_OK;
}
+15 -7
View File
@@ -21,7 +21,6 @@
#include "../lib/u_async.h"
#include "../lib/debug_config.h"
#include "../lib/sha256.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -101,12 +100,21 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
return -1;
}
// Derive node_id from pubkey if not set in config
if (!instance->node_id) {
uint8_t pubkey[SC_PUBKEY_SIZE];
sc_compute_public_key_from_private(instance->my_keys.private_key, pubkey);
instance->node_id = sc_derive_node_id_from_pubkey(pubkey);
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "node_id derived from pubkey: %016llx", (unsigned long long)instance->node_id);
/* Always verify node_id matches pubkey, fix if mismatched */
{
uint8_t pub_bin[SC_PUBKEY_SIZE];
sc_compute_public_key_from_private(instance->my_keys.private_key, pub_bin);
uint64_t derived = sc_derive_node_id_from_pubkey(pub_bin);
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "node_id check: config=%016llx derived=%016llx match=%d",
(unsigned long long)instance->node_id, (unsigned long long)derived,
(instance->node_id == derived));
if (!instance->node_id || instance->node_id != derived) {
if (instance->node_id)
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "node_id mismatch: config=%016llx derived=%016llx — fixing",
(unsigned long long)instance->node_id, (unsigned long long)derived);
instance->node_id = derived;
config->global.my_node_id = derived;
}
}
if (sc_derive_ed25519_pubkey(instance->my_keys.private_key, instance->my_ed25519_pubkey) != SC_OK) {