e2e: AES-128-CCM encryption via BGP router (ROUTER_FLAG_ENCRYPTED), ECDH key per peer-pair from NODEINFO pubkeys, cache 8 entries

- etcp_router.h/c: new flag ROUTER_FLAG_ENCRYPTED (0x04), etcp_route_send_encrypted(), inflight/retrans/send_q support
- utun_instance.h: e2e_ctx_cache[8] — per-peer sc_context_t cache with derived session key
- topo_node.c: topo_node_sign_self() — single point for Ed25519 self-signing of NODEINFO
- topo_node.c: fix stale x25519_self_sig after address update (topo_node_sign_self call)
- nat_detection.c: fix stale x25519_self_sig after in-place socket meta modification
- test_etcp_router_unit: 5 E2E tests (basic round-trip, no NODEINFO drop, tampered, cache reuse, ENCRYPTED+SIGNED combined)
- builds clean, 70/70 tests pass
This commit is contained in:
evgeny committed 2026-08-09 08:19:20 +03:00
1 parent ca176e1f24
commit b2e4aadbf0
44 files changed
+2586 -145

No files matched your search

+12 -1
View File
@@ -271,7 +271,7 @@ int DbManager::getChannelMemberCount(const QString& chId) const {
QList<ChannelMember> DbManager::getChannelMembers(const QString& chId, int offset, int limit) const {
QList<ChannelMember> list;
QString sql = QStringLiteral(
"SELECT p.node_id, COALESCE(n.online,0), COALESCE(n.name,''), COALESCE(p.local_nick,'')"
"SELECT p.node_id, COALESCE(n.online,0), COALESCE(n.name,''), COALESCE(p.local_nick,''), COALESCE(p.adm_tags,'')"
" FROM \"%1\" p LEFT JOIN nodes n ON p.node_id=n.node_id"
" ORDER BY n.online DESC, p.node_id ASC LIMIT ? OFFSET ?"
).arg(peersTableName(chId));
@@ -285,6 +285,17 @@ QList<ChannelMember> DbManager::getChannelMembers(const QString& chId, int offse
m.online = sqlite3_column_int(stmt, 1) != 0;
m.name = colText(stmt, 2);
m.localNick = colText(stmt, 3);
m.admTags = colText(stmt, 4);
m.flags = 0;
const QByteArray at = m.admTags.toUtf8();
const char* tags = at.constData();
if (tags && tags[0]) {
if (strstr(tags, "\"supernode\":\"yes\"")) m.flags |= 0x01;
const char* ap = strstr(tags, "\"admin\":\"");
if (ap) { ap += 8; const char* last = ap; while (*last && *last != '"') { if (*last == 'e' || *last == 'd') ap = last; last++; } if (*ap == 'e') m.flags |= 0x02; }
const char* mp = strstr(tags, "\"moder\":\"");
if (mp) { mp += 8; const char* last = mp; while (*last && *last != '"') { if (*last == 'e' || *last == 'd') mp = last; last++; } if (*mp == 'e') m.flags |= 0x04; }
}
list.append(m);
}
sqlite3_finalize(stmt);