refactor(protocol): remove legacy meshcore direct secret fallback

This commit is contained in:
liu weikai committed 2026-06-14 06:10:07 +08:00
1 parent 1f3c86122f
commit 0b5bb6cea3
6 files changed
+15 -81

No files matched your search

+3 -1
View File
@@ -304,13 +304,15 @@ Current state:
- Confirmed platform gap, now documented in fine-grained capabilities.
- ESP32 direct text/app-data sends now use `MeshCoreDirectRoutePolicy` for the shared decision table:
missing peer pubkey -> discover/fail, selected route -> direct route path, no selected route -> flood,
and preferred-channel secret derivation may fall back to the requested channel.
and route/channel fallback remains explicit without redefining direct-secret material.
- Incoming MeshCore discover request/response decisions now run through `MeshCoreRuntime`: request filter/since
matching emits `SendDiscoverResponseEffect`, and responses emit `PublishNodeInfoEffect` plus
`UpdatePeerRouteEffect`.
- MeshCore direct shared-secret expansion and nRF peer-key derivation now use `MeshCoreDirectSecretCore`;
ESP32 keeps identity storage and peer pubkey lookup in the adapter, then delegates key expansion to the
shared helper.
- ESP32 no longer accepts the historical group-secret-derived direct key fallback; MeshCore direct secrets are
identity/pubkey-derived only.
Residual risk:
@@ -369,13 +369,15 @@ Current C++17 migration state:
- Direct-route send decision for ESP32 MeshCore direct text/app-data now uses shared
`MeshCoreDirectRoutePolicy`: missing peer pubkey triggers discover/failure, selected routes use direct path,
and direct secret derivation may fall back from preferred route channel to requested channel.
and route/channel fallback remains explicit without redefining direct-secret material.
- Incoming MeshCore discover request/response control payloads now flow through `MeshCoreRuntime`: filter/since
matching emits `SendDiscoverResponseEffect`, and discover responses emit `PublishNodeInfoEffect` plus
`UpdatePeerRouteEffect`.
- MeshCore identity shared-secret expansion and nRF peer-key derivation now use shared
`MeshCoreDirectSecretCore`; ESP32 still owns private-key storage and route pubkey lookup before delegating
key expansion to the runtime helper.
- ESP32 no longer falls back to the historical group-secret-derived direct key; MeshCore direct secrets are
identity/pubkey-derived only.
- Peer route storage, pubkey persistence, private identity storage, response scheduling, and frame transmission
are still platform adapter responsibilities until they can be represented as runtime state/effects.
@@ -34,9 +34,6 @@ struct MeshCoreDirectRouteDecision
MeshCoreDirectRouteStatus status = MeshCoreDirectRouteStatus::Ready;
MeshCoreRouteMode route_mode = MeshCoreRouteMode::Flood;
ChannelId tx_channel = ChannelId::PRIMARY;
ChannelId primary_secret_channel = ChannelId::PRIMARY;
ChannelId fallback_secret_channel = ChannelId::PRIMARY;
bool allow_secret_fallback = false;
bool should_discover = false;
};
@@ -45,8 +42,6 @@ inline MeshCoreDirectRouteDecision resolveMeshCoreDirectRoutePolicy(
{
MeshCoreDirectRouteDecision decision{};
decision.tx_channel = facts.requested_channel;
decision.primary_secret_channel = facts.requested_channel;
decision.fallback_secret_channel = facts.requested_channel;
if (facts.identity_ready && (!facts.has_peer_route || !facts.peer_has_public_key))
{
@@ -59,9 +54,6 @@ inline MeshCoreDirectRouteDecision resolveMeshCoreDirectRoutePolicy(
{
decision.route_mode = MeshCoreRouteMode::Direct;
decision.tx_channel = facts.selected_route_channel;
decision.primary_secret_channel = facts.selected_route_channel;
decision.fallback_secret_channel = facts.requested_channel;
decision.allow_secret_fallback = facts.selected_route_channel != facts.requested_channel;
}
return decision;
@@ -26,8 +26,6 @@ int main()
assert(decision.status == chat::runtime::MeshCoreDirectRouteStatus::Ready);
assert(decision.route_mode == chat::runtime::MeshCoreRouteMode::Flood);
assert(decision.tx_channel == chat::ChannelId::SECONDARY);
assert(decision.primary_secret_channel == chat::ChannelId::SECONDARY);
assert(!decision.allow_secret_fallback);
}
{
@@ -43,9 +41,6 @@ int main()
assert(decision.status == chat::runtime::MeshCoreDirectRouteStatus::Ready);
assert(decision.route_mode == chat::runtime::MeshCoreRouteMode::Direct);
assert(decision.tx_channel == chat::ChannelId::SECONDARY);
assert(decision.primary_secret_channel == chat::ChannelId::SECONDARY);
assert(decision.fallback_secret_channel == chat::ChannelId::PRIMARY);
assert(decision.allow_secret_fallback);
}
return 0;
@@ -339,8 +339,6 @@ class MeshCoreAdapter : public IMeshAdapter, public IMeshCoreBleBackend
bool resolveGroupSecret(ChannelId channel, uint8_t out_key16[16],
uint8_t out_key32[32], uint8_t* out_hash) const;
ChannelId resolveChannelFromHash(uint8_t channel_hash, bool* out_match) const;
bool deriveLegacyDirectSecret(ChannelId channel, uint8_t peer_hash,
uint8_t out_key16[16], uint8_t out_key32[32]) const;
bool deriveIdentitySecret(uint8_t peer_hash, uint8_t out_key16[16],
uint8_t out_key32[32]) const;
bool deriveDirectSecret(ChannelId channel, uint8_t peer_hash,
@@ -164,7 +164,6 @@ using chat::meshcore::ParsedPacket;
using chat::meshcore::parsePacket;
using chat::meshcore::saturatingAddU32;
using chat::meshcore::scoreFromSnr;
using chat::meshcore::sha256Trunc;
using chat::meshcore::toHex;
using chat::meshcore::toHmacKey32;
@@ -1481,39 +1480,11 @@ bool MeshCoreAdapter::deriveIdentitySecret(uint8_t peer_hash,
out_key32, 32);
}
bool MeshCoreAdapter::deriveLegacyDirectSecret(ChannelId channel, uint8_t peer_hash,
uint8_t out_key16[16], uint8_t out_key32[32]) const
{
if (!out_key16 || !out_key32)
{
return false;
}
uint8_t base_key16[16];
uint8_t base_key32[32];
if (!resolveGroupSecret(channel, base_key16, base_key32, nullptr))
{
return false;
}
uint8_t material[18];
memcpy(material, base_key16, sizeof(base_key16));
material[16] = (peer_hash < self_hash_) ? peer_hash : self_hash_;
material[17] = (peer_hash < self_hash_) ? self_hash_ : peer_hash;
sha256Trunc(out_key32, 32, material, sizeof(material));
memcpy(out_key16, out_key32, 16);
return true;
}
bool MeshCoreAdapter::deriveDirectSecret(ChannelId channel, uint8_t peer_hash,
uint8_t out_key16[16], uint8_t out_key32[32]) const
{
if (deriveIdentitySecret(peer_hash, out_key16, out_key32))
{
return true;
}
return deriveLegacyDirectSecret(channel, peer_hash, out_key16, out_key32);
(void)channel;
return deriveIdentitySecret(peer_hash, out_key16, out_key32);
}
bool MeshCoreAdapter::tryDecryptPeerPayload(uint8_t src_hash,
@@ -1582,24 +1553,6 @@ bool MeshCoreAdapter::tryDecryptPeerPayload(uint8_t src_hash,
for (size_t i = 0; i < order_len; ++i)
{
{
uint8_t key16[16] = {};
uint8_t key32[32] = {};
if (deriveIdentitySecret(src_hash, key16, key32) &&
tryCandidate(order[i], key16, key32))
{
return true;
}
}
{
uint8_t key16[16] = {};
uint8_t key32[32] = {};
if (deriveLegacyDirectSecret(order[i], src_hash, key16, key32) &&
tryCandidate(order[i], key16, key32))
{
return true;
}
}
{
uint8_t key16[16] = {};
uint8_t key32[32] = {};
@@ -3169,13 +3122,9 @@ MeshActionResult MeshCoreAdapter::sendDirectTextDetailed(ChannelId channel, cons
uint8_t peer_key16[16];
uint8_t peer_key32[32];
if (!deriveDirectSecret(route_decision.primary_secret_channel, peer_hash, peer_key16, peer_key32))
if (!deriveDirectSecret(route_decision.tx_channel, peer_hash, peer_key16, peer_key32))
{
if (!route_decision.allow_secret_fallback ||
!deriveDirectSecret(route_decision.fallback_secret_channel, peer_hash, peer_key16, peer_key32))
{
return MeshActionResult::fail(MeshOperationFailure::PeerKeyMissing);
}
return MeshActionResult::fail(MeshOperationFailure::PeerKeyMissing);
}
constexpr size_t kDirectPlainPrefixSize = 5; // ts(4) + flags(1)
@@ -3352,16 +3301,12 @@ bool MeshCoreAdapter::sendAppData(ChannelId channel, uint32_t portnum,
uint8_t peer_key16[16];
uint8_t peer_key32[32];
if (!deriveDirectSecret(route_decision.primary_secret_channel, peer_hash, peer_key16, peer_key32))
if (!deriveDirectSecret(route_decision.tx_channel, peer_hash, peer_key16, peer_key32))
{
if (!route_decision.allow_secret_fallback ||
!deriveDirectSecret(route_decision.fallback_secret_channel, peer_hash, peer_key16, peer_key32))
{
MESHCORE_LOG("[MESHCORE] TX direct app-data dropped (no peer secret) peer=%08lX port=%u\n",
static_cast<unsigned long>(dest),
static_cast<unsigned>(portnum));
return false;
}
MESHCORE_LOG("[MESHCORE] TX direct app-data dropped (no peer secret) peer=%08lX port=%u\n",
static_cast<unsigned long>(dest),
static_cast<unsigned>(portnum));
return false;
}
(void)peer_key16;