diff --git a/MyConfig.h b/MyConfig.h index 214069b..1fc059d 100644 --- a/MyConfig.h +++ b/MyConfig.h @@ -365,6 +365,15 @@ */ //#define MY_SIGNING_REQUEST_SIGNATURES +/** + * @def MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL + * @brief Enable this to have gateway require all nodes in the network to sign messages sent to it. @ref MY_SIGNING_REQUEST_SIGNATURES must also be set. + * + * Use this for maximum security, but be aware that every single node will have to be personalized before they can be used. + * Note that if this is enabled, and whitelisting is also enabled, whitelisting will also be in effect for all nodes. + */ +//#define MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL + /** * @def MY_VERIFICATION_TIMEOUT_MS * @brief Define a suitable timeout for a signature verification session @@ -828,6 +837,7 @@ #define MY_SIGNING_ATSHA204 #define MY_SIGNING_SOFT #define MY_SIGNING_REQUEST_SIGNATURES +#define MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} #define MY_IS_RFM69HW #define MY_PARENT_NODE_IS_STATIC diff --git a/core/MySigning.cpp b/core/MySigning.cpp index 738eae1..76ed69e 100644 --- a/core/MySigning.cpp +++ b/core/MySigning.cpp @@ -33,6 +33,9 @@ #if defined(MY_SIGNING_REQUEST_SIGNATURES) && (!defined(MY_SIGNING_ATSHA204) && !defined(MY_SIGNING_SOFT)) #error You have to pick either MY_SIGNING_ATSHA204 or MY_SIGNING_SOFT in order to require signatures! #endif +#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) && !defined(MY_SIGNING_REQUEST_SIGNATURES) +#error You have to require signatures if you want to require signatures from all (also enable MY_SIGNING_REQUEST_SIGNATURES in your gateway) +#endif #ifdef MY_SIGNING_FEATURE uint8_t _doSign[32]; // Bitfield indicating which sensors require signed communication uint8_t _doWhitelist[32]; // Bitfield indicating which sensors require serial salted signatures @@ -231,20 +234,26 @@ bool signerProcessInternal(MyMessage &msg) { sizeof(_doWhitelist)); // Inform sender about our preference if we are a gateway, but only require signing if the sender - // required signing + // required signing unless we explicitly configure it to // We do not want a gateway to require signing from all nodes in a network just because it wants one node - // to sign it's messages + // to sign it's messages unless we explicitly configure it to #if defined(MY_GATEWAY_FEATURE) prepareSigningPresentation(msg, sender); #if defined(MY_SIGNING_REQUEST_SIGNATURES) if (DO_SIGN(sender)) { msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; } +#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) + msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES; +#endif #endif #if defined(MY_SIGNING_NODE_WHITELISTING) if (DO_WHITELIST(sender)) { msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING; } +#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) + msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING; +#endif #endif if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) { SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender); @@ -356,9 +365,13 @@ bool signerVerifyMsg(MyMessage &msg) { // (if it is signed and addressed to us) // Note that we do not care at all about any signature found if we do not require signing #if defined(MY_SIGNING_FEATURE) && defined(MY_SIGNING_REQUEST_SIGNATURES) - // If we are a node, or we are a gateway and the sender require signatures + // If we are a node, or we are a gateway and the sender require signatures (or just a strict gw) // and we are the destination... +#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) + if (msg.destination == _nc.nodeId) { +#else if ((!MY_IS_GATEWAY || DO_SIGN(msg.sender)) && msg.destination == _nc.nodeId) { +#endif // Internal messages of certain types are not verified if (skipSign(msg)) { verificationResult = true; diff --git a/core/MySigning.h b/core/MySigning.h index 1353353..761f3e3 100644 --- a/core/MySigning.h +++ b/core/MySigning.h @@ -156,7 +156,8 @@ * This has to be set by at least one of the node in a "pair" or nobody will actually start calculating a signature for a message. * Just set the flag @ref MY_SIGNING_REQUEST_SIGNATURES and the node will inform the gateway that it expects the gateway to sign all * messages sent to the node. If this is set in a gateway, it will @b NOT force all nodes to sign messages to it. It will only require - * signatures from nodes that in turn require signatures.
+ * signatures from nodes that in turn require signatures. If it is desired that the gateway should require signatures from all nodes, + * @ref MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL can be set in the gateway sketch.
* If you want to have two nodes communicate securely directly with each other, the nodes that require signatures must send a presentation * message to all nodes it expect signed messages from (only the gateway is informed automatically). See @ref signerPresentation().
* A node can have three "states" with respect to signing: @@ -267,14 +268,15 @@ * * If a node does require signing, any unsigned message sent to the node will be rejected.
* This also applies to the gateway. However, the difference is that the gateway will only require signed messages from nodes it knows in turn - * require signed messages.
+ * require signed messages (unless @ref MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL is set).
* A node can also inform a different node that it expects to receive signed messages from it. This is done by transmitting an internal message * of type @ref I_SIGNING_PRESENTATION and provide flags as payload that inform the receiver of the signing preferences of the sender.
* All nodes and gateways in a network maintain a table where the signing preferences of all nodes are stored. This is also stored in EEPROM so * if the gateway reboots, the nodes does not have to retransmit a signing presentation to the gateway for the gateway to realize that the node * expect signed messages.
* Also, the nodes that do not require signed messages will also inform gateway of this, so if you reprogram a node to stop require signing, - * the gateway will adhere to this as soon as the new node has presented itself to the gateway. + * the gateway will adhere to this as soon as the new node has presented itself to the gateway. Note however, that if the gateway sets + * @ref MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL a node that does not support signing will be unable to send any data to the gateway. * * The following sequence diagram illustrate how messages are passed in a MySensors network with respect to signing: * @image html MySigning/signingsequence.png @@ -429,7 +431,7 @@ * ... * @endcode * - * The gateway needs to configured with a whitelist (and it have to have an entry for all nodes that send and/or require signed messages):
+ * The gateway needs to be configured with a whitelist (and it has to have an entry for all nodes that send and/or require signed messages):
* @code{.cpp} * #define MY_SIGNING_SOFT * #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 diff --git a/keywords.txt b/keywords.txt index 5d8da56..1e4617b 100644 --- a/keywords.txt +++ b/keywords.txt @@ -123,6 +123,7 @@ MY_GATEWAY_MQTT_CLIENT LITERAL1 MY_DISABLE_REMOTE_RESET LITERAL1 MY_RS485_DE_PIN LITERAL1 MY_SIGNING_REQUEST_SIGNATURES LITERAL1 +MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL LITERAL1 MY_SMART_SLEEP_WAIT_DURATION LITERAL1 MY_NODE_LOCK_FEATURE LITERAL1 MY_NODE_UNLOCK_PIN LITERAL1