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