13
13
14
14
#define DISTANCE_INVALID (0xFF )
15
15
16
+ // Macros for manipulating signing requirement table
17
+ #define DO_SIGN (node ) (doSign[node>>4 ]&(node%16 ))
18
+ #define SET_SIGN (node ) (doSign[node>>4 ]|=(node%16 ))
19
+ #define CLEAR_SIGN (node ) (doSign[node>>4 ]&=~(node%16 ))
16
20
17
21
// Inline function and macros
18
22
static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
@@ -35,14 +39,17 @@ static inline bool isValidDistance( const uint8_t distance ) {
35
39
36
40
MySensor::MySensor () {
37
41
radio = (MyRFDriver*) new MyRFDriverClass ();
42
+ signer = (MySigningDriver*) new MySigningDriverClass ();
38
43
}
39
44
40
45
41
- void MySensor::begin (void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, uint8_t _parentNodeId) {
46
+ void MySensor::begin (void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, uint8_t _parentNodeId, bool requestSignatures ) {
42
47
Serial.begin (BAUD_RATE);
43
48
repeaterMode = _repeaterMode;
44
49
msgCallback = _msgCallback;
45
50
failedTransmissions = 0 ;
51
+ requireSigning = requestSignatures;
52
+
46
53
// Only gateway should use node id 0
47
54
isGateway = _nodeId == 0 ;
48
55
@@ -55,6 +62,8 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b
55
62
eeprom_read_block ((void *)&nc, (void *)EEPROM_NODE_ID_ADDRESS, sizeof (NodeConfig));
56
63
// Read latest received controller configuration from EEPROM
57
64
eeprom_read_block ((void *)&cc, (void *)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof (ControllerConfig));
65
+ // Read out the signing requirements from EEPROM
66
+ eeprom_read_block ((void *)doSign, (void *)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof (doSign));
58
67
59
68
if (isGateway) {
60
69
nc.distance = 0 ;
@@ -137,6 +146,9 @@ void MySensor::setupNode() {
137
146
// Send presentation for this radio node (attach
138
147
present (NODE_SENSOR_ID, repeaterMode? S_ARDUINO_REPEATER_NODE : S_ARDUINO_NODE);
139
148
149
+ // Notify gateway (and possibly controller) about the signing preferences of this node
150
+ sendRoute (build (msg, nc.nodeId , GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false ).set (requireSigning));
151
+
140
152
// Send a configuration exchange request to controller
141
153
// Node sends parent node. Controller answers with latest node configuration
142
154
// which is picked up in process()
@@ -178,6 +190,19 @@ boolean MySensor::sendRoute(MyMessage &message) {
178
190
return false ;
179
191
}
180
192
193
+ mSetVersion (message, PROTOCOL_VERSION);
194
+
195
+ // If destination is known to require signed messages and we are the sender, sign this message unless it is an ACK or a signing handshake message
196
+ if (DO_SIGN (message.destination ) && message.sender == nc.nodeId && !mGetAck (message) && mGetLength (msg) &&
197
+ (mGetCommand (message) != C_INTERNAL || (message.type != I_GET_NONCE && message.type != I_GET_NONCE_RESPONSE && message.type != I_REQUEST_SIGNING))) {
198
+ if (!sign (message)) {
199
+ debug (PSTR (" Message signing failed\n " ));
200
+ return false ;
201
+ }
202
+ // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed,
203
+ // or signature will become invalid and the message rejected by the receiver
204
+ } else mSetSigned (message, 0 ); // Message is not supposed to be signed, make sure it is marked unsigned
205
+
181
206
if (dest == GATEWAY_ADDRESS || !repeaterMode) {
182
207
// If destination is the gateway or if we aren't a repeater, let
183
208
// our parent take care of the message
@@ -240,14 +265,13 @@ boolean MySensor::sendRoute(MyMessage &message) {
240
265
}
241
266
242
267
boolean MySensor::sendWrite (uint8_t to, MyMessage &message) {
243
- uint8_t length = mGetLength (message);
268
+ uint8_t length = mGetSigned (message) ? MAX_MESSAGE_LENGTH : mGetLength (message);
244
269
message.last = nc.nodeId ;
245
- mSetVersion (message, PROTOCOL_VERSION);
246
270
bool ok = radio->send (to, &message, min (MAX_MESSAGE_LENGTH, HEADER_SIZE + length));
247
271
248
- debug (PSTR (" send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,st=%s:%s\n " ),
272
+ debug (PSTR (" send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d, st=%s:%s\n " ),
249
273
message.sender ,message.last , to, message.destination , message.sensor , mGetCommand (message), message.type ,
250
- mGetPayloadType (message), mGetLength (message), to==BROADCAST_ADDRESS ? " bc" : (ok ? " ok" :" fail" ), message.getString (convBuf));
274
+ mGetPayloadType (message), mGetLength (message), mGetSigned (message), to==BROADCAST_ADDRESS ? " bc" : (ok ? " ok" :" fail" ), message.getString (convBuf));
251
275
252
276
return ok;
253
277
}
@@ -290,12 +314,26 @@ boolean MySensor::process() {
290
314
if (!radio->available (&to))
291
315
return false ;
292
316
317
+ (void )signer->checkTimer (); // Manage signing timeout
318
+
293
319
uint8_t len = radio->receive ((uint8_t *)&msg);
294
320
321
+ // Before processing message, reject unsigned messages if signing is required and check signature (if it is signed and addressed to us)
322
+ // Note that we do not care at all about any signature found if we do not require signing
323
+ if (requireSigning && msg.destination == nc.nodeId && mGetLength (msg) &&
324
+ (mGetCommand (msg) != C_INTERNAL || (msg.type != I_GET_NONCE_RESPONSE && msg.type != I_GET_NONCE && msg.type != I_REQUEST_SIGNING))) {
325
+ if (!mGetSigned (msg)) return false ; // Received an unsigned message but we do require signing. This message gets nowhere!
326
+ else if (!signer->verifyMsg (msg)) {
327
+ debug (PSTR (" Message verification failed\n " ));
328
+ return false ; // This signed message has been tampered with!
329
+ }
330
+ }
331
+
295
332
// Add string termination, good if we later would want to print it.
296
333
msg.data [mGetLength (msg)] = ' \0 ' ;
297
- debug (PSTR (" read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d:%s\n " ),
298
- msg.sender , msg.last , msg.destination , msg.sensor , mGetCommand (msg), msg.type , mGetPayloadType (msg), mGetLength (msg), msg.getString (convBuf));
334
+ debug (PSTR (" read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n " ),
335
+ msg.sender , msg.last , msg.destination , msg.sensor , mGetCommand (msg), msg.type , mGetPayloadType (msg), mGetLength (msg), mGetSigned (msg), msg.getString (convBuf));
336
+ mSetSigned (msg,0 ); // Clear the sign-flag now as verification (and debug printing) is completed
299
337
300
338
if (!(mGetVersion (msg) == PROTOCOL_VERSION)) {
301
339
debug (PSTR (" version: %d\n " ),mGetVersion (msg));
@@ -349,6 +387,32 @@ boolean MySensor::process() {
349
387
}
350
388
}
351
389
return false ;
390
+ } else if (type == I_GET_NONCE) {
391
+ if (signer->getNonce (msg)) {
392
+ sendRoute (build (msg, nc.nodeId , GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_GET_NONCE_RESPONSE, false ));
393
+ } else {
394
+ return false ;
395
+ }
396
+ } else if (type == I_REQUEST_SIGNING) {
397
+ if (msg.getBool ()) {
398
+ // We received an indicator that the sender require us to sign all messages we send to it
399
+ SET_SIGN (msg.sender );
400
+ } else {
401
+ // We received an indicator that the sender does not require us to sign all messages we send to it
402
+ CLEAR_SIGN (msg.sender );
403
+ }
404
+ // Save updated table
405
+ eeprom_write_block ((void *)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, (void *)doSign, sizeof (doSign));
406
+
407
+ // Inform sender about our preference if we are a gateway, but only require signing if the sender required signing
408
+ // We do not currently want a gateway to require signing from all nodes in a network just because it wants one node
409
+ // to sign it's messages
410
+ if (isGateway) {
411
+ if (requireSigning)
412
+ sendRoute (build (msg, nc.nodeId , msg.sender , NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false ).set (requireSigning));
413
+ else
414
+ sendRoute (build (msg, nc.nodeId , msg.sender , NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false ).set (false ));
415
+ }
352
416
} else if (sender == GATEWAY_ADDRESS) {
353
417
bool isMetric;
354
418
@@ -543,6 +607,27 @@ int8_t MySensor::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, ui
543
607
return retVal;
544
608
}
545
609
610
+ bool MySensor::sign (MyMessage &message) {
611
+ MyMessage msgNonce;
612
+ if (!sendRoute (build (msgNonce, nc.nodeId , message.destination , message.sensor , C_INTERNAL, I_GET_NONCE, false ).set (" " ))) {
613
+ return false ;
614
+ } else {
615
+ // We have to wait for the nonce to arrive before we can sign our original message
616
+ // Other messages could come in-between. We trust process() takes care of them
617
+ unsigned long enter = millis ();
618
+ while (millis () - enter < 5000 ) {
619
+ if (process ()) {
620
+ if (getLastMessage ().type == I_GET_NONCE_RESPONSE) {
621
+ // Proceed with signing if nonce has been received
622
+ if (signer->putNonce (getLastMessage ()) && signer->signMsg (message)) return true ;
623
+ break ;
624
+ }
625
+ }
626
+ }
627
+ }
628
+ return false ;
629
+ }
630
+
546
631
#ifdef DEBUG
547
632
void MySensor::debugPrint (const char *fmt, ... ) {
548
633
char fmtBuffer[300 ];
0 commit comments