mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-21 10:42:35 +10:00
Merge commit '5548bd3195c18ec9274b2ff8171504acfc2647b3' into agent/include-statusmessage-config
This commit is contained in:
@@ -21,6 +21,10 @@
|
||||
#include "support/MockMeshService.h"
|
||||
#include <cstring>
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
static constexpr NodeNum LOCAL_NODE = 0x0A0A0A0A;
|
||||
static constexpr NodeNum ADMIN_NODE = 0x0B0B0B0B; // authorized admin, sends remote admin to us
|
||||
static constexpr NodeNum QUERIED_NODE = 0x0C0C0C0C; // a remote we send admin requests to
|
||||
@@ -157,6 +161,14 @@ void setUp(void)
|
||||
nodeDB = mockNodeDB;
|
||||
myNodeInfo.my_node_num = LOCAL_NODE;
|
||||
|
||||
#ifdef ARCH_PORTDUINO
|
||||
// The native test harness boots Portduino in simulated mode, and wouldEncryptWithPKC()
|
||||
// hard-disables PKC whenever force_simradio is set. Left true, no outgoing admin request is
|
||||
// ever key-pinned, so the pinning tests below cannot exercise what they are asserting.
|
||||
// Model a real (non-sim) device instead.
|
||||
portduino_config.force_simradio = false;
|
||||
#endif
|
||||
|
||||
config = meshtastic_LocalConfig_init_zero;
|
||||
// A real device always holds a private key; without one perhapsEncode never picks PKC.
|
||||
config.security.private_key.size = 32;
|
||||
|
||||
@@ -159,7 +159,8 @@ void test_E1_perhaps_decode_fuzz(void)
|
||||
|
||||
DecodeState st = perhapsDecode(&p);
|
||||
// Any verdict is fine; the contract is that arbitrary ciphertext never crashes the pipeline.
|
||||
TEST_ASSERT_TRUE(st == DECODE_SUCCESS || st == DECODE_FAILURE || st == DECODE_FATAL);
|
||||
TEST_ASSERT_TRUE(st == DECODE_SUCCESS || st == DECODE_FAILURE || st == DECODE_OPAQUE || st == DECODE_FATAL ||
|
||||
st == DECODE_POLICY_REJECT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,15 @@ class MockRouter : public Router
|
||||
class MockMeshService : public MeshService
|
||||
{
|
||||
public:
|
||||
// No PhoneAPI reader exists in these tests, so packets the receive pipeline forwards to the phone
|
||||
// (MeshService::sendToPhone enqueues pooled copies into toPhoneQueue) would leak at teardown. Drain
|
||||
// the queue like the phone would. This surfaced once sendLocal() began dispatching local packets
|
||||
// through handleReceived() directly rather than via the (mock-overridden) enqueueReceivedMessage().
|
||||
~MockMeshService()
|
||||
{
|
||||
while (meshtastic_MeshPacket *p = getForPhone())
|
||||
releaseToPool(p);
|
||||
}
|
||||
void sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage *m) override
|
||||
{
|
||||
messages_.emplace_back(*m);
|
||||
@@ -334,6 +343,7 @@ const meshtastic_MeshPacket encrypted = {
|
||||
// Initialize mocks and configuration before running each test.
|
||||
void setUp(void)
|
||||
{
|
||||
config = meshtastic_LocalConfig_init_zero;
|
||||
moduleConfig.mqtt =
|
||||
meshtastic_ModuleConfig_MQTTConfig{.enabled = true, .map_reporting_enabled = true, .has_map_report_settings = true};
|
||||
moduleConfig.mqtt.map_report_settings = meshtastic_ModuleConfig_MapReportSettings{
|
||||
@@ -627,6 +637,8 @@ void test_receiveWithoutChannelDownlink(void)
|
||||
// Test receiving an encrypted MeshPacket on the PKI topic.
|
||||
void test_receiveEncryptedPKITopicToUs(void)
|
||||
{
|
||||
config.security.packet_signature_policy =
|
||||
meshtastic_Config_SecurityConfig_PacketSignaturePolicy_PACKET_SIGNATURE_POLICY_STRICT;
|
||||
meshtastic_MeshPacket e = encrypted;
|
||||
e.to = myNodeInfo.my_node_num;
|
||||
|
||||
@@ -718,6 +730,8 @@ static meshtastic_MeshPacket makeDecodedBroadcast()
|
||||
// signing node (audit F3).
|
||||
void test_receiveDropsUnsignedBroadcastFromSigner(void)
|
||||
{
|
||||
config.security.packet_signature_policy =
|
||||
meshtastic_Config_SecurityConfig_PacketSignaturePolicy_PACKET_SIGNATURE_POLICY_BALANCED;
|
||||
mockNodeDB->emptyNode.bitfield |= NODEINFO_BITFIELD_HAS_XEDDSA_SIGNED_MASK;
|
||||
|
||||
const meshtastic_MeshPacket p = makeDecodedBroadcast();
|
||||
@@ -729,6 +743,8 @@ void test_receiveDropsUnsignedBroadcastFromSigner(void)
|
||||
// The same unsigned broadcast from a node never seen signing is accepted.
|
||||
void test_receiveAcceptsUnsignedBroadcastFromNonSigner(void)
|
||||
{
|
||||
config.security.packet_signature_policy =
|
||||
meshtastic_Config_SecurityConfig_PacketSignaturePolicy_PACKET_SIGNATURE_POLICY_BALANCED;
|
||||
const meshtastic_MeshPacket p = makeDecodedBroadcast();
|
||||
unitTest->publish(&p);
|
||||
|
||||
@@ -760,6 +776,8 @@ void test_receiveVerifiesSignedDecodedDownlink(void)
|
||||
// A decoded downlink carrying a signature that fails verification is dropped.
|
||||
void test_receiveDropsBadSignatureOnDecodedDownlink(void)
|
||||
{
|
||||
config.security.packet_signature_policy =
|
||||
meshtastic_Config_SecurityConfig_PacketSignaturePolicy_PACKET_SIGNATURE_POLICY_COMPATIBLE;
|
||||
uint8_t pub[32], priv[32];
|
||||
crypto->generateKeyPair(pub, priv);
|
||||
mockNodeDB->emptyNode.public_key.size = 32;
|
||||
@@ -775,6 +793,53 @@ void test_receiveDropsBadSignatureOnDecodedDownlink(void)
|
||||
|
||||
TEST_ASSERT_TRUE(mockRouter->packets_.empty());
|
||||
}
|
||||
|
||||
void test_receiveCompatibleAcceptsUnsignedBroadcastFromSigner(void)
|
||||
{
|
||||
config.security.packet_signature_policy =
|
||||
meshtastic_Config_SecurityConfig_PacketSignaturePolicy_PACKET_SIGNATURE_POLICY_COMPATIBLE;
|
||||
mockNodeDB->emptyNode.bitfield |= NODEINFO_BITFIELD_HAS_XEDDSA_SIGNED_MASK;
|
||||
|
||||
const meshtastic_MeshPacket p = makeDecodedBroadcast();
|
||||
unitTest->publish(&p);
|
||||
|
||||
TEST_ASSERT_EQUAL(1, mockRouter->packets_.size());
|
||||
}
|
||||
|
||||
void test_receiveStrictDropsUnsignedPortnumsAndUnicast(void)
|
||||
{
|
||||
config.security.packet_signature_policy =
|
||||
meshtastic_Config_SecurityConfig_PacketSignaturePolicy_PACKET_SIGNATURE_POLICY_STRICT;
|
||||
const meshtastic_PortNum ports[] = {
|
||||
meshtastic_PortNum_TEXT_MESSAGE_APP, meshtastic_PortNum_POSITION_APP, meshtastic_PortNum_TELEMETRY_APP,
|
||||
meshtastic_PortNum_NODEINFO_APP, meshtastic_PortNum_WAYPOINT_APP,
|
||||
};
|
||||
for (const auto port : ports) {
|
||||
meshtastic_MeshPacket p = makeDecodedBroadcast();
|
||||
p.decoded.portnum = port;
|
||||
unitTest->publish(&p);
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket unicast = makeDecodedBroadcast();
|
||||
unicast.to = myNodeInfo.my_node_num;
|
||||
unicast.decoded.portnum = meshtastic_PortNum_POSITION_APP;
|
||||
unitTest->publish(&unicast);
|
||||
|
||||
TEST_ASSERT_TRUE(mockRouter->packets_.empty());
|
||||
}
|
||||
|
||||
// A plaintext broker assertion is not evidence that AES-CCM authentication succeeded locally.
|
||||
void test_receiveStrictDoesNotTrustDecodedPkiFlag(void)
|
||||
{
|
||||
config.security.packet_signature_policy =
|
||||
meshtastic_Config_SecurityConfig_PacketSignaturePolicy_PACKET_SIGNATURE_POLICY_STRICT;
|
||||
meshtastic_MeshPacket p = makeDecodedBroadcast();
|
||||
p.to = myNodeInfo.my_node_num;
|
||||
p.pki_encrypted = true;
|
||||
unitTest->publish(&p);
|
||||
|
||||
TEST_ASSERT_TRUE(mockRouter->packets_.empty());
|
||||
}
|
||||
#endif // !(MESHTASTIC_EXCLUDE_PKI) && !(MESHTASTIC_EXCLUDE_XEDDSA)
|
||||
|
||||
// Only the same fields that are transmitted over LoRa should be set in MQTT messages.
|
||||
@@ -1096,6 +1161,9 @@ void setup()
|
||||
RUN_TEST(test_receiveAcceptsUnsignedBroadcastFromNonSigner);
|
||||
RUN_TEST(test_receiveVerifiesSignedDecodedDownlink);
|
||||
RUN_TEST(test_receiveDropsBadSignatureOnDecodedDownlink);
|
||||
RUN_TEST(test_receiveCompatibleAcceptsUnsignedBroadcastFromSigner);
|
||||
RUN_TEST(test_receiveStrictDropsUnsignedPortnumsAndUnicast);
|
||||
RUN_TEST(test_receiveStrictDoesNotTrustDecodedPkiFlag);
|
||||
#endif
|
||||
RUN_TEST(test_receiveIgnoresUnexpectedFields);
|
||||
RUN_TEST(test_receiveIgnoresInvalidHopLimit);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user