Signing whitelisting rewritten

Whitelisting is now supported by all nodes that support signing,
while only nodes that define a whitelist with
MY_SIGNING_NODE_WHITELISTING will check signatures against a whitelist.
This allows a single node in a network to have a whitelist without require
all nodes that communicate it to be configured for whitelisting. The node
will publish its whitelisting preferences to the gateway together with its
signing preferences. In other words; whitelisting is now working as signing
requirements does.
A node that use whitelisting will reject any message (signed or unsigned)
from nodes not present in its whitelist.

Fixes #279
This commit is contained in:
Patrick Fallberg
2016-01-12 08:41:55 +01:00
parent 5ecf146f15
commit ff015dd373
6 changed files with 149 additions and 83 deletions
+3 -3
View File
@@ -163,9 +163,9 @@ typedef enum {
I_INCLUSION_MODE, I_CONFIG, I_FIND_PARENT, I_FIND_PARENT_RESPONSE,
I_LOG_MESSAGE, I_CHILDREN, I_SKETCH_NAME, I_SKETCH_VERSION,
I_REBOOT, I_GATEWAY_READY,
I_REQUEST_SIGNING, /*!< Indicates sender require signed messages (bool param) */
I_NONCE_REQUEST, /*!< Request for a nonce */
I_NONCE_RESPONSE, /*!< Payload is nonce data */
I_SIGNING_PRESENTATION, /*!< Provides signing related preferences (first byte is preference version) */
I_NONCE_REQUEST, /*!< Request for a nonce */
I_NONCE_RESPONSE, /*!< Payload is nonce data */
I_HEARTBEAT, I_PRESENTATION, I_DISCOVER, I_DISCOVER_RESPONSE, I_HEARTBEAT_RESPONSE
} mysensor_internal;
+2 -1
View File
@@ -52,7 +52,8 @@
#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS+2)
#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS+2)
#define EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2)
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS+32) // First free address for sketch static configuration
#define EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS (EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS+32)
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS+32) // First free address for sketch static configuration
// This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data).
#define GATEWAY_ADDRESS ((uint8_t)0)
+86 -39
View File
@@ -20,6 +20,10 @@
#include "MySigning.h"
#include "drivers/ATSHA204/sha256.h"
#define SIGNING_PRESENTATION_VERSION_1 1
#define SIGNING_PRESENTATION_REQUIRE_SIGNATURES (1 << 0)
#define SIGNING_PRESENTATION_REQUIRE_WHITELISTING (1 << 1)
#if defined(MY_DEBUG_VERBOSE)
#define SIGN_DEBUG(x,...) debug(x, ##__VA_ARGS__)
#else
@@ -30,8 +34,9 @@
#error You have to pick either MY_SIGNING_ATSHA204 or MY_SIGNING_SOFT in order to require signatures!
#endif
#ifdef MY_SIGNING_FEATURE
uint8_t _doSign[32]; // Bitfield indicating which sensors require signed communication
MyMessage _msgSign; // Buffer for message to sign.
uint8_t _doSign[32]; // Bitfield indicating which sensors require signed communication
uint8_t _doWhitelist[32]; // Bitfield indicating which sensors require serial salted signatures
MyMessage _msgSign; // Buffer for message to sign.
uint8_t _signingNonceStatus;
// Status when waiting for signing nonce in signerProcessInternal
@@ -72,7 +77,7 @@ static bool skipSign(MyMessage &msg) {
SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type);
return true;
} else if (mGetCommand(msg) == C_INTERNAL &&
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE || msg.type == I_REQUEST_SIGNING ||
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE || msg.type == I_SIGNING_PRESENTATION ||
msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
msg.type == I_FIND_PARENT || msg.type == I_FIND_PARENT_RESPONSE ||
msg.type == I_HEARTBEAT || msg.type == I_HEARTBEAT_RESPONSE)) {
@@ -89,10 +94,24 @@ static bool skipSign(MyMessage &msg) {
}
#endif // MY_SIGNING_FEATURE
// Helper to prepare a signing presentation message
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) {
// Only supports version 1 for now
build(msg, _nc.nodeId, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION, false).set("");
mSetLength(msg, 2);
msg.data[0] = SIGNING_PRESENTATION_VERSION_1;
msg.data[1] = 0;
}
void signerInit(void) {
#if defined(MY_SIGNING_FEATURE)
// Read out the signing requirements from EEPROM
hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(_doSign));
hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
sizeof(_doSign));
// Read out the whitelist requirements from EEPROM
hwReadConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
sizeof(_doWhitelist));
#if defined(MY_SIGNING_SOFT)
// initialize pseudo-RNG
@@ -102,21 +121,23 @@ void signerInit(void) {
}
void signerPresentation(MyMessage &msg) {
#ifdef MY_SIGNING_FEATURE
prepareSigningPresentation(msg, GATEWAY_ADDRESS);
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
_sendRoute(build(msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID,
C_INTERNAL, I_REQUEST_SIGNING, false).set(true));
// If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages
SIGN_DEBUG(PSTR("Request for signing sent, waiting for GW response...\n"));
wait(2000);
#else
_sendRoute(build(msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID,
C_INTERNAL, I_REQUEST_SIGNING, false).set(false));
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
SIGN_DEBUG(PSTR("Signing required\n"));
#endif
#else
// Ww do not support signing, make sure gateway knows this
_sendRoute(build(msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID,
C_INTERNAL, I_REQUEST_SIGNING, false).set(false));
#if defined(MY_SIGNING_NODE_WHITELISTING)
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
SIGN_DEBUG(PSTR("Whitelisting required\n"));
#endif
_sendRoute(msg);
#if defined(MY_SIGNING_FEATURE)
// If we do support signing, wait for the gateway to tell us how it prefer us to transmit our messages
SIGN_DEBUG(PSTR("Waiting for GW to send signing preferences...\n"));
wait(2000);
#endif
}
@@ -125,12 +146,12 @@ bool signerProcessInternal(MyMessage &msg) {
#if !defined(MY_SIGNING_FEATURE) && defined(MY_GATEWAY_FEATURE)
// If we act as gateway and do not have the signing feature and receive a signing request we still
// need to do make sure the requester does not believe the gateway still require signatures
if (msg.type == I_REQUEST_SIGNING) {
_sendRoute(build(msg, _nc.nodeId, msg.sender, NODE_SENSOR_ID,
C_INTERNAL, I_REQUEST_SIGNING, false).set((uint8_t)false));
if (msg.type == I_SIGNING_PRESENTATION) {
prepareSigningPresentation(msg, msg.sender);
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
msg.sender);
return true; // No need to further process I_REQUEST_SIGNING in this case
_sendRoute(msg);
return true; // No need to further process I_SIGNING_PRESENTATION in this case
}
#elif defined(MY_SIGNING_FEATURE)
if (msg.type == I_NONCE_REQUEST) {
@@ -147,8 +168,14 @@ bool signerProcessInternal(MyMessage &msg) {
SIGN_DEBUG(PSTR("Failed to generate nonce!\n"));
}
return true; // No need to further process I_NONCE_REQUEST
} else if (msg.type == I_REQUEST_SIGNING) {
if (msg.getBool()) {
} else if (msg.type == I_SIGNING_PRESENTATION) {
if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]);
return true; // Just drop this presentation message
}
// We only handle version 1 here...
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
// We received an indicator that the sender require us to sign all messages we send to it
SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender);
SET_SIGN(msg.sender);
@@ -157,32 +184,52 @@ bool signerProcessInternal(MyMessage &msg) {
SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender);
CLEAR_SIGN(msg.sender);
}
// Save updated table
hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(_doSign));
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
// We received an indicator that the sender require us to salt signatures with serial
SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender);
SET_WHITELIST(msg.sender);
} else {
// We received an indicator that the sender does not require us to sign all messages we send to it
SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender);
CLEAR_WHITELIST(msg.sender);
}
// Save updated tables
hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
sizeof(_doSign));
hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
sizeof(_doWhitelist));
// Inform sender about our preference if we are a gateway, but only require signing if the sender
// required signing
// 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
#if defined (MY_GATEWAY_FEATURE)
#ifdef MY_SIGNING_REQUEST_SIGNATURES
#if defined(MY_GATEWAY_FEATURE)
prepareSigningPresentation(msg, msg.sender);
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
if (DO_SIGN(msg.sender)) {
_sendRoute(build(msg, _nc.nodeId, msg.sender, NODE_SENSOR_ID,
C_INTERNAL, I_REQUEST_SIGNING, false).set((uint8_t)true));
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), msg.sender);
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
}
else {
_sendRoute(build(msg, _nc.nodeId, msg.sender, NODE_SENSOR_ID,
C_INTERNAL, I_REQUEST_SIGNING, false).set((uint8_t)false));
#endif
#if defined(MY_SIGNING_NODE_WHITELISTING)
if (DO_WHITELIST(msg.sender)) {
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
}
#endif
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), msg.sender);
} else {
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), msg.sender);
}
#else // no MY_SIGNING_REQUEST_SIGNATURES
_sendRoute(build(msg, _nc.nodeId, msg.sender, NODE_SENSOR_ID,
C_INTERNAL, I_REQUEST_SIGNING, false).set((uint8_t)false));
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), msg.sender);
#endif
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), msg.sender);
} else {
SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), msg.sender);
}
_sendRoute(msg);
#endif // MY_GATEWAY_FEATURE
return true; // No need to further process I_REQUEST_SIGNING
return true; // No need to further process I_SIGNING_PRESENTATION
} else if (msg.type == I_NONCE_RESPONSE) {
// Proceed with signing if nonce has been received
SIGN_DEBUG(PSTR("Nonce received from %d. Proceeding with signing...\n"), msg.sender);
+25 -19
View File
@@ -251,9 +251,9 @@
* 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.<br>
* 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_REQUEST_SIGNING and provide a boolean for payload, set to @c true.<br>
* of type @ref I_SIGNING_PRESENTATION and provide flags as payload that inform the receiver of the signing preferences of the sender.<br>
* 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 request to the gateway for the gateway to realize that the node
* 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.<br>
* 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.
@@ -294,7 +294,6 @@
* The whitelist is stored on the node that require signatures. When a received message is verified, the serial of the sender is looked up in a
* list stored on the receiving node, and the corresponding serial stored in the list for that sender is then included in the signature verification
* process. The list is stored as the value of the flag that enables whitelisting, @ref MY_SIGNING_NODE_WHITELISTING.<br>
* For whitelisting to work, the sending node also needs to have whitelisting enabled.<br>
*
* Whitelisting is achieved by 'salting' the signature with some node-unique information known to the receiver. In the case of ATSHA204A this is the
* unique serial number programmed into the circuit. This unique number is never transmitted over the air in clear text, so Eve will not be able to
@@ -303,8 +302,8 @@
* the originating NodeId of the signed message and do the corresponding calculation with the serial it has stored in it's whitelist if it finds a
* matching entry in it's whitelist.
*
* Whitelisting is an optional alternative because it adds some code which might not be desirable for every user. So if you want the ability to
* provide and use whitelists, as well as transmitting to a node with a whitelist, you need to enable @ref MY_SIGNING_NODE_WHITELISTING.<br>
* Whitelisting is an optional alternative because it adds some code and configuration options which might not be desirable for every user. So if
* you want the ability to use whitelists, you need to enable @ref MY_SIGNING_NODE_WHITELISTING.<br>
* The whitelist is provided as value of the flag that enable it as follows (example is a node that require signing as well):
* @code{.cpp}
* #define MY_SIGNING_ATSHA204
@@ -314,10 +313,10 @@
* ...
* @endcode
* In this example, there are two nodes in the whitelist; the gateway, and a separate node that communicates directly with this node (with signed
* messages).
* messages). You do not need to do anything special for the sending nodes, apart from making sure they support signing.
*
* The "soft" backend of course also support whitelisting. However, since it does not contain a unique identifier, you have to provide an additional
* setting (@ref MY_SIGNING_SOFT_SERIAL) when you enable whitelisting as illustrated in this example:
* setting (@ref MY_SIGNING_SOFT_SERIAL) for all nodes that communicate to a node which has whitelisting enabled. Example:
* @code{.cpp}
* #define MY_SIGNING_SOFT
* #define MY_SIGNING_SOFT_SERIAL 0x12,0x34,0x56,0x78,0x90,0x12,0x34,0x56,0x78
@@ -329,16 +328,16 @@
* ...
* @endcode
*
* For a node that should transmit whitelisted messages but not receive whitelisted messages, you can set the whitelist flag as follows:
* For a node that should transmit whitelisted messages but not receive whitelisted messages, you do not need any special configurations except to define
* a unique serial if using the software backend:
* @code{.cpp}
* #define MY_SIGNING_NODE_WHITELISTING {}
* #define MY_SIGNING_SOFT
* #define MY_SIGNING_SOFT_SERIAL 0x12,0x34,0x56,0x78,0x90,0x12,0x34,0x56,0x78
* #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
* #define MY_SIGNING_SOFT_HMAC_KEY 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,0x11,0x22
* @endcode
* Remember that for the software backend, you still need to set @ref MY_SIGNING_SOFT_SERIAL (a default is set in MyConfig.h if you do not provide one
* in your sketch.
*
* It is important to emphasize that you do not have to provide a whitelist that has entries for all nodes that transmit signed messages to the node
* in question. You only need to have entries for the nodes that in turn have enabled @ref MY_SIGNING_NODE_WHITELISTING. Nodes that does not have
* this option enabled can still transmit "regular" signed messages as long as they do not match a NodeId in the receivers whitelist.
* Remember that you always need to select a signing backend for all nodes that communicate to a node that require whitelisting.
* Also, note that a node that use whitelisting will not accept messages from nodes that are not present in it's whitelist.
*
* @section MySigningtechnical The technical stuff
*
@@ -363,7 +362,7 @@
* Exactly how this is done can be reviewd in the source for the ATSHA204SOFT backend and the ATSHA204A
* <a href="http://www.atmel.com/Images/Atmel-8885-CryptoAuth-ATSHA204A-Datasheet.pdf">datasheet</a>.
* In the MySensors protocol, the following internal messagetypes handles signature requirements and nonce requests:<br>
* @ref I_REQUEST_SIGNING <br>
* @ref I_SIGNING_PRESENTATION <br>
* @ref I_NONCE_REQUEST <br>
* @ref I_NONCE_RESPONSE <br>
*
@@ -409,14 +408,13 @@
* Nor can it be changed in order to do it in the future. You can also use whitelisting to revoke your lost node.<br>
* This is an unlikely use case because there really is no reason to sign sensor values. If you for some reason want to obfuscate sensor data,
* encryption is a better alternative.<br>
* Configuration example for a motion sensor with whitelisting (it has to have the gateway whitelisted since the gateway will send signed messages to the node):<br>
* Configuration example for a motion sensor:<br>
* @code{.cpp}
* #define MY_SIGNING_SOFT
* #define MY_SIGNING_SOFT_SERIAL 0x12,0x34,0x56,0x78,0x90,0x12,0x34,0x56,0x78
* #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
* #define MY_SIGNING_SOFT_HMAC_KEY 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,0x11,0x22
* #define MY_SIGNING_REQUEST_SIGNATURES
* #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88}}}
* #include <MySensor.h>
* ...
* @endcode
@@ -441,10 +439,10 @@
* Configuration example for the keyfob (keyfob will only transmit to another node and not receive anything):<br>
* @code{.cpp}
* #define MY_SIGNING_ATSHA204
* #define MY_SIGNING_NODE_WHITELISTING {}
* #include <MySensor.h>
* ...
* @endcode
*
* Configuration example for the door controller node (should require signing from anyone who wants to control it):<br>
* @code{.cpp}
* #define MY_SIGNING_SOFT
@@ -487,6 +485,14 @@ typedef struct {
/** @brief Helper macro to determine the number of elements in a array */
#define NUM_OF(x) (sizeof(x)/sizeof(x[0]))
/** @brief Helper macro to determine if node require serial salted signatures */
#define DO_WHITELIST(node) (~_doWhitelist[node>>3]&(1<<node%8))
/** @brief Helper macro to set that node require serial salted signatures */
#define SET_WHITELIST(node) (_doWhitelist[node>>3]&=~(1<<node%8))
/** @brief Helper macro to set that node does not require serial salted signatures */
#define CLEAR_WHITELIST(node) (_doWhitelist[node>>3]|=(1<<node%8))
/**
* @brief Initializes signing infrastructure and associated backend.
*
+15 -9
View File
@@ -38,6 +38,7 @@ uint8_t _signing_current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1];
uint8_t _signing_temp_message[SHA_MSG_SIZE];
uint8_t _singning_rx_buffer[SHA204_RSP_SIZE_MAX];
uint8_t _singning_tx_buffer[SHA204_CMD_SIZE_MAX];
extern uint8_t _doWhitelist[32];
#ifdef MY_SIGNING_NODE_WHITELISTING
const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING;
@@ -154,14 +155,14 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated
signerCalculateSignature(msg);
#ifdef MY_SIGNING_NODE_WHITELISTING
// Salt the signature with the senders nodeId and the unique serial of the ATSHA device
memcpy(_signing_current_nonce, &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed
_signing_current_nonce[32] = msg.sender;
atsha204.getSerialNumber(&_signing_current_nonce[33]);
(void)signerSha256(_signing_current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
#endif
if (DO_WHITELIST(msg.destination)) {
// Salt the signature with the senders nodeId and the unique serial of the ATSHA device
memcpy(_signing_current_nonce, &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed
_signing_current_nonce[32] = msg.sender;
atsha204.getSerialNumber(&_signing_current_nonce[33]);
(void)signerSha256(_signing_current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
}
// Overwrite the first byte in the signature with the signing identifier
_singning_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
@@ -195,7 +196,8 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
#ifdef MY_SIGNING_NODE_WHITELISTING
// Look up the senders nodeId in our whitelist and salt the signature with that data
for (int j=0; j < NUM_OF(_signing_whitelist); j++) {
size_t j;
for (j=0; j < NUM_OF(_signing_whitelist); j++) {
if (_signing_whitelist[j].nodeId == msg.sender) {
DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0);
memcpy(_signing_current_nonce, &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed
@@ -205,6 +207,10 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
break;
}
}
if (j == NUM_OF(_signing_whitelist)) {
DEBUG_SIGNING_PRINTBUF(F("Sender not found in whitelist, message rejected!"), NULL, 0);
return false;
}
#endif
// Overwrite the first byte in the signature with the signing identifier
@@ -42,9 +42,10 @@ uint8_t _signing_current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH];
uint8_t _signing_temp_message[32];
static uint8_t _signing_hmac_key[32] = { MY_SIGNING_SOFT_HMAC_KEY };
uint8_t _signing_hmac[32];
extern uint8_t _doWhitelist[32];
const uint8_t _signing_node_serial_info[SHA204_SERIAL_SZ] = {MY_SIGNING_SOFT_SERIAL};
#ifdef MY_SIGNING_NODE_WHITELISTING
const uint8_t _signing_node_serial_info[SHA204_SERIAL_SZ] = {MY_SIGNING_SOFT_SERIAL};
const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING;
#endif
@@ -154,16 +155,16 @@ bool signerAtsha204SoftSignMsg(MyMessage &msg) {
mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated
signerCalculateSignature(msg);
#ifdef MY_SIGNING_NODE_WHITELISTING
// Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided
_signing_sha256.init();
for (int i=0; i<32; i++) _signing_sha256.write(_signing_hmac[i]);
_signing_sha256.write(msg.sender);
for (int i=0; i<SHA204_SERIAL_SZ; i++) _signing_sha256.write(_signing_node_serial_info[i]);
memcpy(_signing_hmac, _signing_sha256.result(), 32);
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
#endif
if (DO_WHITELIST(msg.destination)) {
// Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided
_signing_sha256.init();
for (int i=0; i<32; i++) _signing_sha256.write(_signing_hmac[i]);
_signing_sha256.write(msg.sender);
for (int i=0; i<SHA204_SERIAL_SZ; i++) _signing_sha256.write(_signing_node_serial_info[i]);
memcpy(_signing_hmac, _signing_sha256.result(), 32);
DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32);
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
}
// Overwrite the first byte in the signature with the signing identifier
_signing_hmac[0] = SIGNING_IDENTIFIER;
@@ -198,7 +199,8 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
#ifdef MY_SIGNING_NODE_WHITELISTING
// Look up the senders nodeId in our whitelist and salt the signature with that data
for (int j=0; j < NUM_OF(_signing_whitelist); j++) {
size_t j;
for (j=0; j < NUM_OF(_signing_whitelist); j++) {
if (_signing_whitelist[j].nodeId == msg.sender) {
DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0);
_signing_sha256.init();
@@ -210,6 +212,10 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
break;
}
}
if (j == NUM_OF(_signing_whitelist)) {
DEBUG_SIGNING_PRINTBUF(F("Sender not found in whitelist, message rejected!"), NULL, 0);
return false;
}
#endif
// Overwrite the first byte in the signature with the signing identifier